nidapeng
2024-03-08 a127d6f905fa2a3a47e2dd872ca24db70c158dd2
更改头部
已添加58个文件
已修改27个文件
3080 ■■■■ 文件已修改
admin/package-lock.json 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/App.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/avatar/man.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/avatar/woman.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/company/apply.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/company/change_apply.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/company/dipatch_unit.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/company/settle.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/company/tax.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/plat/apply_check.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/plat/change_apply_check.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/plat/company_add.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/plat/settle_check.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/icons/plat/tax_check.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/Galanz@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/Samsung@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/ar_open@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/background_defult.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/banner_defult.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_bingxiang@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_dianshi@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_jinshui@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_kaoxiang@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_kongtiao@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_qita@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_reshuiqi@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_xiwanji@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_xiyiji @2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/category/ic_yanzao@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/ic_copy@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/ic_delete@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/ic_img@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/ic_pk@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/ic_search@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/login_bg.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/login_img.jpg 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/login_img.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/man.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/pk_defult.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/top_ic_bolang@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/top_ic_chilun@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/woman.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/images/zan.png 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/alertstyle.scss 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/element-variables.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/lib.css 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/style.scss 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/variables.scss 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/base/BaseOpera.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/base/BaseTable.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/DepartmentSelect.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/GlobalAlertWindow.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/GlobalQuestionWindow.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/GlobalRigthWindow.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/GlobalWindow.vue 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/Header.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/ImportButton.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/ImportWindow.vue 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/Light.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/Menu.vue 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/MenuSelect.vue 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/Pagination.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/PositionSelect.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/RichEditor.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/SearchFormCollapse.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/ShowRich.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/Tree.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/TreeSelect.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/UploadAvatarImage.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/UploadAvatarVideo.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/UploadFile.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/UploadFileCommon.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/UploadImage.vue 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/myImage.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/tagsview.vue 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/upload.vue 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/layouts/AppLayout.vue 119 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/layouts/TableLayout.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/layouts/TableLayout1.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/plugins/messagebox.js 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/store/index.js 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/vue.config.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/java/com/doumee/task/ScheduleTool.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_web/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/package-lock.json
@@ -1819,6 +1819,63 @@
          "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
          "dev": true
        },
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "ssri": {
          "version": "8.0.1",
          "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-8.0.1.tgz?cache=0&sync_timestamp=1617826515595&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-8.0.1.tgz",
@@ -1826,6 +1883,28 @@
          "dev": true,
          "requires": {
            "minipass": "^3.1.1"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        },
        "vue-loader-v16": {
          "version": "npm:vue-loader@16.8.3",
          "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
          "dev": true,
          "optional": true,
          "requires": {
            "chalk": "^4.1.0",
            "hash-sum": "^2.0.0",
            "loader-utils": "^2.0.0"
          }
        }
      }
@@ -13486,87 +13565,6 @@
          "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
          "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
          "dev": true
        }
      }
    },
    "vue-loader-v16": {
      "version": "npm:vue-loader@16.8.3",
      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
      "dev": true,
      "optional": true,
      "requires": {
        "chalk": "^4.1.0",
        "hash-sum": "^2.0.0",
        "loader-utils": "^2.0.0"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        }
      }
    },
admin/src/App.vue
@@ -3,10 +3,20 @@
</template>
<style lang="scss">
@import "assets/style/lib.css";
// å¼•入全局样式
@import "assets/style/style";
// å¼•入系统内置图标
@import "assets/icons/system/index";
// å¼•入自定义图标
@import "assets/icons/ext/index";
.long-title-style {
  white-space: nowrap;
  text-overflow: ellipsis;
  -webkit-text-overflow: ellipsis;
  overflow: hidden;
}
.el-tooltip__popper.is-dark {
  max-width: 400px;
}
</style>
admin/src/assets/avatar/man.png
admin/src/assets/avatar/woman.png
admin/src/assets/icons/company/apply.png
admin/src/assets/icons/company/change_apply.png
admin/src/assets/icons/company/dipatch_unit.png
admin/src/assets/icons/company/settle.png
admin/src/assets/icons/company/tax.png
admin/src/assets/icons/plat/apply_check.png
admin/src/assets/icons/plat/change_apply_check.png
admin/src/assets/icons/plat/company_add.png
admin/src/assets/icons/plat/settle_check.png
admin/src/assets/icons/plat/tax_check.png
admin/src/assets/images/Galanz@2x.png
admin/src/assets/images/Samsung@2x.png
admin/src/assets/images/ar_open@2x.png
admin/src/assets/images/background_defult.png
admin/src/assets/images/banner_defult.png
admin/src/assets/images/category/ic_bingxiang@2x.png
admin/src/assets/images/category/ic_dianshi@2x.png
admin/src/assets/images/category/ic_jinshui@2x.png
admin/src/assets/images/category/ic_kaoxiang@2x.png
admin/src/assets/images/category/ic_kongtiao@2x.png
admin/src/assets/images/category/ic_qita@2x.png
admin/src/assets/images/category/ic_reshuiqi@2x.png
admin/src/assets/images/category/ic_xiwanji@2x.png
admin/src/assets/images/category/ic_xiyiji @2x.png
admin/src/assets/images/category/ic_yanzao@2x.png
admin/src/assets/images/ic_copy@2x.png
admin/src/assets/images/ic_delete@2x.png
admin/src/assets/images/ic_img@2x.png
admin/src/assets/images/ic_pk@2x.png
admin/src/assets/images/ic_search@2x.png
admin/src/assets/images/login_bg.png
admin/src/assets/images/login_img.jpg
admin/src/assets/images/login_img.png
admin/src/assets/images/man.png
admin/src/assets/images/pk_defult.png
admin/src/assets/images/top_ic_bolang@2x.png
admin/src/assets/images/top_ic_chilun@2x.png
admin/src/assets/images/woman.png
admin/src/assets/images/zan.png
admin/src/assets/style/alertstyle.scss
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
::v-deep .el-form-item {
  display: flex;
}
::v-deep .el-form-item__content {
  margin-left: 0 !important;
  flex: 1;
}
.address-plus {
  display: flex;
  justify-content: space-between;
  ::v-deep .el-select {
    width: 31%;
    .el-input__inner {
      width: 100%;
    }
  }
}
.address {
  display: flex;
  justify-content: space-between;
  ::v-deep .el-select {
    width: 47%;
    .el-input__inner {
      width: 100%;
    }
  }
}
::v-deep input {
  text-align: left !important;
}
admin/src/assets/style/element-variables.scss
@@ -6,3 +6,4 @@
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
admin/src/assets/style/lib.css
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
/*-----------------[初始化]--------------*/
*{ font-family: PingFang SC;}
/* æ¸…理浮动 */
.cle:after {visibility:hidden;display:block;font-size:0;content:" ";clear:both;height:0;}
.cle:after{zoom:1;}
.clear{clear: both;}
.tc{text-align:center;}
.tl{text-align:left}
.tr{text-align:right}
.fl{float: left;}
.fr{float: right;}
.wp{ width: 94%; margin: 0 auto;}
.w30{ width: 30%;}.w40{ width: 40%;}.w47{ width: 47%;}.w48{ width: 48%;}.w49{ width: 49%;}.w50{ width: 50%;}.w60{ width: 60%;}.w80{ width: 80%;}.w90{ width: 90%;}
.bg_fa{ background-color: #fafafa;}.bg_f2{ background-color: #f2f2f2;}.bg_f1{ background-color: #f1f1f1;}.bg_f5{ background-color: #f5f5f5;}.bg_f6{ background-color: #f6f6f6;}.bg_f7{ background-color: #f7f7f7;}.bg_f8{ background-color: #f8f8f8;}.bg_e{ background-color: #eee;}.bg_d{ background-color: #ddd;}.bg_w{ background-color: #fff;}.bg_3{ background-color: #333;}.bcf{ color: #fff;}.bc3{ color: #333;}.bcc{ color: #ccc;}.bc9{ color: #999;}.bc6{ color: #666;}
.rd4{border-radius: 4px;}.rd5{border-radius: 5px;}.rd6{border-radius: 6px;}.rd8{border-radius: 8px;}.rd10{border-radius: 10px;}.rd15{border-radius: 15px;}.rd20{border-radius: 20px;}.rd30{border-radius: 30px;}.rd40{border-radius: 40px;}.rd50{border-radius: 50px;}.rd60{border-radius: 60px;}.rd70{border-radius: 70px;}.rd80{border-radius: 80px;}.rd90{border-radius: 90px;}.rd100{border-radius: 100px;}.rd120{border-radius: 120px;}.rdhalf{  border-radius:50%}
.ml5{ margin-left: 5px;}.ml10{ margin-left: 10px;}.ml15{ margin-left: 15px;}.ml20{ margin-left: 20px;}.ml25{ margin-left: 25px;}.ml30{ margin-left: 30px;}.ml40{ margin-left: 40px;}.ml50{ margin-left: 50px;}.ml60{ margin-left: 60px;}
.mt5{ margin-top: 5px;}.mt10{ margin-top: 10px;}.mt15{ margin-top: 15px;}.mt20{ margin-top: 20px;}.mt25{ margin-top: 25px;}.mt30{ margin-top: 30px;}.mt35{ margin-top: 35px;}.mt40{ margin-top: 40px;}.mt45{ margin-top: 45px;}.mt50{ margin-top: 50px;}.mt60{ margin-top: 60px;}.mt70{ margin-top: 70px;}.mt80{ margin-top: 80px;}.mt90{ margin-top: 90px;}.mt100{ margin-top:100px;}.mt150{ margin-top:150px;}.mt200{ margin-top:200px;}.mt-20{ margin-top: -20px;}.mt-30{ margin-top: -30px;}.mt-40{ margin-top: -40px;}
.mb5{ margin-bottom: 5px;}.mb10{ margin-bottom: 10px;}.mb15{ margin-bottom: 15px;}.mb20{ margin-bottom: 20px;}.mb25{ margin-bottom: 25px;}.mb30{ margin-bottom: 30px;}.mb40{ margin-bottom: 40px;}.mb50{ margin-bottom: 50px;}.mb60{ margin-bottom: 60px;}.mb80{ margin-bottom: 80px;}
.mr5{ margin-right: 5px;}.mr10{ margin-right: 10px;}.mr15{ margin-right: 15px;}.mr20{ margin-right: 20px;}.mr25{ margin-right: 25px;}.mr30{ margin-right: 30px;}.mr40{ margin-right: 40px;}.mr60{ margin-right: 60px;}.mr80{ margin-right: 80px;}.mr100{ margin-right: 100px;}
.pl10{ padding-left: 10px;}.pl20{ padding-left: 20px;}.pl25{ padding-left: 25px;}.pl30{ padding-left: 30px;}.pl40{ padding-left: 40px;}.pl50{ padding-left: 50px;}.pl60{ padding-left: 60px;}.pl80{ padding-left: 80px;}.pl100{ padding-left: 100px;}
.pr10{ padding-right: 10px;}.pr20{ padding-right: 20px;}.pr25{ padding-right: 25px;}.pr30{ padding-right: 30px;}.pr40{ padding-right: 40px;}.pr50{ padding-right: 50px;}.pr60{ padding-right: 60px;}.pr80{ padding-right: 80px;}.pr100{ padding-right: 100px;}
.pb10{ padding-bottom: 10px;}.pb20{ padding-bottom: 20px;}.pb25{ padding-bottom: 25px;}.pb30{ padding-bottom: 30px;}.pb40{ padding-bottom: 40px;}.pb50{ padding-bottom: 50px;}.pb100{ padding-bottom: 100px;}
.pt10{ padding-top: 10px;}.pt20{ padding-top: 20px;}.pt25{ padding-top: 25px;}.pt30{ padding-top: 30px;}.pt40{ padding-top: 40px;}.pt50{ padding-top: 50px;}.pt100{ padding-top: 100px;}
.plr{ padding-left: 30px; padding-right: 30px;}.plr20{ padding-left: 20px; padding-right: 20px;}.plr25{ padding-left: 25px; padding-right: 25px;}.plr30{ padding-left: 30px; padding-right: 30px;}.plr40{ padding-left: 40px; padding-right: 40px;}.plr50{ padding-left: 50px; padding-right: 50px;}.plr60{ padding-left: 60px; padding-right: 60px;}
.ptb10{padding-bottom: 10px; padding-top: 10px;} .ptb15{padding-bottom: 15px; padding-top: 15px;} .ptb20{padding-bottom: 20px; padding-top: 20px;}.ptb25{padding-bottom: 25px; padding-top: 25px;}.ptb30{padding-bottom: 30px; padding-top: 30px;}.ptb35{padding-bottom: 35px; padding-top: 35px;}.ptb40{padding-bottom: 40px; padding-top: 40px;}.ptb50{padding-bottom: 50px; padding-top: 50px;}.ptb60{padding-bottom: 60px; padding-top: 60px;}.ptb80{padding-bottom: 80px; padding-top: 80px;}.ptb100{padding-bottom: 100px; padding-top: 100px;}.ptb150{padding-bottom: 150px; padding-top: 150px;}.ptb200{padding-bottom: 200px; padding-top: 200px;}
.p5{ padding:5px}.p10{ padding:10px} .p20{ padding:20px}.p30{ padding:30px}.p2030{ padding:20px 30px}.p40{ padding:40px}.p3040{ padding:30px 40px}
.f0{ font-size: 0px;}.f20{ font-size: 20px;}.f22{ font-size: 22px;}.f24{ font-size: 24px;}.f26{ font-size: 26px;}.f28{ font-size: 28px;}.f30{ font-size: 30px;}.f32{ font-size: 32px;}.f34{ font-size: 34px;}.f36{ font-size: 36px;} .f38{ font-size: 38px;}.f40{ font-size: 40px;} .f42{ font-size: 42px;}.f44{ font-size: 44px;}.f48{ font-size: 48px;}.f50{ font-size: 50px;}.f60{ font-size: 60px;}.f64{ font-size: 64px;}.f70{ font-size: 70px;}.f80{ font-size: 80px;}.f90{ font-size: 90px;}.f100{ font-size: 100px;}
.img16{ width: 16px; height: 16px;}
.img20{ width: 20px; height: 20px;}
.img24{ width: 24px; height: 24px;}
.img26{ width: 26px; height: 26px;}
.img30{ width: 30px; height: 30px;}
.img32{ width: 32px; height: 32px;}
.img36{ width: 36px; height: 36px;}
.img40{ width: 40px; height: 40px;}
.img48{ width: 48px; height: 48px;}
.img60{ width: 60px; height: 60px;}
.img66{ width: 66px; height: 66px;}
.img80{ width: 80px; height: 80px;}
.img86{ width: 86px; height: 86px;}
.img90{ width: 90px; height: 90px;}
.img100{ width: 100px; height: 100px;}
.img110{ width: 110px; height: 110px;}
.img120{ width: 120px; height: 120px;}
.img150{ width: 150px; height: 150px;}
.img180{ width: 180px; height: 180px;}
.img200{ width: 200px; height: 200px;}
.imgfull{ width: 100%;}
.rimb{ border-bottom: 1px solid #F1F1F1;}
.rimt{ border-top: 1px solid #F1F1F1;}
.bcover{  background-size: cover; background-position: center center; background-repeat:  no-repeat;}
.bfull{ background-size: 100% 100%; background-position: center center; background-repeat:  no-repeat;}
.b{ font-weight: bold;}
.ibm{ display: inline-block; vertical-align: middle;}
.bbox{ box-sizing: border-box;}
.rauto{ margin-left:auto; margin-right:auto}
.fixedBottom{position: fixed;        left: 0;        bottom: 0;        width: 100%;}
.lh1-6{line-height: 1.6;}
.lh1-6{line-height: 1.6;}
.lh1-8{line-height: 1.8;}
.lh2{line-height: 2;}
.sbtn{ display: inline-block; padding: 0.7em 2em;  border: 1px solid transparent; box-sizing: border-box; text-align: center;}
.mini{ font-size: 18px;}
.med{ font-size: 26px;}
.def{ font-size: 34px;}
.sbtn_w100{ width: 100%; padding-left: 0; padding-right: 0;}
.sbtn_green{ color: #fff; background:#65C35D; }
.sbtn_green_rim{ color: #65C35D; border-color:#65C35D; }
.sbtn_black{ color: #fff; background:#333; }
.sbtn_gray{ color: #333; background:#F7F7F7; }
.sbtn_black_rim{ color: #333; border-color:#eee; }
.sbtn_gray_rim{ color: #999; border-color:#ccc; }
/* flex */
.flex{ display: flex; flex-wrap: wrap; justify-content: space-between;}
.cXY{ display: flex;  align-items: center;justify-content: center;}
.cY{ display: flex; align-items: center;}
.cX{display: flex; justify-content: center}
.rowW{ display: flex; flex-wrap: wrap;}
.bX{ display: flex;   flex-direction: row; justify-content: space-between;}
.bY{ display: flex;   flex-direction:column; justify-content: space-between;}
.bcX{ display: flex; justify-content: space-between; align-items: center;}
.fx1{ flex: 1; overflow: hidden; }
.cAXY{ position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);}
.shadowA{box-shadow: 0 0 5px 0 #ddd;}
.shadowB{ position: relative;}
.shadowB::after{ content: ""; display: block; width: 100%; height: 8px; box-shadow: 0 6px 12px rgba(0,0,0,.08); top: -8px; left: 0; position: absolute; }
.orange{ color: #EA531B;}
.green{ color: #65C35D;}
.blue{ color: #3C77DA;}
.red{ color: #f00;}
/* /deep/ .uicon-close .u-icon--right{ position: absolute; right: 30px; top: 30px; z-index: 999;} */
.popCloseBtn{ position: absolute; width:50px; height:50px; right: 20px; top: 20px;}
.fixedHeader{ position: absolute; left: 0; top: 0;}
admin/src/assets/style/style.scss
@@ -5,13 +5,26 @@
  padding: 0;
  margin: 0;
  color: $font-color;
  // overflow: hidden;
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scrollbar-width: none; /* firefox */
  -ms-overflow-style: none; /* IE 10+ */
  &::-webkit-scrollbar {
    display: none; /* Chrome Safari */
  }
  body {
    height: 100%;
    padding: 0;
    margin: 0;
    overflow: scroll;
    overflow: hidden;
    scrollbar-width: none; /* firefox */
    -ms-overflow-style: none; /* IE 10+ */
    &::-webkit-scrollbar {
      display: none; /* Chrome Safari */
    }
  }
  h1,h2,h3,h4,h5,h6,ul {
    margin: 0;
@@ -23,10 +36,61 @@
  #app {
    height: 100%;
    min-width: $page-min-width;
    // overflow: hidden;
  }
}
.bg {
  z-index: 9990 !important;
}
.windows {
  z-index: 9991 !important;
}
// ç©¿æ¢­æ¡†çš„æŒ‰é’®
.el-transfer__buttons {
  padding: 0 16px !important;
}
.table-header {
  background-color: #F5F6F8!important;
  th {
    background-color: #F5F6F8!important;
    color: #3F4F69 !important;
    font-size: 14px;
  }
}
.doumee-element-table {
  border-color: #DFE2E8;
  tr, th, td {
    border-color: #DFE2E8;
  }
}
::v-deep .el-table__fixed {
  height: 100% !important;
}
::v-deep .el-table__fixed-right {
  height: 100% !important;
}
::v-deep .el-table__cell {
  height: 100% !important;
}
.apply-status0, .apply-status2 , .apply-status3, .apply-status10,
.change-status0,.change-status1,.change-status2,
.settle-status0,.settle-status2,.settle-status3,
.tax-status0,
.du-status0 {
  color: #216EEE  !important;
}
  .apply-status1 , .apply-status4, .apply-status6, .apply-status7, .apply-status8, .apply-status11,
.change-status3,.change-status4,.change-status5,.change-status8,
.settle-status1,
.tax-status2,
.du-status2 {
  color: #F95601 !important;
}
  .apply-status5,.change-status7,.settle-status7,.tax-status1,.du-status1,.settle-status4  {
  color: #00BA92  !important;
}
admin/src/assets/style/variables.scss
@@ -1,9 +1,16 @@
// ä¸»è‰²è°ƒ
$primary-color: #2E68EC;
$primary-color: #216EEE;
$primary-title-start-color: #3582ff;
$primary-title-color: #216EcE;
$primary-color-sel: #0046c6;
$primary-color-hover: #1562e2;
$icon-background-color: #0d5ada;
//菜单悬浮色:
$menu-hover-color: rgba(33, 110, 238, 0.10);
// å¤´éƒ¨é«˜åº¦
$header-height: 60px;
// èœå•宽度
$menu-width: 208px;
$menu-width: 250px;
// é¡µé¢æœ€å°å®½åº¦
$page-min-width: 1000px;
admin/src/components/base/BaseOpera.vue
@@ -14,6 +14,16 @@
      }
    }
  },
  // watch: {
  //   visible() {
  //     console.log(this.visible);
  //   }
  // },
  watch: {
    $route (to, from) {
      this.close()
    }
  },
  methods: {
    // é…ç½®
    config (extParams = {}) {
@@ -49,6 +59,9 @@
        }
      })
    },
    close () {
      this.visible = false
    },
    // ç¡®è®¤æ–°å»º/修改
    confirm () {
      if (this.form.id == null || this.form.id === '') {
@@ -60,9 +73,12 @@
    // ç¡®è®¤æ–°å»º
    __confirmCreate () {
      this.$refs.form.validate((valid) => {
        // debugger
        if (!valid) {
          return
        }
        // console.log(this.form);
        // debugger
        // è°ƒç”¨æ–°å»ºæŽ¥å£
        this.isWorking = true
        this.api.create(this.form)
admin/src/components/base/BaseTable.vue
@@ -135,9 +135,11 @@
    // åˆ é™¤
    deleteById (row, childConfirm = true) {
      this.__checkApi()
      let message = `确认删除${this.module}【${row[this.configData['field.main']]}】吗?`
      // let message = `确认删除${this.module}【${row[this.configData['field.main']]}】吗?`
      let message = `确认删除该记录吗?`
      if (childConfirm && row.children != null && row.children.length > 0) {
        message = `确认删除${this.module}【${row[this.configData['field.main']]}】及其子${this.module}吗?`
        // message = `确认删除${this.module}【${row[this.configData['field.main']]}】及其子${this.module}吗?`
        message = `确认删除该记录及其子数据吗?`
      }
      this.$dialog.deleteConfirm(message)
        .then(() => {
@@ -175,7 +177,7 @@
          }
        }
        if (containChildrenRows.length > 0) {
          message = `本次将删除${this.module}【${containChildrenRows.join('、')}】及其子${this.module}记录,确认删除吗?`
          message = '本次将删除该数据及其子数据,确认删除吗?'
        }
      }
      this.$dialog.deleteConfirm(message)
admin/src/components/common/DepartmentSelect.vue
@@ -45,7 +45,7 @@
    }
  },
  watch: {
    excludeId () {
    value () {
      this.fetchData()
    }
  },
@@ -54,6 +54,7 @@
    fetchData () {
      fetchTree()
        .then(records => {
          // debugger
          this.data = []
          this.__fillData(this.data, records)
        })
admin/src/components/common/GlobalAlertWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
<template>
  <el-dialog
    class="global-window"
    title="title"
    :visible="visible"
    :with-header="true"
    :width="width"
    :close-on-press-escape="false"
    :wrapper-closable="false"
    :append-to-body="true"
    @close="close"
  >
    <div slot="title" class="window__header">
      {{title}}
    </div>
    <div class="window__body">
      <slot></slot>
    </div>
    <div v-if="withFooter" class="window__footer">
      <slot name="footer">
        <el-button @click="confirm" :loading="confirmWorking" type="primary">确定</el-button>
        <el-button @click="close">取消</el-button>
      </slot>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: 'GlobalAlertWindow',
  props: {
    width: {
      type: String,
      default: '50%'
    },
    // æ˜¯å¦åŒ…含底部操作
    withFooter: {
      type: Boolean,
      default: true
    },
    // ç¡®è®¤æŒ‰é’®loading状态
    confirmWorking: {
      type: Boolean,
      default: false
    },
    // æ ‡é¢˜
    title: {
      type: String,
      default: ''
    },
    // æ˜¯å¦å±•示
    visible: {
      type: Boolean,
      required: true
    }
  },
  methods: {
    confirm () {
      // console.log(this.title);
      // debugger
      this.$emit('confirm')
    },
    close () {
      // console.log(this.title);
      // debugger
      this.$emit('update:visible', false)
    }
  }
}
</script>
<style scoped lang="scss">
@import "@/assets/style/variables.scss";
// è¾“入框高度
$input-height: 32px;
::v-deep .el-dialog__header {
  background-color: #f7f7f7;
  font-weight: 500;
  color: #222;
}
::v-deep .el-dialog__body {
  padding: 20px 20px 0;
  box-sizing: border-box;
}
.global-window {
  // top: 80px !important;
  // left: 218px !important;
  // å¤´éƒ¨æ ‡é¢˜
  ::v-deep .el-dialog__header {
    padding: 19px 24px;
    height: 56px;
    line-height: 18px;
    box-sizing: border-box;
    border-bottom: 1px solid #eee;
    // text-align: center;
    .el-dialog__headerbtn {
      width: 18px;
      height: 18px;
      .el-dialog__close {
        width: 18px;
        height: 18px;
        font-size: 19px;
        line-height: 18px;
      }
    }
  }
  // ä¸»ä½“
  .window__body {
    min-height: 200px;
  }
  .window__footer {
      user-select: none;
      border-top: 1px solid #eee;
      height: 60px;
      line-height: 60px;
      text-align: center;
    }
}
</style>
admin/src/components/common/GlobalQuestionWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
<template>
  <el-dialog
    class="global-window"
    title="title"
    :visible="visible"
    :with-header="true"
    :top="top"
    :width="width"
    :close-on-press-escape="false"
    :wrapper-closable="false"
    :append-to-body="true"
    @close="close"
  >
    <div slot="title" style="min-height: 10px;" class="window__header">
      {{title}}
    </div>
    <div class="window__body">
      <slot></slot>
    </div>
    <div v-if="withFooter" class="window__footer">
      <slot name="footer">
        <el-button @click="confirm" :loading="confirmWorking" type="primary">确定</el-button>
        <el-button @click="close">返回</el-button>
      </slot>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: 'GlobalQuestionWindow',
  props: {
    width: {
      type: String,
      default: '40%'
    },
    top: {
      type: String,
      default: '15vh'
    },
    // æ˜¯å¦åŒ…含底部操作
    withFooter: {
      type: Boolean,
      default: true
    },
    // ç¡®è®¤æŒ‰é’®loading状态
    confirmWorking: {
      type: Boolean,
      default: false
    },
    // æ ‡é¢˜
    title: {
      type: String,
      default: ''
    },
    // æ˜¯å¦å±•示
    visible: {
      type: Boolean,
      required: true
    }
  },
  methods: {
    confirm () {
      // console.log(this.title);
      // debugger
      this.$emit('confirm')
    },
    close () {
      // console.log(this.title);
      // debugger
      this.$emit('update:visible', false)
    }
  }
}
</script>
<style scoped lang="scss">
@import "@/assets/style/variables.scss";
// è¾“入框高度
$input-height: 32px;
::v-deep .el-dialog__header {
  background-color: #f7f7f7;
  font-weight: 500;
  color: #222;
}
::v-deep .el-dialog__body {
  padding: 30px 20px 0;
  box-sizing: border-box;
}
.global-window {
  // top: 80px !important;
  // left: 218px !important;
  // å¤´éƒ¨æ ‡é¢˜
  ::v-deep .el-drawer__header {
    padding: 0 10px 0 0;
    line-height: 40px;
    border-bottom: 1px solid #eee;
    text-align: center;
    width: 100%;
  }
  // ä¸»ä½“
  ::v-deep .el-dialog__body {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 40px;
    bottom: 0;
    width: 100%;
    height: calc(90vh - 52px);
    overflow: hidden;
    background-color: #f7f7f7;
    // å†…容
    .window__body {
      width: 100%;
      height: 100%;
      overflow-y: auto;
      // æ ‡ç­¾
      .el-form-item__label {
        float: none;
      }
      // å…ƒç´ å®½åº¦ä¸º100%
      .el-form-item__content > *{
        width: 100%;
      }
    }
    // å°¾éƒ¨
    .window__footer {
      user-select: none;
      border-top: 1px solid #eee;
      height: 60px;
      line-height: 60px;
      text-align: center;
    }
  }
}
</style>
admin/src/components/common/GlobalRigthWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
<template>
  <el-drawer
    class="global-window"
    title="title"
    :visible="visible"
    :with-header="true"
    :size="width"
    :close-on-press-escape="false"
    :wrapper-closable="false"
    :append-to-body="true"
    :modal="false"
    @close="close"
  >
    <div slot="title" class="window__header">
      <span class="header__btn-back" @click="close"><i class="el-icon-arrow-left"></i></span>{{title}}
      <!-- {{title}} -->
    </div>
    <div class="window__body">
      <slot></slot>
    </div>
    <div v-if="withFooter" class="window__footer">
      <slot name="footer">
        <el-button @click="confirm" :loading="confirmWorking" type="primary">确定</el-button>
        <el-button @click="close">返回</el-button>
      </slot>
    </div>
  </el-drawer>
</template>
<script>
export default {
  name: 'GlobalWindow',
  props: {
    width: {
      type: String,
      default: '100%'
    },
    // æ˜¯å¦åŒ…含底部操作
    withFooter: {
      type: Boolean,
      default: true
    },
    // ç¡®è®¤æŒ‰é’®loading状态
    confirmWorking: {
      type: Boolean,
      default: false
    },
    // æ ‡é¢˜
    title: {
      type: String,
      default: ''
    },
    // æ˜¯å¦å±•示
    visible: {
      type: Boolean,
      required: true
    }
  },
  methods: {
    confirm () {
      this.$emit('confirm')
    },
    close () {
      this.$emit('update:visible', false)
    }
  }
}
</script>
<style scoped lang="scss">
@import "@/assets/style/variables.scss";
// è¾“入框高度
$input-height: 32px;
.global-window {
  top: 80px !important;
  left: 218px !important;
  // å¤´éƒ¨æ ‡é¢˜
  ::v-deep .el-drawer__header {
    padding: 0 10px 0 0;
    line-height: 40px;
    border-bottom: 1px solid #eee;
    // text-align: center;
    font-weight: 500;
    color: #222;
    // è¿”回按钮
    .header__btn-back {
      display: inline-block;
      width: 30px;
      background: $primary-color;
      color: #fff;
      text-align: center;
      margin-right: 12px;
      border-right: 1px solid #eee;
    }
    .el-drawer__close-btn:focus {
      outline: none;
    }
  }
  // ä¸»ä½“
  ::v-deep .el-drawer__body {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 40px;
    bottom: 0;
    width: 100%;
    overflow: hidden;
    // background-color: #f7f7f7;
    // å†…容
    .window__body {
      // width: 1100px;
      // margin: 0 auto;
      // background-color: #fff;
      width: 100%;
      height: 100%;
      overflow-y: auto;
      padding: 0;
      // æ ‡ç­¾
      .el-form-item__label {
        float: none;
      }
      // å…ƒç´ å®½åº¦ä¸º100%
      .el-form-item__content > *{
        width: 100%;
      }
    }
    // å°¾éƒ¨
    .window__footer {
      user-select: none;
      border-top: 1px solid #eee;
      height: 60px;
      line-height: 60px;
      text-align: center;
    }
  }
}
</style>
admin/src/components/common/GlobalWindow.vue
@@ -8,18 +8,20 @@
    :close-on-press-escape="false"
    :wrapper-closable="false"
    :append-to-body="true"
    :modal="false"
    @close="close"
  >
    <div slot="title" class="window__header">
      <span class="header__btn-back" @click="close"><i class="el-icon-arrow-left"></i></span>{{title}}
      <!-- {{title}} -->
    </div>
    <div class="window__body">
      <slot></slot>
    </div>
    <div v-if="withFooter" class="window__footer">
      <slot name="footer">
        <el-button @click="confirm" :loading="confirmWorking" type="primary">确定</el-button>
        <el-button @click="close">取消</el-button>
        <el-button @click="confirm" :loading="confirmWorking" type="primary">{{text}}</el-button>
        <el-button @click="close">返回</el-button>
      </slot>
    </div>
  </el-drawer>
@@ -31,12 +33,17 @@
  props: {
    width: {
      type: String,
      default: '36%'
      default: '100%'
    },
    // æ˜¯å¦åŒ…含底部操作
    withFooter: {
      type: Boolean,
      default: true
    },
    // æäº¤æŒ‰é’®æ–‡å­—
    text: {
      type: String,
      default: '确定'
    },
    // ç¡®è®¤æŒ‰é’®loading状态
    confirmWorking: {
@@ -70,11 +77,16 @@
// è¾“入框高度
$input-height: 32px;
.global-window {
  top: 80px !important;
  left: 250px !important;
  // å¤´éƒ¨æ ‡é¢˜
  /deep/ .el-drawer__header {
  ::v-deep .el-drawer__header {
    padding: 0 10px 0 0;
    line-height: 40px;
    border-bottom: 1px solid #eee;
    // text-align: center;
    font-weight: 500;
    color: #222;
    // è¿”回按钮
    .header__btn-back {
      display: inline-block;
@@ -90,7 +102,7 @@
    }
  }
  // ä¸»ä½“
  /deep/ .el-drawer__body {
  ::v-deep .el-drawer__body {
    display: flex;
    flex-direction: column;
    position: absolute;
@@ -98,15 +110,20 @@
    bottom: 0;
    width: 100%;
    overflow: hidden;
    // background-color: #f7f7f7;
    // å†…容
    .window__body {
      // width: 1100px;
      // margin: 0 auto;
      // background-color: #fff;
      width: 100%;
      height: 100%;
      overflow-y: auto;
      padding: 12px 16px;
      // æ ‡ç­¾
      .el-form-item__label {
        float: none;
      }
      // .el-form-item__label {
      //   float: none;
      // }
      // å…ƒç´ å®½åº¦ä¸º100%
      .el-form-item__content > *{
        width: 100%;
admin/src/components/common/Header.vue
@@ -6,149 +6,25 @@
        <i class="el-icon-s-fold" v-else @click="switchCollapseMenu(null)"></i>
        {{title}}
      </h2>
      <div class="user">
        <el-dropdown trigger="click">
          <span class="el-dropdown-link">
            <img v-if="userInfo != null" :src="userInfo.avatar == null ? '@/assets/images/avatar/man.png' : userInfo.avatar" alt="">{{userInfo | displayName}}<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item @click.native="changePwd">修改密码</el-dropdown-item>
            <el-dropdown-item @click.native="logout">退出登录</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
      <tagsview class="tags"></tagsview>
    </div>
    <!-- ä¿®æ”¹å¯†ç  -->
    <GlobalWindow
      title="修改密码"
      :visible.sync="visible.changePwd"
      @confirm="confirmChangePwd"
      @close="visible.changePwd = false"
    >
      <el-form :model="changePwdData.form" ref="changePwdDataForm" :rules="changePwdData.rules">
        <el-form-item label="原始密码" prop="oldPwd" required>
          <el-input v-model="changePwdData.form.oldPwd" type="password" placeholder="请输入原始密码" maxlength="30" show-password></el-input>
        </el-form-item>
        <el-form-item label="新密码" prop="newPwd" required>
          <el-input v-model="changePwdData.form.newPwd" type="password" placeholder="请输入新密码" maxlength="30" show-password></el-input>
        </el-form-item>
        <el-form-item label="确认新密码" prop="confirmPwd" required>
          <el-input v-model="changePwdData.form.confirmPwd" type="password" placeholder="请再次输入新密码" maxlength="30" show-password></el-input>
        </el-form-item>
      </el-form>
    </GlobalWindow>
  </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import GlobalWindow from './GlobalWindow'
import { logout, updatePwd } from '@/api/system/common'
import tagsview from "./tagsview.vue"
export default {
  name: 'Header',
  components: { GlobalWindow },
  data () {
    return {
      visible: {
        // ä¿®æ”¹å¯†ç 
        changePwd: false
      },
      isWorking: {
        // ä¿®æ”¹å¯†ç 
        changePwd: false
      },
      username: 'bob', // ç”¨æˆ·å
      // ä¿®æ”¹å¯†ç å¼¹æ¡†
      changePwdData: {
        form: {
          oldPwd: '',
          newPwd: '',
          confirmPwd: ''
        },
        rules: {
          oldPwd: [
            { required: true, message: '请输入原始密码' }
          ],
          newPwd: [
            { required: true, message: '请输入新密码' }
          ],
          confirmPwd: [
            { required: true, message: '请再次输入新密码' }
          ]
        }
      }
    }
  },
  components: { tagsview },
  computed: {
    ...mapState(['menuData', 'userInfo']),
    ...mapState(['menuData']),
    title () {
      return this.$route.meta.title
    }
  },
  filters: {
    // å±•示名称
    displayName (userInfo) {
      if (userInfo == null) {
        return ''
      }
      if (userInfo.realname != null && userInfo.realname.trim().length > 0) {
        return userInfo.realname
      }
      return userInfo.username
    }
  },
  methods: {
    ...mapMutations(['setUserInfo', 'switchCollapseMenu']),
    // ä¿®æ”¹å¯†ç 
    changePwd () {
      this.visible.changePwd = true
      this.$nextTick(() => {
        this.$refs.changePwdDataForm.resetFields()
      })
    },
    // ç¡®å®šä¿®æ”¹å¯†ç 
    confirmChangePwd () {
      if (this.isWorking.changePwd) {
        return
      }
      this.$refs.changePwdDataForm.validate((valid) => {
        if (!valid) {
          return
        }
        // éªŒè¯ä¸¤æ¬¡å¯†ç è¾“入是否一致
        if (this.changePwdData.form.newPwd !== this.changePwdData.form.confirmPwd) {
          this.$tip.warning('两次密码输入不一致')
          return
        }
        // æ‰§è¡Œä¿®æ”¹
        this.isWorking.changePwd = true
        updatePwd({
          oldPwd: this.changePwdData.form.oldPwd,
          newPwd: this.changePwdData.form.newPwd
        })
          .then(() => {
            this.$tip.apiSuccess('修改成功')
            this.visible.changePwd = false
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
          .finally(() => {
            this.isWorking.changePwd = false
          })
      })
    },
    // é€€å‡ºç™»å½•
    logout () {
      logout()
        .then(() => {
          this.setUserInfo(null)
          this.$router.push({ name: 'login' })
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    }
    ...mapMutations(['switchCollapseMenu']),
  }
}
</script>
@@ -161,40 +37,23 @@
  background: #fff;
  height: 100%;
  display: flex;
  overflow: hidden;
  h2 {
    width: 50%;
    flex-shrink: 0;
    line-height: $header-height;
    line-height: 48px;
    width: 200px;
    font-size: 19px;
    font-weight: 600;
    color: #606263;
    font-weight: normal;
    display: inline;
    & > i {
      font-size: 20px;
      margin-right: 12px;
    }
  }
  .user {
    width: 50%;
    flex-shrink: 0;
    text-align: right;
    .el-dropdown {
      top: 2px;
    }
    img {
      width: 32px;
      position: relative;
      top: 10px;
      margin-right: 10px;
    }
  }
}
// ä¸‹æ‹‰èœå•框
.el-dropdown-menu {
  width: 140px;
  .el-dropdown-menu__item:hover {
    background: #E3EDFB;
    color: $primary-color;
  }
}
// .tags {
//     padding-bottom: 16px;
//   }
</style>
admin/src/components/common/ImportButton.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
<template>
  <div class="import-button">
    <el-button type="primary" @click="$refs.importWindow.open(text)">{{text}}</el-button>
    <ImportWindow :action="action" :template-path="templatePath" :template-name="templateName" ref="importWindow" @download="$emit('download')" @success="handleSuccess"/>
  </div>
</template>
<script>
import ImportWindow from './ImportWindow'
export default {
  name: 'ImportButton',
  components: { ImportWindow },
  props: {
    // æŒ‰é’®æ–‡æ¡ˆ
    text: {
      default: '导入'
    },
    // æ¨¡ç‰ˆåœ°å€
    templatePath: {
      required: true
    },
    // ä¸‹è½½åŽçš„æ¨¡ç‰ˆæ–‡ä»¶åç§°
    templateName: {
      required: true
    },
    // å¯¼å…¥æŽ¥å£åœ°å€
    action: {
      required: true
    }
  },
  methods: {
    handleSuccess () {
      this.$emit('success')
    }
  }
}
</script>
admin/src/components/common/ImportWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,204 @@
<template>
  <el-dialog
    width="500px"
    :title="title"
    :visible.sync="visible"
    append-to-body
    custom-class="eva-dialog import-window"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :show-close="false"
  >
    <el-form>
      <el-form-item>
        <el-upload
          drag
          :show-file-list="false"
          action="none"
          accept=".xlsx, .xls"
          :before-upload="handleBeforeUpload"
        >
          <template v-if="form.file == null">
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
          </template>
          <template v-else>
            <i class="el-icon-files"></i>
            <div class="el-upload__text">{{form.file.name}}<em></em></div>
          </template>
        </el-upload>
      </el-form-item>
    </el-form>
    <div slot="footer" class="import-window__footer">
      <!-- <div class="sync-exists">
        <el-checkbox v-model="form.sync"/><span>同步已存在的数据</span>
      </div> -->
      <div class="opera">
        <a href=""></a>
        <el-button type="text" icon="el-icon-download" @click="downloadTemplate">下载模版</el-button>
        <el-button @click="cancel">{{cancelText}}</el-button>
        <el-button type="primary" @click="confirm" :loading="isWorking">{{confirmText}}</el-button>
      </div>
    </div>
  </el-dialog>
</template>
<script>
import request from '@/utils/request'
export default {
  name: 'ImportWindow',
  props: {
    // å¯¼å…¥æŽ¥å£åœ°å€
    action: {
      required: true
    },
    // ç¡®è®¤æŒ‰é’®æ–‡æ¡ˆ
    confirmText: {
      type: String,
      default: '导入'
    },
    // å–消按钮文案
    cancelText: {
      type: String,
      default: '取消'
    },
    // æ¨¡ç‰ˆåœ°å€
    templatePath: {
      required: true
    },
    // ä¸‹è½½åŽçš„æ¨¡ç‰ˆæ–‡ä»¶åç§°
    templateName: {
      required: true
    }
  },
  data () {
    return {
      visible: false,
      isWorking: false,
      title: '导入数据',
      form: {
        sync: false,
        file: false,
        categoryId: ''
      }
    }
  },
  methods: {
    /**
     * æ‰“开窗口
     *
     * @param title çª—口标题
     */
    open (title) {
      this.visible = true
      this.title = title
      this.form.sync = false
      this.form.file = null
    },
    /**
     * ç¡®å®šå¯¼å…¥
     */
    confirm () {
      if (this.form.file == null) {
        this.$tip.warning('请选择文件')
        return
      }
      this.isWorking = true
      const param = new FormData()
      param.set('file', this.form.file)
      request.post(this.action, param, {
        headers: {
          'Content-Type': 'multipart/form-data;charset=UTF-8'
        }
      })
        .then(() => {
          this.$tip.success('导入成功')
          this.visible = false
          this.$emit('success')
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
        .finally(() => {
          this.isWorking = false
        })
    },
    /**
     * å–消
     */
    cancel () {
      this.visible = false
    },
    /**
     * ä¸‹è½½æ¨¡ç‰ˆ
     */
    downloadTemplate () {
      const link = document.createElement('a')
      link.setAttribute('download', this.templateName) //下载的文件名
      console.log(`${window.location.origin}${process.env.VUE_APP_CONTEXT_PATH}${this.templatePath}`);
      link.href = `${window.location.origin}${process.env.VUE_APP_CONTEXT_PATH}${this.templatePath}`  //文件url
      link.click()
      // this.$emit('download')
    },
    /**
     * æ–‡ä»¶ä¸Šä¼ å‰å­˜å‚¨ä¸Šä¼ çš„æ–‡ä»¶
     *
     * @param file éœ€å¯¼å…¥çš„æ–‡ä»¶
     */
    handleBeforeUpload (file) {
      this.form.file = file
      return false
    }
  }
}
</script>
<style lang="scss">
@import "../../assets/style/variables";
.import-window {
  .el-upload {
    width: 100%;
    .el-upload-dragger {
      width: 100%;
      .el-icon-upload, .el-icon-files {
        font-size: 67px;
        color: #C0C4CC;
        margin: 40px 0 16px;
        line-height: 50px;
      }
    }
  }
  .import-window__footer {
    display: flex;
    .sync-exists {
      width: 200px;
      flex-shrink: 0;
      text-align: left;
      font-size: 13px;
      display: flex;
      align-items: center;
      .el-checkbox {
        margin-right: 10px;
      }
      & > * {
        vertical-align: middle;
      }
    }
    .opera {
      flex-grow: 1;
      a {
        font-size: 12px;
        margin-right: 10px;
        text-decoration: none;
        .el-icon-download {
          font-size: 15px;
          position: relative;
          top: 2px;
        }
      }
    }
  }
}
</style>
admin/src/components/common/Light.vue
@@ -28,13 +28,16 @@
$cycle-size01: 16px;
$cycle-size02: 6px;
$normal-color: #00CC99;
$shadow-color: #00CCa9;
$warn-color: #FFCC33;
$warn-shadow-color: #FFCbe3;
$danger-color: #FF3300;
$dange-shadowr-color: #FF3310;
@mixin light-status ($cycle-bg) {
  em {
    background: $cycle-bg;
    i {
      background: $cycle-bg - 30;
      background: mix($cycle-bg,  #000030, 0.5);
    }
  }
}
@@ -79,44 +82,44 @@
}
@keyframes shine-normal {
  0% {
    box-shadow: 0 0 5px $normal-color + 10;
    box-shadow: 0 0 5px $shadow-color;
  }
  25% {
    box-shadow: 0 0 10px $normal-color + 10;
    box-shadow: 0 0 10px $shadow-color;
  }
  50% {
    box-shadow: 0 0 15px $normal-color + 10;
    box-shadow: 0 0 15px $shadow-color;
  }
  100% {
    box-shadow: 0 0 20px $normal-color + 10;
    box-shadow: 0 0 20px $shadow-color;
  }
}
@keyframes shine-warn {
  0% {
    box-shadow: 0 0 5px $warn-color - 50;
    box-shadow: 0 0 5px $warn-shadow-color;
  }
  25% {
    box-shadow: 0 0 10px $warn-color - 50;
    box-shadow: 0 0 10px $warn-shadow-color;
  }
  50% {
    box-shadow: 0 0 15px $warn-color - 50;
    box-shadow: 0 0 15px $warn-shadow-color;
  }
  100% {
    box-shadow: 0 0 20px $warn-color - 50;
    box-shadow: 0 0 20px $warn-shadow-color;
  }
}
@keyframes shine-danger {
  0% {
    box-shadow: 0 0 5px $danger-color + 10;
    box-shadow: 0 0 5px $dange-shadowr-color;
  }
  25% {
    box-shadow: 0 0 10px $danger-color + 10;
    box-shadow: 0 0 10px $dange-shadowr-color;
  }
  50% {
    box-shadow: 0 0 15px $danger-color + 10;
    box-shadow: 0 0 15px $dange-shadowr-color;
  }
  100% {
    box-shadow: 0 0 20px $danger-color + 10;
    box-shadow: 0 0 20px $dange-shadowr-color;
  }
}
</style>
admin/src/components/common/Menu.vue
@@ -1,19 +1,15 @@
<template>
  <div class="menu" :class="{collapse: menuData.collapse}">
    <div class="logo">
      <div><img src="@/assets/logo.png"></div>
      <h1 :class="{hidden: menuData.collapse}">{{title}}</h1>
    </div>
    <scrollbar>
<!--      :default-openeds="defaultOpeneds"-->
      <el-menu
        ref="menu"
        :unique-opened="true"
        :default-active="activeIndex"
        text-color="#fff"
        active-text-color="#fff"
        :collapse="menuData.collapse"
        :default-openeds="defaultOpeneds"
        :collapse-transition="false"
        unique-opened
        @select="handleSelect"
      >
        <MenuItems v-for="menu in menuData.list" :key="menu.index" :menu="menu" :is-root-menu="true"/>
@@ -28,11 +24,6 @@
import Scrollbar from './Scrollbar'
export default {
  name: 'Menu',
  data() {
    return {
      title: process.env.VUE_APP_TITLE
    }
  },
  components: { Scrollbar, MenuItems },
  computed: {
    ...mapState(['menuData']),
@@ -45,12 +36,17 @@
      const menuConfig = this.__getMenuConfig(path, 'url', this.menuData.list)
      if (menuConfig == null) {
        return null
      } else {
        this.$store.commit("pushtags", menuConfig)
      }
      // console.log(menuConfig.index);
      return menuConfig.index
    },
    // é»˜è®¤å±•开的菜单index
    defaultOpeneds () {
      return this.menuData.list.map(menu => menu.index)
      // return this.menuData.list.map(menu => menu.index)
      return [this.menuData.list[0].index]
    }
  },
  methods: {
@@ -70,7 +66,9 @@
      if (menuConfig.url == null || menuConfig.url.trim().length === 0) {
        return
      }
      this.$router.push(menuConfig.url)
      this.$store.commit("pushtags", menuConfig)
    },
    // èŽ·å–èœå•é…ç½®
    __getMenuConfig (value, key, menus) {
@@ -97,37 +95,6 @@
  height: 100%;
  display: flex;
  flex-direction: column;
  // LOGO
  .logo {
    height: 60px;
    flex-shrink: 0;
    line-height: 60px;
    overflow: hidden;
    display: flex;
    background: $primary-color - 20;
    padding: 0 16px;
    & > div {
      width: 32px;
      flex-shrink: 0;
      margin-right: 12px;
      img {
        width: 100%;
        flex-shrink: 0;
        vertical-align: middle;
        position: relative;
        top: -2px;
      }
    }
    h1 {
      font-size: 16px;
      font-weight: 500;
      transition: opacity ease .3s;
      overflow: hidden;
      &.hidden {
        opacity: 0;
      }
    }
  }
}
</style>
<style lang="scss">
@@ -141,11 +108,11 @@
    background: $primary-color;
    // é€‰ä¸­çŠ¶æ€
    &.is-active {
      background: $primary-color - 40 !important;
      background: $primary-color-sel !important;
    }
    // æ‚¬æµ®
    &:hover {
      background-color: $primary-color - 12;
      background-color: $primary-color-hover;
    }
    &:focus {
      background: $primary-color;
@@ -158,13 +125,13 @@
    }
    &.is-active {
      .el-submenu__title{
        background-color: $primary-color - 20;
        background-color: $icon-background-color;
      }
      .el-menu .el-menu-item{
        background-color: $primary-color - 20;
        background-color: $icon-background-color;
        // æ‚¬æµ®
        &:hover {
          background-color: $primary-color - 30;
          background-color: $icon-background-color;
        }
      }
    }
admin/src/components/common/MenuSelect.vue
@@ -12,7 +12,7 @@
<script>
import TreeSelect from './TreeSelect'
import { fetchTree } from '@/api/system/menu'
import { fetchTree, fetchTree1 } from '@/api/system/menu'
export default {
  name: 'MenuSelect',
  components: { TreeSelect },
@@ -20,6 +20,9 @@
    value: {},
    inline: {
      default: true
    },
    type: {
      default: '0'
    },
    placeholder: {
      default: '请选择菜单'
@@ -47,14 +50,25 @@
  methods: {
    // èŽ·å–æ‰€æœ‰èœå•
    fetchData () {
      fetchTree()
        .then(records => {
          this.data = []
          this.__fillData(this.data, records)
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
      if (this.type === '1') {
        fetchTree1()
          .then(records => {
            this.data = []
            this.__fillData(this.data, records)
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
      } else {
        fetchTree()
          .then(records => {
            this.data = []
            this.__fillData(this.data, records)
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
      }
    },
    // å¡«å……菜单树
    __fillData (list, pool) {
admin/src/components/common/Pagination.vue
@@ -2,7 +2,7 @@
  <div class="table-pagination">
    <el-pagination
      :current-page="pagination.pageIndex"
      :page-sizes="[10, 20, 30, 40]"
      :page-sizes="pagination.pageSizes||[10, 20, 30, 40]"
      :page-size="pagination.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="pagination.total"
admin/src/components/common/PositionSelect.vue
@@ -93,7 +93,7 @@
}
.vue-treeselect {
  line-height: 30px;
  /deep/ .vue-treeselect__control {
  ::deep .vue-treeselect__control {
    height: 32px;
    .vue-treeselect__single-value {
      line-height: 30px;
admin/src/components/common/RichEditor.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,158 @@
<template>
  <div style="border: 1px solid #ccc;">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editor"
      :defaultConfig="toolbarConfig"
      :mode="mode"
    />
    <Editor
      style="height: 300px; overflow-y: hidden;"
      :value="content.content"
      :mode="mode"
      :defaultConfig="editorConfig"
      @onCreated="onCreated"
      @onChange="onChange"
      @input="html=$event"
    />
  </div>
</template>
<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
export default {
  name: 'RichEditor',
  components: { Editor, Toolbar },
  props: {
    content: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      editor: null,
      html: '<p><br></p>',
      toolbarConfig: {
        toolbarKeys: [
          "headerSelect",
          "blockquote",
          "|",
          "bold",
          "underline",
          "italic",
          {
              "key": "group-more-style",
              "title": "更多",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path></svg>",
              "menuKeys": [
                  "through",
                  "code",
                  "sup",
                  "sub",
                  "clearStyle"
              ]
          },
          "color",
          "bgColor",
          "|",
          "fontSize",
          "fontFamily",
          "lineHeight",
          "|",
          "bulletedList",
          "numberedList",
          "todo",
          {
              "key": "group-justify",
              "title": "对齐",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z\"></path></svg>",
              "menuKeys": [
                  "justifyLeft",
                  "justifyRight",
                  "justifyCenter",
                  "justifyJustify"
              ]
          },
          {
              "key": "group-indent",
              "title": "缩进",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z\"></path></svg>",
              "menuKeys": [
                  "indent",
                  "delIndent"
              ]
          },
          // "|",
          "emotion",
          "insertLink",
          {
              "key": "group-image",
              "title": "图片",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z\"></path></svg>",
              "menuKeys": [
                  "insertImage",
                  "uploadImage"
              ]
          },
          "insertTable",
          "codeBlock",
          "divider",
          "|",
          "undo",
          "redo",
          "|",
          "fullScreen"
        ]
      },
      editorConfig: {
        placeholder: '请输入内容...',
        MENU_CONF: {
          uploadImage: {
            // server: '/api/upload',
            name: 'file',
            server: process.env.VUE_APP_API_PREFIX + '/public/uploadLocal',
            meta: {
              folder: 'shop'
            },
            onBeforeUpload(file) {    // JS è¯­æ³•
              // file é€‰ä¸­çš„æ–‡ä»¶ï¼Œæ ¼å¼å¦‚ { key: file }
              // debugger
              return file
            },
            onSuccess(file, res) {
                console.log(`${file.name} ä¸Šä¼ æˆåŠŸ`, res)
            },
            onError(file, err, res) {
              console.log(`${file.name} ä¸Šä¼ å‡ºé”™`, err, res)
            },
          },
        }
      },
      mode: 'default', // or 'simple'
    }
  },
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // ç»„件销毁时,及时销毁编辑器
  },
  methods: {
    onCreated (editor) {
      this.editor = Object.seal(editor)
    },
    onChange (editor) {
      console.log(this.html);
      // debugger
      if (!this.html||this.content.content==this.html) {
        return
      }
      this.$emit('edit', this.html)
    },
  },
}
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>
admin/src/components/common/SearchFormCollapse.vue
@@ -31,7 +31,7 @@
    height: 50px;
    overflow: hidden;
    padding-right: 250px;
    /deep/ section {
    ::v-deep section {
      position: absolute;
      top: 0;
      right: 100px;
admin/src/components/common/ShowRich.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
<template>
  <GlobalAlertWindow
    :title="title"
    :visible.sync="visible"
    :confirm-working="isWorking"
    @confirm="confirm"
  >
    <Editor v-if="form.content" v-model="form.content" :defaultConfig="{ readOnly : true }" />
    <div slot="footer"></div>
  </GlobalAlertWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalAlertWindow from '@/components/common/GlobalAlertWindow'
import { Editor } from '@wangeditor/editor-for-vue'
export default {
  name: 'ShowRich',
  extends: BaseOpera,
  components: { GlobalAlertWindow, Editor },
  data () {
    return {
      // è¡¨å•数据
      form: {
        content: ''
      },
      // éªŒè¯è§„则
      rules: {
      }
    }
  },
  created () {
    this.config({
      api: '/business/areas',
      'field.id': 'id'
    })
  },
  methods: {
  },
}
</script>
admin/src/components/common/Tree.vue
@@ -1,34 +1,18 @@
<template>
<!--    <div class="tree">-->
<!--        <div v-for="(item, index) of list" :key="index" @click.stop="clickIten(item)">-->
<!--            <div class="tree_item">-->
<!--                <i class="el-icon-caret-bottom" :class="{ 'activeColor': item[defaultProps.status] }" v-show="item[defaultProps.status] && item[defaultProps.children]"></i>-->
<!--                <i class="el-icon-caret-right color" v-show="item[defaultProps.children] && !item[defaultProps.status]"></i>-->
<!--                <div class="tree_item_label long-title-style" :title="item[defaultProps.name]" :class="{ 'activeColor': item[defaultProps.status] && !item[defaultProps.children] }">{{ item[defaultProps.name] }}</div>-->
<!--            </div>-->
<!--            <div class="tree_childern" v-show="item[defaultProps.status]">-->
<!--                <tree-->
<!--                  :list="item[defaultProps.children]"-->
<!--                  :defaultProps="defaultProps"-->
<!--                  @callback="callback"-->
<!--                />-->
<!--            </div>-->
<!--        </div>-->
<!--    </div>-->
    <div class="tree">
        <div v-for="(item, index) in list" :key="index" @click.stop="clickIten(item)">
        <div v-for="(item, index) of list" :key="index" @click.stop="clickIten(item)">
            <div class="tree_item">
                <i class="el-icon-caret-bottom" :class="{ 'activeColor': item.fsStatus === 1 }" v-show="item.fsStatus === 1 && item.childList.length > 0"></i>
                <i class="el-icon-caret-right color" v-show="item.childList.length > 0 && (item.fsStatus === 0 || !item.fsStatus)"></i>
                <div class="tree_item_label long-title-style" :title="item.name" :class="{ 'activeColor': item.fsDate === 1 && item.childList.length === 0 }">{{ item.name }}</div>
                <i class="el-icon-caret-bottom" :class="{ 'activeColor': item[defaultProps.status] }" v-show="item[defaultProps.status] && item[defaultProps.children]"></i>
                <i class="el-icon-caret-right color" v-show="item[defaultProps.children] && !item[defaultProps.status]"></i>
                <div class="tree_item_label long-title-style" :title="item[defaultProps.name]" :class="{ 'activeColor': item[defaultProps.status] && !item[defaultProps.children] }">{{ item[defaultProps.name] }}</div>
            </div>
<!--            v-show="item.status === 1"-->
            <div class="tree_childern" v-show="item.fsStatus === 1">
            <div class="tree_childern" v-show="item[defaultProps.status]">
                <tree
                    :list="item.childList"
                    :defaultProps="defaultProps"
                    @callback="callback"
                  :list="item[defaultProps.children]"
                  :defaultProps="defaultProps"
                  @callback="callback"
                />
                 <!-- @callback="callback" -->
            </div>
        </div>
    </div>
@@ -52,12 +36,12 @@
          name: 'name',
          status: 'status',
          children: 'children',
          id: 'erpId'
          id: 'id'
        }
      }
    }
  },
  data () {
  data() {
    return {
      tempItem: {
        id: null,
@@ -68,56 +52,44 @@
  methods: {
    // ç‚¹å‡»å½“前项
    clickIten (item) {
      this.recursion(this.list)
      item.fsDate === 0 || !item.fsDate ? item.fsDate = 1 : item.fsDate = 0
      if (item.childList.length > 0) {
        item.fsStatus === 0 || !item.fsStatus ? item.fsStatus = 1 : item.fsStatus = 0
      item[this.defaultProps.status] = !item[this.defaultProps.status]
      this.list.forEach(subItem => {
        if ((subItem[this.defaultProps.id] !== item[this.defaultProps.id] && subItem[this.defaultProps.status]) || (this.list.length === 1 && subItem[this.defaultProps.status] === false)) {
          subItem[this.defaultProps.status] = false
          if (subItem[this.defaultProps.children]) {
            this.recursion(subItem[this.defaultProps.children])
          }
        }
      })
      if (this.tempItem['id'] === item[this.defaultProps.id]) {
        this.tempItem = {
          id: null,
          name: null
        }
      } else {
        this.tempItem.id = item[this.defaultProps.id]
        this.tempItem.name = item[this.defaultProps.name]
      }
      // item[this.defaultProps.status] = !item[this.defaultProps.status]
      // this.list.forEach(subItem => {
      //   if ((subItem[this.defaultProps.id] !== item[this.defaultProps.id] && subItem[this.defaultProps.status]) || (this.list.length === 1 && subItem[this.defaultProps.status] === false)) {
      //     subItem[this.defaultProps.status] = false
      //     if (subItem[this.defaultProps.children]) {
      //       this.recursion(subItem[this.defaultProps.children])
      //     }
      //   }
      // })
      // if (this.tempItem.id === item[this.defaultProps.id]) {
      //   this.tempItem = {
      //     id: null,
      //     name: null
      //   }
      // } else {
      //   this.tempItem.id = item[this.defaultProps.id]
      //   this.tempItem.name = item[this.defaultProps.name]
      // }
      this.$emit('callback', item)
      this.$emit('callback', this.tempItem, item)
    },
    // é€’归方法
    recursion (children) {
      // children.forEach(item => {
      //   item[this.defaultProps.status] = false
      //   if (item[this.defaultProps.children]) {
      //     this.recursion(item[this.defaultProps.children])
      //   }
      // })
      children.forEach(item => {
        item.fsDate = 0
        if (item.childList.length > 0) {
          this.recursion(item.childList)
        item[this.defaultProps.status] = false
        if (item[this.defaultProps.children]) {
          this.recursion(item[this.defaultProps.children])
        }
      })
    },
    callback (data, item) {
      console.log('data', data)
      console.log('item', item)
      if (this.tempItem.id === data.id) {
        this.tempItem = {}
      } else {
        this.tempItem.id = data.erpId
        this.tempItem.id = data.id
        this.tempItem.name = data.name
      }
      this.$emit('callback', data, item)
      this.$emit('callback', this.tempItem, item)
    }
  }
}
admin/src/components/common/TreeSelect.vue
@@ -57,7 +57,7 @@
  }
  .vue-treeselect {
    line-height: 30px;
    /deep/ .vue-treeselect__control {
    ::v-deep .vue-treeselect__control {
      height: 32px;
      .vue-treeselect__single-value {
        line-height: 30px;
admin/src/components/common/UploadAvatarImage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
<template>
  <div>
    <el-upload
      class="avatar-uploader"
      accept=".png,.jpg"
      :style="customStyle"
      :action="uploadImgUrl"
      :data="uploadData"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
      :on-error="uploadError"
      :before-upload="beforeAvatarUpload">
      <img v-if=" file.imgurlfull" style="width: 100%;" :src="file.imgurlfull" :style="customStyle" class="avatar">
      <div v-else :style="customStyle">
        <i class="el-icon-plus avatar-uploader-icon"></i>
        <div class="tips-style">{{ tipsLabel }}</div>
      </div>
    </el-upload>
  </div>
</template>
<script>
export default {
  props: {
    file: {
      type: Object,
      default: () => {}
    },
    tipsLabel: '',
    customStyle: {
      type: String,
      default: 'width: 90px; height: 90px;'
    },
    uploadData: Object
  },
  data() {
    return {
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/public/upload'
    }
  },
  methods: {
    // ä¸Šä¼ å›¾ç‰‡
    handleAvatarSuccess(res, file) {
      if (res.code == 200) {
        let { data } = res
        this.file.imgurl = data.imgaddr;
        this.file.imgurlfull = data.url;
        this.$message.success('上传成功')
        this.$emit('uploadSuccess', { imgurl: data.imgaddr, imgurlfull: data.url, name: data.originname })
      } else {
        this.$tip.apiFailed('上传失败')
      }
      this.$emit('uploadEnd')
    },
    uploadError() {
      this.$tip.apiFailed('上传失败')
      this.$emit('endUpload')
    },
    // // æ‹¦æˆª
    beforeAvatarUpload(file) {
      this.$emit('uploadBegin')
      return true
    }
  }
}
</script>
<style lang="scss" scoped>
$image-width: 90px;
.avatar-uploader {
  width: $image-width;
  height: $image-width;
}
::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  line-height: 90px;
  font-size: 28px;
  color: #8c939d;
  width: $image-width;
  height: $image-width;
  text-align: center;
}
.avatar {
  width: 100% !important;
  height: auto !important;
  display: block;
}
.tips-style {
  height: 13px;
  font-size: 13px;
  font-weight: 400;
  color: #999999;
  line-height: 13px;
}
</style>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
</style>
admin/src/components/common/UploadAvatarVideo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
<template>
  <div>
    <el-upload
      class="avatar-uploader"
      accept=".mp4"
      :style="customStyle"
      :action="uploadImgUrl"
      :data="uploadData"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
      :on-error="uploadError"
      :before-upload="beforeAvatarUpload">
      <video v-if="file.videourlfull" :src="file.videourlfull" :style="customStyle" class="avatar" />
      <div v-else :style="customStyle">
        <i class="el-icon-plus avatar-uploader-icon"></i>
        <div class="tips-style">{{ tipsLabel }}</div>
      </div>
    </el-upload>
  </div>
</template>
<script>
export default {
  props: {
    file: {
      type: Object,
      default: () => {}
    },
    tipsLabel: '',
    customStyle: {
      type: String,
      default: 'width: 90px; height: 90px;'
    },
    uploadData: Object
  },
  data() {
    return {
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/public/upload'
    }
  },
  methods: {
    // ä¸Šä¼ å›¾ç‰‡
    handleAvatarSuccess(res, file) {
      if (res.code == 200) {
        let { data } = res
        this.file.videourl = data.imgaddr;
        this.file.videourlfull = data.url;
        this.$message.success('上传成功')
        this.$emit('uploadSuccess', { imgurl: data.imgaddr, imgurlfull: data.url, name: data.originname })
      } else {
        this.$tip.apiFailed('上传失败')
      }
      this.$emit('uploadEnd')
    },
    uploadError() {
      this.$tip.apiFailed('上传失败')
      this.$emit('endUpload')
    },
    // // æ‹¦æˆª
    beforeAvatarUpload(file) {
      this.$emit('uploadBegin')
      return true
    }
  }
}
</script>
<style lang="scss" scoped>
$image-width: 100px;
.avatar-uploader {
  width: $image-width;
  height: $image-width;
}
::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  width: $image-width;
  height: $image-width;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  line-height: 90px;
  font-size: 28px;
  color: #8c939d;
  width: $image-width;
  height: $image-width;
  text-align: center;
}
.avatar {
  width: $image-width;
  height: $image-width;
  display: block;
}
.tips-style {
  height: 13px;
  font-size: 13px;
  font-weight: 400;
  color: #999999;
  line-height: 13px;
}
</style>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
</style>
admin/src/components/common/UploadFile.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,123 @@
<template>
  <div>
    <el-upload
      class="upload-demo"
      :accept="uploadData.fileTyp"
      :action="uploadImgUrl"
      :limit="1"
      :on-exceed="handleExceed"
      :on-success="handleFileSuccess"
      :on-error="uploadError"
      :before-upload="beforeFileUpload"
      :file-list="fileList">
    <el-button size="small" type="primary">点击上传</el-button>
    <div slot="tip" class="el-upload__tip">只能上传{{ uploadData.fileType }}文件,且不超过5mb</div>
  </el-upload>
  </div>
</template>
<script>
export default {
  props: {
    file: {
      type: Object,
      default: () => {}
    },
    tipsLabel: '',
    customStyle: {
      type: String,
    default: 'width: 190px; height: 190px;'
    },
    uploadData: Object
  },
  data() {
    return {
      fileList:null,
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/public/upload?folder='+this.uploadData.folder
    }
  },
  methods: {
    // ä¸Šä¼ å›¾ç‰‡
    handleExceed(){},
    handleFileSuccess(res, file) {
      if (res.code == 200) {
        let { data } = res
        // this.fileList = [{name: data.originname, url: data.url }]
        this.$message.success('上传成功')
        this.$emit('uploadSuccess', { fileurl: data.imgaddr, fileurlFull: data.url, name: data.originname })
      } else {
        this.$tip.apiFailed('上传失败')
      }
      this.$emit('uploadEnd')
    },
    uploadError() {
      this.$tip.apiFailed('上传失败')
      this.$emit('endUpload')
    },
    // // æ‹¦æˆª
    beforeFileUpload(file) {
      this.$emit('uploadBegin')
      return true
    }
  }
}
</script>
<style lang="scss" scoped>
$image-width: 100px;
.avatar-uploader {
  width: $image-width;
  height: $image-width;
}
::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  width: $image-width;
  height: $image-width;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  line-height: 90px;
  font-size: 28px;
  color: #8c939d;
  width: $image-width;
  height: $image-width;
  text-align: center;
}
.avatar {
  width: $image-width;
  height: $image-width;
  display: block;
}
.tips-style {
  height: 13px;
  font-size: 13px;
  font-weight: 400;
  color: #999999;
  line-height: 13px;
}
</style>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
::v-deep .el-upload-list__item {
  width: 80% !important;
  height: 50px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
</style>
admin/src/components/common/UploadFileCommon.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,150 @@
<template>
  <div>
    <el-upload
      class="avatar-uploader"
      :accept="uploadData.fileTyp"
      :style="customStyle"
      :action="uploadImgUrl"
      :file="file1"
      :data="uploadData"
      :limit="1"
      :show-file-list="false"
      :on-success="handleSuccess"
      :on-error="uploadError"
      :before-upload="beforeAvatarUpload">
      <img v-if="file.fileType==0 && file.fileUrlFull" :src="file.fileUrlFull" style="width: 90px;height: 90px" class="avatar">
      <video v-if="file.fileType==1 &&file.fileUrlFull" :src="file.fileUrlFull" style="width: 90px;height: 90px" class="avatar" />
      <span v-if="file.fileType==2 &&file.fileUrlFull"  style="width: 90px;height: 90px" class="avatar" >{{file.fileName}}</span>
      <div class="desc_data_list_item_img" style="cursor: pointer; background: #8c939d;">
          <i  class="el-icon-plus"></i>
      </div>
    </el-upload>
  </div>
</template>
<script>
export default {
  props: {
    file: {
      type: Object,
      default: () => {}
    },
    tipsLabel: '',
    customStyle: {
      type: String,
      default: 'width: 90px; height: 90px;'
    },
    uploadData: Object
  },
  data() {
    return {
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/public/upload'
    }
  },
  methods: {
    // ä¸Šä¼ å›¾ç‰‡
    handleSuccess(res, file) {
      if (res.code == 200) {
        let { data } = res
        this.file.fileUrl = data.imgaddr
        this.file.fileType = data.type
        this.file.fileName= data.originname
        this.file.fileUrlFull = data.url
        this.$message.success('上传成功')
        this.$emit('uploadSuccess', { fileurl: data.imgaddr, fileUrlFull: data.url, name: data.originname })
      } else {
        this.$tip.apiFailed('上传失败')
      }
      this.$emit('uploadEnd')
    },
    uploadError() {
      this.$tip.apiFailed('上传失败')
      this.$emit('endUpload')
    },
    // // æ‹¦æˆª
    beforeAvatarUpload(file) {
      this.$emit('uploadBegin')
      return true
    }
  }
}
</script>
<style lang="scss" scoped>
.desc_data_list_item_img {
  flex-shrink: 0;
  width: 80px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  .el-icon-plus {
    font-size: 26px;
    color: #ffffff;
  }
  img {
    width: 100%;
    height: 100%;
  }
}
$image-width: 100px;
.avatar-uploader {
  width: $image-width;
  height: $image-width;
}
::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  width: $image-width;
  height: $image-width;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  line-height: 90px;
  font-size: 28px;
  color: #8c939d;
  width: $image-width;
  height: $image-width;
  text-align: center;
}
.avatar {
  width: $image-width;
  height: $image-width;
  display: block;
}
.tips-style {
  height: 13px;
  font-size: 13px;
  font-weight: 400;
  color: #999999;
  line-height: 13px;
}
</style>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
</style>
admin/src/components/common/UploadImage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
<template>
  <div>
    <el-upload
      :action="uploadImgUrl"
      :data="uploadData"
      list-type="picture-card"
      :file-list="fileList"
      accept=".jpg,.png"
      :before-upload="beforeUpload"
      :on-success="uploadSuccess"
      :on-error="fail"
    >
      <i class="el-icon-plus icon"></i>
      <div slot="file" slot-scope="{file}">
        <img
          class="el-upload-list__item-thumbnail"
          :src="file.url" alt=""
          style="width: 100px;height: 100px;"
        >
        <span class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in"></i>
          </span>
          <span
            class="el-upload-list__item-delete"
            @click="handleRemove(file)"
          >
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <el-image-viewer
      v-if="showViewer"
      :on-close="closeViewer"
      :initialIndex="tempIndex"
      :url-list="srcList"
      :z-index="3000"
    />
  </div>
</template>
<script>
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
export default {
  components: {
    ElImageViewer
  },
  props: {
    fileList: {
      type: Array,
      default: () => []
    },
    uploadData: Object,
  },
  data() {
    return {
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/public/uploadLocal',
      realList: [],
      srcList: [],
      tempIndex: 0,
      showViewer: false,
    }
  },
  watch: {
    fileList: {
      handler(val) {
        console.log(val);
        if (val.length==0) {
          this.realList = []
          this.srcList = []
        }
      }
    }
  },
  methods: {
    beforeUpload(file) {
      this.$emit('beginUpload')
      return true
    },
     // ä¸Šä¼ å›¾ç‰‡æˆåŠŸ
     uploadSuccess (res, file, fileList) {
      // console.log('this.fileList', this.fileList);
      // console.log('fileList', fileList);
      this.$emit('endUpload')
      this.realList = fileList
      this.srcList.push(res.data.url)
      // console.log('file', file);
      if (res.code === 200) {
        this.fileList.push(
          {
            fileurl: res.data.imgaddr,
            name: res.data.originname,
            url: res.data.url
          }
        )
      } else {
        this.$message.error(res.msg || '上传失败')
      }
    },
    fail (err, file, fileList) {
      this.$emit('endUpload')
      this.$message.error('上传失败')
    },
    handlePictureCardPreview(file) {
      // this.tempIndex = this.srcList.findIndex(item => item == file.response.data.url )
      // console.log(file);
      this.tempIndex = this.fileList.findIndex(item => item.url == file.url )
      // console.log( this.tempIndex);
      this.srcList = this.fileList.map(item => item.url)
      this.showViewer = true
    },
    closeViewer() {
      this.showViewer = false
    },
    handleRemove(file) {
      console.log(this.fileList);
      let tempIndex = this.realList.findIndex(item => item.url === file.url)
      // debugger
      this.realList.splice(tempIndex, 1)
      this.fileList.splice(tempIndex, 1)
      this.srcList.splice(tempIndex, 1)
    },
  },
}
</script>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
</style>
admin/src/components/common/myImage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
<template>
  <div>
    {{ src }}
    <img
      class="el-upload-list__item-thumbnail"
      :src="src" alt=""
      :style="`width: ${width}px;height: ${height}px;`"
      @click="handlePictureCardPreview()"
    >
    <el-image-viewer
      v-if="showViewer"
      :on-close="closeViewer"
      :initialIndex="tempIndex"
      :url-list="previewSrcList"
      :z-index="3000"
    />
  </div>
</template>
<script>
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
export default {
  components: {
    ElImageViewer
  },
  props: {
    src: {
      type: String,
      default: ''
    },
    width: {
      type: Number,
      default: 100
    },
    height: {
      type: Number,
      default: 100
    },
    previewSrcList: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      tempIndex: 0,
      showViewer: false,
    }
  },
  methods: {
    handlePictureCardPreview() {
      console.log(this.src);
      this.tempIndex = this.srcList.findIndex(item => item == this.src )
      this.showViewer = true
    },
    closeViewer() {
      this.showViewer = false
    },
  },
}
</script>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
::v-deep .el-upload-list__item {
  width: 90px !important;
  height: 90px !important;
}
</style>
admin/src/components/common/tagsview.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,261 @@
<template>
  <div class="tags-view-style" style="display:flex; overflow-x: scroll;">
    <i class="el-icon-arrow-left btn" v-if="leftStatus" :class="leftStatus?'nor-btn':'ban-btn'" @click="scrollToStart()"></i>
    <div id="tags-box" ref="tags">
      <div
        v-for="(item, index) in tags"
        :key="index"
        :id="'tags-box-' + index"
        @contextmenu.prevent="openMenu(item,$event)"
        :class="isActive(item.url,index)?'active':''"
        class="tagsview"
        @click="tagsmenu(item, index)"
      >
        {{ item.label }}
        <!-- è¿™ä¸ªåœ°æ–¹ä¸€å®šè¦click加个stop阻止,不然会因为事件冒泡一直触发父元素的点击事件,无法跳转另一个路由 -->
        <span v-if="tags.length > 1" class="el-icon-close tagsicon" @click.stop="handleClose(item,index)"></span>
        <!-- <ul v-show="visible" class="contextmenu" :style="{left:left+'px',top:top+'px'}">
          <li @click.stop="rightClose()">关闭</li>
          <li @click.stop="cleartags($route.path)">关闭其他</li>
        </ul> -->
      </div>
    </div>
    <i class="el-icon-arrow-right btn" v-if="rightStatus"  :class="rightStatus?'nor-btn':'ban-btn'" @click="scrollToEnd()"></i>
  </div>
</template>
<script>
//这个就是导入vuex的数据,配合下面...map用
import { mapState, mapMutations } from "vuex";
export default {
  data() {
    return {
      //右键菜单隐藏对应布尔值
      visible: false,
      //右键菜单对应位置
      top: 0,
      left: 0,
      leftStatus: false,
      rightStatus: false,
    }
  },
  computed: {
    //引入vuex中state中的tags数据,一样this调用就行
    ...mapState(["tags"]),
  },
  watch:{
    //监听右键菜单的值是否为true,如果是就创建全局监听点击事件,触发closeMenu事件隐藏菜单,如果是false就删除监听
    visible(value) {
      if (value) {
        document.body.addEventListener('click', this.closeMenu)
      } else {
        document.body.removeEventListener('click', this.closeMenu)
      }
    },
    $route(to,from){
      this.tags.forEach((item, index) => {
        if (item.url === to.path) {
          let tagsDiv = document.getElementById('tags-box')
          if (index) {
            tagsDiv.scrollTo(index * 110, 0)
          } else {
            tagsDiv.scrollTo(0, 0)
          }
        }
      })
    }
  },
  mounted() {
    this.$refs.tags.addEventListener('scroll', e => {
      if (this.$refs.tags.scrollLeft > 0) {
        this.leftStatus = true
      } else {
        this.leftStatus = false
      }
      if (this.$refs.tags.scrollLeft + this.$refs.tags.clientWidth < this.$refs.tags.scrollWidth) {
       this.rightStatus = true
      } else {
        this.rightStatus = false
      }
    }, false)
  },
  methods: {
    //引入vuex中mutation方法,可以直接this.xxx调用他
    ...mapMutations(["closeTab", "cleartagsview"]),
    //点击叉叉删除的事件
    rightClose() {
      this.visible = false
      if (this.tags.length == 1) {
        return
      }
      let index = this.tags.indexOf(this.selectedTag)
      this.handleClose(this.selectedTag, index)
    },
    handleClose(item, index) {
      if (this.tags.length == 1) {
        return
      }
      //先把长度保存下来后面用来比较做判断条件
      let length = this.tags.length - 1;
      //vuex调方法,上面...map引入的vuex方法,不会这种方法的看vue官网文档
      this.closeTab(item);
      // å¦‚果关闭的标签不是当前路由的话,就不跳转
      if (item.url !== this.$route.path) {
        return;
      }
      // åˆ¤æ–­ï¼šå¦‚æžœindex和length是一样的,那就代表都是一样的长度,就是最后一位,那就往左跳转一个
      if (index === length) {
        //再判断:如果length=0,也就是说你删完了所有标签
        if (length === 0) {
          //那么再判断:如果当前路由不等于index,也就是我首页的路由
          if (this.$route.path !== "/index") {
            //那么就跳转首页。这一步的意思是:如果删除的最后一个标签不是首页就统一跳转首页,如果你删除的最后一个标签是首页标签,已经在这个首页路由上了,你还跳个什么呢。这不重复操作了吗。
            this.$router.push({ path: "/index" });
          }
        } else {
          //那么,如果上面的条件都不成立,没有length=0.也就是说你还有好几个标签,并且你删除的是最后一位标签,那么就往左边挪一位跳转路由
          this.$router.push({ path: this.tags[index - 1].url });
        }
      } else {
        // å¦‚果你点击不是最后一位标签,点的前面的,那就往右边跳转
        this.$router.push({ path: this.tags[index].url });
      }
    },
    //点击跳转路由
    tagsmenu(item, index) {
      console.log('tagsmenu');
      //判断:当前路由不等于当前选中项的url,也就代表你点击的不是现在选中的标签,是另一个标签就跳转过去,如果你点击的是现在已经选中的标签就不用跳转了,因为你已经在这个路由了还跳什么呢。
      if (this.$route.path !== item.url) {
        //用path的跳转方法把当前项的url当作地址跳转。
        this.$router.push({ path: item.url });
        let tagsDiv = document.getElementById('tags-box')
        if (index) {
          tagsDiv.scrollTo(index * 110, 0)
        }
      }
    },
    //通过判断路由一致返回布尔值添加class,添加高亮效果
    isActive(route, index) {
      let res = route === this.$route.path
      return res
    },
    scrollToStart() {
      let tagsDiv = document.getElementById('tags-box')
      tagsDiv.scrollTo(0, 0)
    },
    scrollToEnd() {
      let tagsDiv = document.getElementById('tags-box')
      tagsDiv.scrollTo(tagsDiv.scrollWidth, 0)
    },
    //右键事件,显示右键菜单,并固定好位置。
    openMenu(tag, e) {
      this.visible = true
      this.selectedTag = tag
      const offsetLeft = this.$el.getBoundingClientRect().left
      console.log(tag, e);
      this.left = e.clientX - offsetLeft + 60  //右键菜单距离左边的距离
      this.top = e.clientY +20  //右键菜单距离上面的距离           è¿™ä¸¤ä¸ªå¯ä»¥æ›´æ”¹ï¼Œçœ‹çœ‹è‡ªå·±çš„右键菜单在什么位置,自己调
    },
    //隐藏右键菜单
    closeMenu() {
      this.visible = false
    },
    //右键菜单关闭所有选项,触发vuex中的方法,把当前路由当参数传过去用于判断
    cleartags(val){
      this.visible = false
      this.cleartagsview(val)
    }
  },
};
</script>
<style lang="scss" scoped>
.btn {
  font-size: 20px;
  line-height: 48px;
  height: 48px;
}
.nor-btn {
  color: #666;
  cursor: pointer;
  &:hover {
    color: #2E68EC;
  }
}
.ban-btn {
  color: #999;
  cursor:not-allowed
}
#tags-box {
  overflow-x: hidden;
  white-space: nowrap;
  flex: 1;
  // width: 240px;
  scrollbar-width: none; /* firefox */
  -ms-overflow-style: none; /* IE 10+ */
  &::-webkit-scrollbar {
      display: none; /* Chrome Safari */
    }
}
#tags-box::-webkit-scrollbar {
    display: none; /* Chrome Safari */
}
//标签导航样式
.tagsview {
  cursor: pointer;
  // margin-left: 4px;
  height: 48px;
  line-height: 48px;
  padding: 0 8px 0 24px;
  // border: 1px solid #d8dce5;
  // border-radius: 5px;
  color: #000;
  font-size: 14px;
  display: inline-block;
}
//叉号鼠标经过样式
.tagsicon:hover{
  color: #f56c6c;
}
//标签高亮
.active{
  color: #2E68EC;
  border-bottom: 2px solid #2E68EC;
}
//右键菜单样式
.contextmenu {
  margin: 0;
  background: #fff;
  z-index: 100;
  position: absolute;
  list-style-type: none;
  padding: 5px 0;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 400;
  color: #333;
  box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
  li {
    margin: 0;
    padding: 7px 16px;
    cursor: pointer;
    &:hover {
      background: #eee;
    }
  }
}
.tags-view-style {
  scrollbar-width: none; /* firefox */
  -ms-overflow-style: none; /* IE 10+ */
  &::-webkit-scrollbar {
    display: none; /* Chrome Safari */
  }
}
</style>
admin/src/components/common/upload.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,141 @@
<template>
    <div class="file">
        <div class="file_list">
            <div class="file_list_item" :style="{width: width, height: height}" v-for="(item, index) in list" :key="index">
                <div class="dele" @click="deleItem(index)">
                    <i class="el-icon-close"></i>
                </div>
                <img :src="item.url" v-if="fileType(item.url) === 'img'" />
                <video controls autoplay :src="item.url" v-else></video>
            </div>
            <div class="file_list_item" :style="{width: width, height: height, cursor: 'pointer'}" @click="$refs.file.click()">
                <i class="el-icon-plus"></i>
            </div>
        </div>
        <input type="file" ref="file" :accept="accept" @change="getFile" />
    </div>
</template>
<script>
    import axios from 'axios';
    export default {
        props: {
            width: {
                type: String,
                default: '90px'
            },
            height: {
                type: String,
                default: '90px'
            },
            list: {
                type: Array,
                default: []
            },
            accept: {
                type: String,
                default: ''
            },
            folder: {
                type: String,
                default: ''
            }
        },
        data() {
            return {
                uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/public/upload'
            }
        },
        methods: {
            fileType(url) {
                if (url.indexOf('.mp4') !== -1) {
                    return 'video'
                } else {
                    return 'img'
                }
            },
            getFile(e) {
                if (e.target && e.target.files.length > 0) {
                    this.$emit('loading')
                    const formdate = new FormData()
                    formdate.append('file', e.target.files[0])
                    formdate.append('folder', this.folder)
                    axios.post(this.uploadImgUrl, formdate)
                        .then(res => {
                            this.$emit('success', res.data.data)
                        })
                        .catch(e => {
                            this.$message.error(e)
                        })
                        .finally(() => {
                            this.$refs.file.value = null
                        })
                }
            },
            deleItem(index) {
                this.$emit('dele', index)
            }
        }
    }
</script>
<style lang="scss" scoped>
    .file {
        /*width: 100%;*/
        /*height: 90px;*/
        margin: 10px 0;
        input {
            opacity: 0;
        }
        .file_list {
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            .file_list_item {
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                overflow: hidden;
                border-radius: 5px;
                border: 1px solid #d5d5d5;
                margin-left: 15px;
                position: relative;
                &:first-child {
                    margin: 0 !important;
                }
                .dele {
                    position: absolute;
                    right: 0;
                    top: 0;
                    width: 20px;
                    height: 20px;
                    background: red;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    cursor: pointer;
                    .el-icon-close {
                        color: #ffffff;
                        font-size: 19px;
                    }
                }
                .el-icon-plus {
                    font-size: 30px;
                    color: black;
                }
                img {
                    width: 100%;
                }
                video {
                    width: 100%;
                    height: 100%;
                }
            }
        }
    }
</style>
admin/src/layouts/AppLayout.vue
@@ -1,31 +1,53 @@
<template>
  <el-container class="app-layout">
    <el-aside :class="{collapse:menuData.collapse}">
      <Menu/>
    </el-aside>
    <el-main>
      <header>
        <AppHeader/>
      </header>
      <main>
        <transition name="fade">
          <router-view></router-view>
        </transition>
      </main>
    </el-main>
  </el-container>
  <div>
    <CommonHeader />
    <div style="height:10px; background: #fff"></div>
    <el-container class="app-layout">
      <el-aside :class="{collapse:menuData.collapse}">
        <Menu/>
      </el-aside>
      <el-main>
        <header>
          <AppHeader/>
        </header>
        <div style="height:10px;"></div>
        <main ref="containerS">
          <transition name="fade">
<!--            <keep-alive>-->
              <router-view></router-view>
<!--            </keep-alive>-->
          </transition>
        </main>
      </el-main>
    </el-container>
  </div>
</template>
<script>
import { mapState } from 'vuex'
import Header from '@/components/common/Header'
import CommonHeader from '@/components/common/CommonHeader'
import Menu from '@/components/common/Menu'
export default {
  name: 'DefaultLayout',
  components: { AppHeader: Header, Menu },
  components: { AppHeader: Header, Menu, CommonHeader },
  data() {
    return {
      isFinishData: false,
        orgBackground: ''
    }
  },
  computed: {
    ...mapState(['menuData'])
  }
    ...mapState(['menuData', 'userInfo'])
  },
    mounted() {
    },
    methods: {
  },
}
</script>
@@ -34,17 +56,27 @@
.el-container {
  background: #F7F8F9;
  height: 100%;
  display: flex;
  overflow: hidden;
  // overflow: hidden;
  overflow: scroll;
  // å·¦è¾¹èœå•
  .el-aside {
    width: 250px !important;
    width: $menu-width !important;
    flex-shrink: 0;
    height: 100%;
    overflow-y: auto;
    // height: 100%;
    // height: 900px;
    height: calc(100vh - 80px);
    overflow-y: scroll;
    overflow-x: hidden;
    background: $primary-color;
    color: #fff;
    transition: width ease .3s;
    scrollbar-width: none; /* firefox */
    -ms-overflow-style: none; /* IE 10+ */
    &::-webkit-scrollbar {
      display: none; /* Chrome Safari */
    }
    &.collapse {
      width: 64px !important;
    }
@@ -52,18 +84,26 @@
  // å³è¾¹å†…容
  .el-main {
    width: 100%;
    height: 100%;
    // height: 100%;
    height: calc(100vh - 90px);
    padding: 0;
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    overflow-y: scroll;
    overflow-x: hidden;
    scrollbar-width: none; /* firefox */
    -ms-overflow-style: none; /* IE 10+ */
    &::-webkit-scrollbar {
      display: none; /* Chrome Safari */
    }
    & > header {
      height: $header-height;
      height: 48px;
      flex-shrink: 0;
    }
    & > main {
      height: 100%;
        box-sizing: border-box;
      overflow-y: auto;
    }
  }
@@ -81,4 +121,33 @@
  transition: all .5s;
  position: absolute;
}
.comfirm {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 1000;
  .container {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    background-color: #fff;
    width: 500px;
    height: 120px;
    padding: 30px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    .complete {
      display: flex;
      flex-direction: row-reverse;
    }
  }
}
</style>
admin/src/layouts/TableLayout.vue
@@ -1,11 +1,11 @@
<template>
  <div class="table-layout">
    <!-- å¤´éƒ¨ -->
    <div v-if="withBreadcrumb" class="table-header">
<!--    <div v-if="withBreadcrumb" class="table-header">
      <el-breadcrumb separator="/">
        <el-breadcrumb-item v-for="path in paths" :key="path">{{path}}</el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    </div>-->
    <Profile :roles="roles" :permissions="permissions">
      <!-- æœç´¢è¡¨å•部分 -->
      <div class="table-search-form">
admin/src/layouts/TableLayout1.vue
@@ -1,11 +1,11 @@
<template>
    <div class="table-layout">
        <!-- å¤´éƒ¨ -->
        <div v-if="withBreadcrumb" class="table-header">
<!--        <div v-if="withBreadcrumb" class="table-header">
            <el-breadcrumb separator="/">
                <el-breadcrumb-item v-for="path in paths" :key="path">{{path}}</el-breadcrumb-item>
            </el-breadcrumb>
        </div>
        </div>-->
        <Profile :roles="roles" :permissions="permissions">
            <div style="width: 100%; height: 100%; padding: 0 16px; box-sizing: border-box; display: flex; align-items: center; justify-content: space-between;">
                <div style="width: 300px; height: 100%; flex-shrink: 0; background: #ffffff;">
admin/src/plugins/messagebox.js
@@ -3,16 +3,16 @@
export default {
  ...MessageBox,
  // åˆ é™¤äºŒæ¬¡ç¡®è®¤
  actionConfirm (title,message) {
    return MessageBox.confirm(message, title, {
      confirmButtonText: '确认',
  deleteConfirm (message) {
    return MessageBox.confirm(message, '删除提醒', {
      confirmButtonText: '确认删除',
      cancelButtonText: '取消',
      type: 'warning'
    })
  },
  deleteConfirm (message) {
    return MessageBox.confirm(message, '删除提醒', {
      confirmButtonText: '确认删除',
  resetConfirm (message) {
    return MessageBox.confirm(message, '重置提醒', {
      confirmButtonText: '确认重置',
      cancelButtonText: '取消',
      type: 'warning'
    })
@@ -32,5 +32,37 @@
      cancelButtonText: '取消',
      type: 'warning'
    })
  },
  // å®Œå–„提醒
  messageApprove (message) {
    return MessageBox.confirm(message, '审核提醒', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
  },
    // é—®å·ç¡®å®žæé†’
  messageWaring (message, title, confirmText='确定', cancelText='取消') {
    return MessageBox.confirm(message, title, {
      confirmButtonText: confirmText,
      cancelButtonText: cancelText,
      type: 'warning'
    })
  },
    // é—®å·ç¡®å®žæé†’
  messageConfirm (message, confirmText='确定', cancelText='取消') {
    return MessageBox.confirm(message, "操作确认", {
      confirmButtonText: confirmText,
      cancelButtonText: cancelText,
      type: 'warning'
    })
  },
  // ç¡®è®¤æ˜¯å¦æœåŠ¡è¯¥ä¼ä¸š
  cancelOrder (message) {
    return MessageBox.confirm(message, '取消提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
  }
}
admin/src/store/index.js
@@ -13,7 +13,11 @@
    list: [],
    // æ˜¯å¦æ”¶èµ·
    collapse: false
  }
  },
  //tags数组
  tags:[],
  //tagsview标签显示隐藏
  isCollapse:false
}
const mutations = {
@@ -28,8 +32,12 @@
  },
  // è®¾ç½®å·²ç™»å½•的用户信息
  setUserInfo: (state, data) => {
    state.userInfo = data
    state.userInfo = {
      ...state.userInfo,
      ...data
    }
  },
  // è®¾ç½®é¦–页路由信息
  setHomePage (state, homePage) {
    state.homePage = homePage
@@ -37,6 +45,37 @@
  // é‡ç½®èœå•
  resetMenus: (state) => {
    state.menuData.list = []
  },
  //  tags
  pushtags(state,val){
    //如果等于-1说明tabs不存在那么插入,否则什么都不做
    //findindex找角标,循环判断一下,如果等于那么就代表有相同的,就不必添加,如果找不到那就是-1.就添加
    let result = state.tags.findIndex(item => item.label === val.label)
    if (result === -1) {
      state.tags.push({...val, keepAlive: false})
    } else {
      state.tags[result]= {...val, keepAlive: true}
    }
    // result === -1 ? state.tags.push(val) : (state.tags[result]==val)
  },
  //关闭标签
  closeTab(state, val) {
    //同上,找角标,然后用角标的位置对应删除一位。splice:这是数组的删除方法
    let result = state.tags.findIndex(item => item.label === val.label)
    state.tags.splice(result, 1)
  },
  //关闭所有tagsview标签
  cleartagsview(state,val){
    //清空数组
    state.tags=[]
    //跳转到首页,val接受传过来的当前路由
    if(val !== "/index"){
      router.push({path:"/index"})
    }
  },
  //改变tagsview显示隐藏
  changeisshow(state){
    state.isCollapse=!state.isCollapse
  }
}
const actions = {}
admin/vue.config.js
@@ -18,7 +18,8 @@
        // https://dmtest.ahapp.net/admin_api   æµ‹è¯•服
        // http://10.10.99.63/admin_interface/  æœ€æ–°æµ‹è¯•服(内网)
        // http://218.23.218.228:8018/admin_interface   æœ€æ–°æµ‹è¯•服(外网)
        target: 'http://218.23.218.228:8018/admin_interface',
        // target: 'http://218.23.218.228:8018/admin_interface',
        target: 'http://localhost:10028',
        changeOrigin: true,
        pathRewrite: {
          [`^${[process.env.VUE_APP_API_PREFIX]}`]: ''
server/dmvisit_admin/src/main/java/com/doumee/task/ScheduleTool.java
@@ -26,8 +26,8 @@
 * @date 2021-10-10 14:40:35
 * https://www.bejson.com/othertools/cron/  cron è¡¨è¾¾å¼ç”Ÿæˆåœ°å€
 */
@Component
@EnableScheduling
//@Component
//@EnableScheduling
public class ScheduleTool {
    @Autowired
server/dmvisit_admin/src/main/resources/application.yml
@@ -10,7 +10,7 @@
  #  application:
  #    name: doumeemes
  profiles:
    active: testHS
    active: dev
  # JSON返回配置
  jackson:
server/dmvisit_web/src/main/resources/application.yml
@@ -10,7 +10,7 @@
  #  application:
  #    name: doumeemes
  profiles:
    active: testHS
    active: dev
  # JSON返回配置
  jackson: