linan 4 年之前
当前提交
7727142f87
共有 63 个文件被更改,包括 24090 次插入0 次删除
  1. 2 0
      .browserslistrc
  2. 3 0
      .env.development
  3. 3 0
      .env.production
  4. 18 0
      .eslintrc.js
  5. 20 0
      .gitignore
  6. 17 0
      .vscode/cc.code-snippets
  7. 4 0
      .vscode/settings.json
  8. 4 0
      README.md
  9. 3 0
      babel.config.js
  10. 995 0
      element-variables.scss
  11. 4990 0
      package-lock.json
  12. 46 0
      package.json
  13. 5 0
      postcss.config.js
  14. 二进制
      public/favicon.ico
  15. 22 0
      public/index.html
  16. 387 0
      public/libs/H264SPSParser.js
  17. 667 0
      public/libs/H264Session.js
  18. 108 0
      public/libs/videoWorker.js
  19. 24 0
      src/App.vue
  20. 83 0
      src/api/breed.js
  21. 32 0
      src/api/fileInfo.js
  22. 11 0
      src/api/login.js
  23. 36 0
      src/api/material.js
  24. 34 0
      src/api/production.js
  25. 5 0
      src/assets/css/reset.scss
  26. 二进制
      src/assets/deliveryRoom_1.png
  27. 二进制
      src/assets/deliveryRoom_2.png
  28. 二进制
      src/assets/deliveryRoom_3.png
  29. 二进制
      src/assets/deliveryRoom_4.png
  30. 二进制
      src/assets/login_bg.jpg
  31. 二进制
      src/assets/logo.png
  32. 1 0
      src/assets/logo2.png
  33. 127 0
      src/components/uploadImg/test.vue
  34. 118 0
      src/components/uploadImg/uploadImg.vue
  35. 27 0
      src/main.js
  36. 11 0
      src/module.js
  37. 43 0
      src/router/index.js
  38. 70 0
      src/router/routes.js
  39. 95 0
      src/sdk/ajax.js
  40. 6 0
      src/sdk/config.js
  41. 78 0
      src/store/index.js
  42. 153 0
      src/store/publicType.js
  43. 7 0
      src/store/store-module.js
  44. 234 0
      src/views/Home/Home.vue
  45. 114 0
      src/views/Home/mencCofig.js
  46. 167 0
      src/views/Login/Login.vue
  47. 52 0
      src/views/aaaaaaaa.vue
  48. 285 0
      src/views/breed/collectSeedLog.vue
  49. 215 0
      src/views/breed/commoditySheepFile.vue
  50. 263 0
      src/views/breed/matingLog.vue
  51. 259 0
      src/views/breed/matingSuccLog.vue
  52. 244 0
      src/views/breed/offFieldLog.vue
  53. 253 0
      src/views/breed/parturitionLog.vue
  54. 281 0
      src/views/breed/pregnancyTestLog.vue
  55. 303 0
      src/views/breed/seedSheepFile.vue
  56. 283 0
      src/views/breed/shiftFieldLog.vue
  57. 236 0
      src/views/breed/weaningLog.vue
  58. 209 0
      src/views/fileInfo/areaInfo.vue
  59. 121 0
      src/views/fileInfo/firmInfo.vue
  60. 120 0
      src/views/fileInfo/pastureInfo.vue
  61. 231 0
      src/views/fileInfo/workerInfo.vue
  62. 30 0
      vue.config.js
  63. 11935 0
      yarn.lock

+ 2 - 0
.browserslistrc

@@ -0,0 +1,2 @@
+> 1%
+last 2 versions

+ 3 - 0
.env.development

@@ -0,0 +1,3 @@
+# 本地开发模式
+# 以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。
+VUE_APP_TITLE=vue-module

+ 3 - 0
.env.production

@@ -0,0 +1,3 @@
+# 生产模式
+# 以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。
+VUE_APP_TITLE=vue-module

+ 18 - 0
.eslintrc.js

@@ -0,0 +1,18 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true
+  },
+  extends: ['plugin:vue/essential'],
+  rules: {
+    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
+  },
+  parserOptions: {
+    parser: 'babel-eslint'
+  },
+  globals: {
+    'AMap': false,
+    'AMapUI': false
+  }
+}

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+.DS_Store
+node_modules
+/dist
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 17 - 0
.vscode/cc.code-snippets

@@ -0,0 +1,17 @@
+{
+	// Place your huimv.cloud.client 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and 
+	// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope 
+	// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is 
+	// used to trigger the snippet and the body will be expanded and inserted. Possible variables are: 
+	// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. 
+	// Placeholders with the same ids are connected.
+	// Example:
+	"Print to console": {
+		"scope": "javascript,typescript",
+		"prefix": "cc",
+		"body": [
+			"console.log($1)",
+		],
+		"description": "Log output to console"
+	}
+}

+ 4 - 0
.vscode/settings.json

@@ -0,0 +1,4 @@
+{
+  "prettier.semi": false,
+  "prettier.singleQuote": true
+}

+ 4 - 0
README.md

@@ -0,0 +1,4 @@
+# vue-module
+
+适用于[vue-module-loader](https://github.com/mqhe2007/vue-module-loader)的微前端模块工程
+

+ 3 - 0
babel.config.js

@@ -0,0 +1,3 @@
+module.exports = {
+  presets: ["@vue/cli-plugin-babel/preset"]
+};

+ 995 - 0
element-variables.scss

@@ -0,0 +1,995 @@
+/* Element Chalk Variables */
+
+// Special comment for theme configurator
+// type|skipAutoTranslation|Category|Order
+// skipAutoTranslation 1
+
+/* Transition
+-------------------------- */
+$--all-transition: all .3s cubic-bezier(.645,.045,.355,1) !default;
+$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
+$--fade-linear-transition: opacity 200ms linear !default;
+$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
+$--border-transition-base: border-color .2s cubic-bezier(.645,.045,.355,1) !default;
+$--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1) !default;
+
+/* Color
+-------------------------- */
+/// color|1|Brand Color|0
+// $--color-primary: #409EFF !default;
+$--color-primary: #029B62 !default;
+/// color|1|Background Color|4
+$--color-white: #FFFFFF !default;
+/// color|1|Background Color|4
+$--color-black: #000000 !default;
+$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
+$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
+$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
+$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
+$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
+$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
+$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
+$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
+$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
+/// color|1|Functional Color|1
+$--color-success: #67C23A !default;
+/// color|1|Functional Color|1
+$--color-warning: #E6A23C !default;
+/// color|1|Functional Color|1
+$--color-danger: #F56C6C !default;
+/// color|1|Functional Color|1
+$--color-info: #909399 !default;
+
+$--color-success-light: mix($--color-white, $--color-success, 80%) !default;
+$--color-warning-light: mix($--color-white, $--color-warning, 80%) !default;
+$--color-danger-light: mix($--color-white, $--color-danger, 80%) !default;
+$--color-info-light: mix($--color-white, $--color-info, 80%) !default;
+
+$--color-success-lighter: mix($--color-white, $--color-success, 90%) !default;
+$--color-warning-lighter: mix($--color-white, $--color-warning, 90%) !default;
+$--color-danger-lighter: mix($--color-white, $--color-danger, 90%) !default;
+$--color-info-lighter: mix($--color-white, $--color-info, 90%) !default;
+/// color|1|Font Color|2
+$--color-text-primary: #303133 !default;
+/// color|1|Font Color|2
+$--color-text-regular: #606266 !default;
+/// color|1|Font Color|2
+$--color-text-secondary: #909399 !default;
+/// color|1|Font Color|2
+$--color-text-placeholder: #C0C4CC !default;
+/// color|1|Border Color|3
+$--border-color-base: #DCDFE6 !default;
+/// color|1|Border Color|3
+$--border-color-light: #E4E7ED !default;
+/// color|1|Border Color|3
+$--border-color-lighter: #EBEEF5 !default;
+/// color|1|Border Color|3
+$--border-color-extra-light: #F2F6FC !default;
+
+// Background
+/// color|1|Background Color|4
+$--background-color-base: #F5F7FA !default;
+
+/* Link
+-------------------------- */
+$--link-color: $--color-primary-light-2 !default;
+$--link-hover-color: $--color-primary !default;
+
+/* Border
+-------------------------- */
+$--border-width-base: 1px !default;
+$--border-style-base: solid !default;
+$--border-color-hover: $--color-text-placeholder !default;
+$--border-base: $--border-width-base $--border-style-base $--border-color-base !default;
+/// borderRadius|1|Radius|0
+$--border-radius-base: 4px !default;
+/// borderRadius|1|Radius|0
+$--border-radius-small: 2px !default;
+/// borderRadius|1|Radius|0
+$--border-radius-circle: 100% !default;
+/// borderRadius|1|Radius|0
+$--border-radius-zero: 0 !default;
+
+// Box-shadow
+/// boxShadow|1|Shadow|1
+$--box-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04) !default;
+// boxShadow|1|Shadow|1
+$--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12) !default;
+/// boxShadow|1|Shadow|1
+$--box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !default;
+
+/* Fill
+-------------------------- */
+$--fill-base: $--color-white !default;
+
+/* Typography
+-------------------------- */
+$--font-path: 'fonts' !default;
+$--font-display: 'auto' !default;
+/// fontSize|1|Font Size|0
+$--font-size-extra-large: 20px !default;
+/// fontSize|1|Font Size|0
+$--font-size-large: 18px !default;
+/// fontSize|1|Font Size|0
+$--font-size-medium: 16px !default;
+/// fontSize|1|Font Size|0
+$--font-size-base: 14px !default;
+/// fontSize|1|Font Size|0
+$--font-size-small: 13px !default;
+/// fontSize|1|Font Size|0
+$--font-size-extra-small: 12px !default;
+/// fontWeight|1|Font Weight|1
+$--font-weight-primary: 500 !default;
+/// fontWeight|1|Font Weight|1
+$--font-weight-secondary: 100 !default;
+/// fontLineHeight|1|Line Height|2
+$--font-line-height-primary: 24px !default;
+/// fontLineHeight|1|Line Height|2
+$--font-line-height-secondary: 16px !default;
+$--font-color-disabled-base: #bbb !default;
+/* Size
+-------------------------- */
+$--size-base: 14px !default;
+
+/* z-index
+-------------------------- */
+$--index-normal: 1 !default;
+$--index-top: 1000 !default;
+$--index-popper: 2000 !default;
+
+/* Disable base
+-------------------------- */
+$--disabled-fill-base: $--background-color-base !default;
+$--disabled-color-base: $--color-text-placeholder !default;
+$--disabled-border-base: $--border-color-light !default;
+
+/* Icon
+-------------------------- */
+$--icon-color: #666 !default;
+$--icon-color-base: $--color-info !default;
+
+/* Checkbox
+-------------------------- */
+/// fontSize||Font|1
+$--checkbox-font-size: 14px !default;
+/// fontWeight||Font|1
+$--checkbox-font-weight: $--font-weight-primary !default;
+/// color||Color|0
+$--checkbox-font-color: $--color-text-regular !default;
+$--checkbox-input-height: 14px !default;
+$--checkbox-input-width: 14px !default;
+/// borderRadius||Border|2
+$--checkbox-border-radius: $--border-radius-small !default;
+/// color||Color|0
+$--checkbox-background-color: $--color-white !default;
+$--checkbox-input-border: $--border-base !default;
+
+/// color||Color|0
+$--checkbox-disabled-border-color: $--border-color-base !default;
+$--checkbox-disabled-input-fill: #edf2fc !default;
+$--checkbox-disabled-icon-color: $--color-text-placeholder !default;
+
+$--checkbox-disabled-checked-input-fill: $--border-color-extra-light !default;
+$--checkbox-disabled-checked-input-border-color: $--border-color-base !default;
+$--checkbox-disabled-checked-icon-color: $--color-text-placeholder !default;
+
+/// color||Color|0
+$--checkbox-checked-font-color: $--color-primary !default;
+$--checkbox-checked-input-border-color: $--color-primary !default;
+/// color||Color|0
+$--checkbox-checked-background-color: $--color-primary !default;
+$--checkbox-checked-icon-color: $--fill-base !default;
+
+$--checkbox-input-border-color-hover: $--color-primary !default;
+/// height||Other|4
+$--checkbox-bordered-height: 40px !default;
+/// padding||Spacing|3
+$--checkbox-bordered-padding: 9px 20px 9px 10px !default;
+/// padding||Spacing|3
+$--checkbox-bordered-medium-padding: 7px 20px 7px 10px !default;
+/// padding||Spacing|3
+$--checkbox-bordered-small-padding: 5px 15px 5px 10px !default;
+/// padding||Spacing|3
+$--checkbox-bordered-mini-padding: 3px 15px 3px 10px !default;
+$--checkbox-bordered-medium-input-height: 14px !default;
+$--checkbox-bordered-medium-input-width: 14px !default;
+/// height||Other|4
+$--checkbox-bordered-medium-height: 36px !default;
+$--checkbox-bordered-small-input-height: 12px !default;
+$--checkbox-bordered-small-input-width: 12px !default;
+/// height||Other|4
+$--checkbox-bordered-small-height: 32px !default;
+$--checkbox-bordered-mini-input-height: 12px !default;
+$--checkbox-bordered-mini-input-width: 12px !default;
+/// height||Other|4
+$--checkbox-bordered-mini-height: 28px !default;
+
+/// color||Color|0
+$--checkbox-button-checked-background-color: $--color-primary !default;
+/// color||Color|0
+$--checkbox-button-checked-font-color: $--color-white !default;
+/// color||Color|0
+$--checkbox-button-checked-border-color: $--color-primary !default;
+
+
+
+/* Radio
+-------------------------- */
+/// fontSize||Font|1
+$--radio-font-size: $--font-size-base !default;
+/// fontWeight||Font|1
+$--radio-font-weight: $--font-weight-primary !default;
+/// color||Color|0
+$--radio-font-color: $--color-text-regular !default;
+$--radio-input-height: 14px !default;
+$--radio-input-width: 14px !default;
+/// borderRadius||Border|2
+$--radio-input-border-radius: $--border-radius-circle !default;
+/// color||Color|0
+$--radio-input-background-color: $--color-white !default;
+$--radio-input-border: $--border-base !default;
+/// color||Color|0
+$--radio-input-border-color: $--border-color-base !default;
+/// color||Color|0
+$--radio-icon-color: $--color-white !default;
+
+$--radio-disabled-input-border-color: $--disabled-border-base !default;
+$--radio-disabled-input-fill: $--disabled-fill-base !default;
+$--radio-disabled-icon-color: $--disabled-fill-base !default;
+
+$--radio-disabled-checked-input-border-color: $--disabled-border-base !default;
+$--radio-disabled-checked-input-fill: $--disabled-fill-base !default;
+$--radio-disabled-checked-icon-color: $--color-text-placeholder !default;
+
+/// color||Color|0
+$--radio-checked-font-color: $--color-primary !default;
+/// color||Color|0
+$--radio-checked-input-border-color: $--color-primary !default;
+/// color||Color|0
+$--radio-checked-input-background-color: $--color-white !default;
+/// color||Color|0
+$--radio-checked-icon-color: $--color-primary !default;
+
+$--radio-input-border-color-hover: $--color-primary !default;
+
+$--radio-bordered-height: 40px !default;
+$--radio-bordered-padding: 12px 20px 0 10px !default;
+$--radio-bordered-medium-padding: 10px 20px 0 10px !default;
+$--radio-bordered-small-padding: 8px 15px 0 10px !default;
+$--radio-bordered-mini-padding: 6px 15px 0 10px !default;
+$--radio-bordered-medium-input-height: 14px !default;
+$--radio-bordered-medium-input-width: 14px !default;
+$--radio-bordered-medium-height: 36px !default;
+$--radio-bordered-small-input-height: 12px !default;
+$--radio-bordered-small-input-width: 12px !default;
+$--radio-bordered-small-height: 32px !default;
+$--radio-bordered-mini-input-height: 12px !default;
+$--radio-bordered-mini-input-width: 12px !default;
+$--radio-bordered-mini-height: 28px !default;
+
+/// fontSize||Font|1
+$--radio-button-font-size: $--font-size-base !default;
+/// color||Color|0
+$--radio-button-checked-background-color: $--color-primary !default;
+/// color||Color|0
+$--radio-button-checked-font-color: $--color-white !default;
+/// color||Color|0
+$--radio-button-checked-border-color: $--color-primary !default;
+$--radio-button-disabled-checked-fill: $--border-color-extra-light !default;
+
+/* Select
+-------------------------- */
+$--select-border-color-hover: $--border-color-hover !default;
+$--select-disabled-border: $--disabled-border-base !default;
+/// fontSize||Font|1
+$--select-font-size: $--font-size-base !default;
+$--select-close-hover-color: $--color-text-secondary !default;
+
+$--select-input-color: $--color-text-placeholder !default;
+$--select-multiple-input-color: #666 !default;
+/// color||Color|0
+$--select-input-focus-border-color: $--color-primary !default;
+/// fontSize||Font|1
+$--select-input-font-size: 14px !default;
+
+$--select-option-color: $--color-text-regular !default;
+$--select-option-disabled-color: $--color-text-placeholder !default;
+$--select-option-disabled-background: $--color-white !default;
+/// height||Other|4
+$--select-option-height: 34px !default;
+$--select-option-hover-background: $--background-color-base !default;
+/// color||Color|0
+$--select-option-selected-font-color: $--color-primary !default;
+$--select-option-selected-hover: $--background-color-base !default;
+
+$--select-group-color: $--color-info !default;
+$--select-group-height: 30px !default;
+$--select-group-font-size: 12px !default;
+
+$--select-dropdown-background: $--color-white !default;
+$--select-dropdown-shadow: $--box-shadow-light !default;
+$--select-dropdown-empty-color: #999 !default;
+/// height||Other|4
+$--select-dropdown-max-height: 274px !default;
+$--select-dropdown-padding: 6px 0 !default;
+$--select-dropdown-empty-padding: 10px 0 !default;
+$--select-dropdown-border: solid 1px $--border-color-light !default;
+
+/* Alert
+-------------------------- */
+$--alert-padding: 8px 16px !default;
+/// borderRadius||Border|2
+$--alert-border-radius: $--border-radius-base !default;
+/// fontSize||Font|1
+$--alert-title-font-size: 13px !default;
+/// fontSize||Font|1
+$--alert-description-font-size: 12px !default;
+/// fontSize||Font|1
+$--alert-close-font-size: 12px !default;
+/// fontSize||Font|1
+$--alert-close-customed-font-size: 13px !default;
+
+$--alert-success-color: $--color-success-lighter !default;
+$--alert-info-color: $--color-info-lighter !default;
+$--alert-warning-color: $--color-warning-lighter !default;
+$--alert-danger-color: $--color-danger-lighter !default;
+
+/// height||Other|4
+$--alert-icon-size: 16px !default;
+/// height||Other|4
+$--alert-icon-large-size: 28px !default;
+
+/* MessageBox
+-------------------------- */
+/// color||Color|0
+$--messagebox-title-color: $--color-text-primary !default;
+$--msgbox-width: 420px !default;
+$--msgbox-border-radius: 4px !default;
+/// fontSize||Font|1
+$--messagebox-font-size: $--font-size-large !default;
+/// fontSize||Font|1
+$--messagebox-content-font-size: $--font-size-base !default;
+/// color||Color|0
+$--messagebox-content-color: $--color-text-regular !default;
+/// fontSize||Font|1
+$--messagebox-error-font-size: 12px !default;
+$--msgbox-padding-primary: 15px !default;
+/// color||Color|0
+$--messagebox-success-color: $--color-success !default;
+/// color||Color|0
+$--messagebox-info-color: $--color-info !default;
+/// color||Color|0
+$--messagebox-warning-color: $--color-warning !default;
+/// color||Color|0
+$--messagebox-danger-color: $--color-danger !default;
+
+/* Message
+-------------------------- */
+$--message-shadow: $--box-shadow-base !default;
+$--message-min-width: 380px !default;
+$--message-background-color: #edf2fc !default;
+$--message-padding: 15px 15px 15px 20px !default;
+/// color||Color|0
+$--message-close-icon-color: $--color-text-placeholder !default;
+/// height||Other|4
+$--message-close-size: 16px !default;
+/// color||Color|0
+$--message-close-hover-color: $--color-text-secondary !default;
+
+/// color||Color|0
+$--message-success-font-color: $--color-success !default;
+/// color||Color|0
+$--message-info-font-color: $--color-info !default;
+/// color||Color|0
+$--message-warning-font-color: $--color-warning !default;
+/// color||Color|0
+$--message-danger-font-color: $--color-danger !default;
+
+/* Notification
+-------------------------- */
+$--notification-width: 330px !default;
+/// padding||Spacing|3
+$--notification-padding: 14px 26px 14px 13px !default;
+$--notification-radius: 8px !default;
+$--notification-shadow: $--box-shadow-light !default;
+/// color||Color|0
+$--notification-border-color: $--border-color-lighter !default;
+$--notification-icon-size: 24px !default;
+$--notification-close-font-size: $--message-close-size !default;
+$--notification-group-margin-left: 13px !default;
+$--notification-group-margin-right: 8px !default;
+/// fontSize||Font|1
+$--notification-content-font-size: $--font-size-base !default;
+/// color||Color|0
+$--notification-content-color: $--color-text-regular !default;
+/// fontSize||Font|1
+$--notification-title-font-size: 16px !default;
+/// color||Color|0
+$--notification-title-color: $--color-text-primary !default;
+
+/// color||Color|0
+$--notification-close-color: $--color-text-secondary !default;
+/// color||Color|0
+$--notification-close-hover-color: $--color-text-regular !default;
+
+/// color||Color|0
+$--notification-success-icon-color: $--color-success !default;
+/// color||Color|0
+$--notification-info-icon-color: $--color-info !default;
+/// color||Color|0
+$--notification-warning-icon-color: $--color-warning !default;
+/// color||Color|0
+$--notification-danger-icon-color: $--color-danger !default;
+
+/* Input
+-------------------------- */
+$--input-font-size: $--font-size-base !default;
+/// color||Color|0
+$--input-font-color: $--color-text-regular !default;
+/// height||Other|4
+$--input-width: 140px !default;
+/// height||Other|4
+$--input-height: 40px !default;
+$--input-border: $--border-base !default;
+$--input-border-color: $--border-color-base !default;
+/// borderRadius||Border|2
+$--input-border-radius: $--border-radius-base !default;
+$--input-border-color-hover: $--border-color-hover !default;
+/// color||Color|0
+$--input-background-color: $--color-white !default;
+$--input-fill-disabled: $--disabled-fill-base !default;
+$--input-color-disabled: $--font-color-disabled-base !default;
+/// color||Color|0
+$--input-icon-color: $--color-text-placeholder !default;
+/// color||Color|0
+$--input-placeholder-color: $--color-text-placeholder !default;
+$--input-max-width: 314px !default;
+
+$--input-hover-border: $--border-color-hover !default;
+$--input-clear-hover-color: $--color-text-secondary !default;
+
+$--input-focus-border: $--color-primary !default;
+$--input-focus-fill: $--color-white !default;
+
+$--input-disabled-fill: $--disabled-fill-base !default;
+$--input-disabled-border: $--disabled-border-base !default;
+$--input-disabled-color: $--disabled-color-base !default;
+$--input-disabled-placeholder-color: $--color-text-placeholder !default;
+
+/// fontSize||Font|1
+$--input-medium-font-size: 14px !default;
+/// height||Other|4
+$--input-medium-height: 36px !default;
+/// fontSize||Font|1
+$--input-small-font-size: 13px !default;
+/// height||Other|4
+$--input-small-height: 32px !default;
+/// fontSize||Font|1
+$--input-mini-font-size: 12px !default;
+/// height||Other|4
+$--input-mini-height: 28px !default;
+
+/* Cascader
+-------------------------- */
+/// color||Color|0
+$--cascader-menu-font-color: $--color-text-regular !default;
+/// color||Color|0
+$--cascader-menu-selected-font-color: $--color-primary !default;
+$--cascader-menu-fill: $--fill-base !default;
+$--cascader-menu-font-size: $--font-size-base !default;
+$--cascader-menu-radius: $--border-radius-base !default;
+$--cascader-menu-border: solid 1px $--border-color-light !default;
+$--cascader-menu-shadow: $--box-shadow-light !default;
+$--cascader-node-background-hover: $--background-color-base !default;
+$--cascader-node-color-disabled:$--color-text-placeholder !default;
+$--cascader-color-empty:$--color-text-placeholder !default;
+$--cascader-tag-background: #f0f2f5;
+
+/* Group
+-------------------------- */
+$--group-option-flex: 0 0 (1/5) * 100% !default;
+$--group-option-offset-bottom: 12px !default;
+$--group-option-fill-hover: rgba($--color-black, 0.06) !default;
+$--group-title-color: $--color-black !default;
+$--group-title-font-size: $--font-size-base !default;
+$--group-title-width: 66px !default;
+
+/* Tab
+-------------------------- */
+$--tab-font-size: $--font-size-base !default;
+$--tab-border-line: 1px solid #e4e4e4 !default;
+$--tab-header-color-active: $--color-text-secondary !default;
+$--tab-header-color-hover: $--color-text-regular !default;
+$--tab-header-color: $--color-text-regular !default;
+$--tab-header-fill-active: rgba($--color-black, 0.06) !default;
+$--tab-header-fill-hover: rgba($--color-black, 0.06) !default;
+$--tab-vertical-header-width: 90px !default;
+$--tab-vertical-header-count-color: $--color-white !default;
+$--tab-vertical-header-count-fill: $--color-text-secondary !default;
+
+/* Button
+-------------------------- */
+/// fontSize||Font|1
+$--button-font-size: $--font-size-base !default;
+/// fontWeight||Font|1
+$--button-font-weight: $--font-weight-primary !default;
+/// borderRadius||Border|2
+$--button-border-radius: $--border-radius-base !default;
+/// padding||Spacing|3
+$--button-padding-vertical: 12px !default;
+/// padding||Spacing|3
+$--button-padding-horizontal: 20px !default;
+
+/// fontSize||Font|1
+$--button-medium-font-size: $--font-size-base !default;
+/// borderRadius||Border|2
+$--button-medium-border-radius: $--border-radius-base !default;
+/// padding||Spacing|3
+$--button-medium-padding-vertical: 10px !default;
+/// padding||Spacing|3
+$--button-medium-padding-horizontal: 20px !default;
+
+/// fontSize||Font|1
+$--button-small-font-size: 12px !default;
+$--button-small-border-radius: #{$--border-radius-base - 1} !default;
+/// padding||Spacing|3
+$--button-small-padding-vertical: 9px !default;
+/// padding||Spacing|3
+$--button-small-padding-horizontal: 15px !default;
+/// fontSize||Font|1
+$--button-mini-font-size: 12px !default;
+$--button-mini-border-radius: #{$--border-radius-base - 1} !default;
+/// padding||Spacing|3
+$--button-mini-padding-vertical: 7px !default;
+/// padding||Spacing|3
+$--button-mini-padding-horizontal: 15px !default;
+
+/// color||Color|0
+$--button-default-font-color: $--color-text-regular !default;
+/// color||Color|0
+$--button-default-background-color: $--color-white !default;
+/// color||Color|0
+$--button-default-border-color: $--border-color-base !default;
+
+/// color||Color|0
+$--button-disabled-font-color: $--color-text-placeholder !default;
+/// color||Color|0
+$--button-disabled-background-color: $--color-white !default;
+/// color||Color|0
+$--button-disabled-border-color: $--border-color-lighter !default;
+
+/// color||Color|0
+$--button-primary-border-color: $--color-primary !default;
+/// color||Color|0
+$--button-primary-font-color: $--color-white !default;
+/// color||Color|0
+$--button-primary-background-color: $--color-primary !default;
+/// color||Color|0
+$--button-success-border-color: $--color-success !default;
+/// color||Color|0
+$--button-success-font-color: $--color-white !default;
+/// color||Color|0
+$--button-success-background-color: $--color-success !default;
+/// color||Color|0
+$--button-warning-border-color: $--color-warning !default;
+/// color||Color|0
+$--button-warning-font-color: $--color-white !default;
+/// color||Color|0
+$--button-warning-background-color: $--color-warning !default;
+/// color||Color|0
+$--button-danger-border-color: $--color-danger !default;
+/// color||Color|0
+$--button-danger-font-color: $--color-white !default;
+/// color||Color|0
+$--button-danger-background-color: $--color-danger !default;
+/// color||Color|0
+$--button-info-border-color: $--color-info !default;
+/// color||Color|0
+$--button-info-font-color: $--color-white !default;
+/// color||Color|0
+$--button-info-background-color: $--color-info !default;
+
+$--button-hover-tint-percent: 20% !default;
+$--button-active-shade-percent: 10% !default;
+
+
+/* cascader
+-------------------------- */
+$--cascader-height: 200px !default;
+
+/* Switch
+-------------------------- */
+/// color||Color|0
+$--switch-on-color: $--color-primary !default;
+/// color||Color|0
+$--switch-off-color: $--border-color-base !default;
+/// fontSize||Font|1
+$--switch-font-size: $--font-size-base !default;
+$--switch-core-border-radius: 10px !default;
+// height||Other|4 TODO: width 代码写死的40px 所以下面这三个属性都没意义
+$--switch-width: 40px !default;
+// height||Other|4
+$--switch-height: 20px !default;
+// height||Other|4
+$--switch-button-size: 16px !default;
+
+/* Dialog
+-------------------------- */
+$--dialog-background-color: $--color-white !default;
+$--dialog-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) !default;
+/// fontSize||Font|1
+$--dialog-title-font-size: $--font-size-large !default;
+/// fontSize||Font|1
+$--dialog-content-font-size: 14px !default;
+/// fontLineHeight||LineHeight|2
+$--dialog-font-line-height: $--font-line-height-primary !default;
+/// padding||Spacing|3
+$--dialog-padding-primary: 20px !default;
+
+/* Table
+-------------------------- */
+/// color||Color|0
+$--table-border-color: $--border-color-lighter !default;
+$--table-border: 1px solid $--table-border-color !default;
+/// color||Color|0
+$--table-font-color: $--color-text-regular !default;
+/// color||Color|0
+$--table-header-font-color: $--color-text-secondary !default;
+/// color||Color|0
+$--table-row-hover-background-color: $--background-color-base !default;
+$--table-current-row-background-color: $--color-primary-light-9 !default;
+/// color||Color|0
+$--table-header-background-color: $--color-white !default;
+$--table-fixed-box-shadow: 0 0 10px rgba(0, 0, 0, .12) !default;
+
+/* Pagination
+-------------------------- */
+/// fontSize||Font|1
+$--pagination-font-size: 13px !default;
+/// color||Color|0
+$--pagination-background-color: $--color-white !default;
+/// color||Color|0
+$--pagination-font-color: $--color-text-primary !default;
+$--pagination-border-radius: 3px !default;
+/// color||Color|0
+$--pagination-button-color: $--color-text-primary !default;
+/// height||Other|4
+$--pagination-button-width: 35.5px !default;
+/// height||Other|4
+$--pagination-button-height: 28px !default;
+/// color||Color|0
+$--pagination-button-disabled-color: $--color-text-placeholder !default;
+/// color||Color|0
+$--pagination-button-disabled-background-color: $--color-white !default;
+/// color||Color|0
+$--pagination-hover-color: $--color-primary !default;
+
+/* Popup
+-------------------------- */
+/// color||Color|0
+$--popup-modal-background-color: $--color-black !default;
+/// opacity||Other|1
+$--popup-modal-opacity: 0.5 !default;
+
+/* Popover
+-------------------------- */
+/// color||Color|0
+$--popover-background-color: $--color-white !default;
+/// fontSize||Font|1
+$--popover-font-size: $--font-size-base !default;
+/// color||Color|0
+$--popover-border-color: $--border-color-lighter !default;
+$--popover-arrow-size: 6px !default;
+/// padding||Spacing|3
+$--popover-padding: 12px !default;
+$--popover-padding-large: 18px 20px !default;
+/// fontSize||Font|1
+$--popover-title-font-size: 16px !default;
+/// color||Color|0
+$--popover-title-font-color: $--color-text-primary !default;
+
+/* Tooltip
+-------------------------- */
+/// color|1|Color|0
+$--tooltip-fill: $--color-text-primary !default;
+/// color|1|Color|0
+$--tooltip-color: $--color-white !default;
+/// fontSize||Font|1
+$--tooltip-font-size: 12px !default;
+/// color||Color|0
+$--tooltip-border-color: $--color-text-primary !default;
+$--tooltip-arrow-size: 6px !default;
+/// padding||Spacing|3
+$--tooltip-padding: 10px !default;
+
+/* Tag
+-------------------------- */
+/// color||Color|0
+$--tag-info-color: $--color-info !default;
+/// color||Color|0
+$--tag-primary-color: $--color-primary !default;
+/// color||Color|0
+$--tag-success-color: $--color-success !default;
+/// color||Color|0
+$--tag-warning-color: $--color-warning !default;
+/// color||Color|0
+$--tag-danger-color: $--color-danger !default;
+/// fontSize||Font|1
+$--tag-font-size: 12px !default;
+$--tag-border-radius: 4px !default;
+$--tag-padding: 0 10px !default;
+
+/* Tree
+-------------------------- */
+/// color||Color|0
+$--tree-node-hover-background-color: $--background-color-base !default;
+/// color||Color|0
+$--tree-font-color: $--color-text-regular !default;
+/// color||Color|0
+$--tree-expand-icon-color: $--color-text-placeholder !default;
+
+/* Dropdown
+-------------------------- */
+$--dropdown-menu-box-shadow: $--box-shadow-light !default;
+$--dropdown-menuItem-hover-fill: $--color-primary-light-9 !default;
+$--dropdown-menuItem-hover-color: $--link-color !default;
+
+/* Badge
+-------------------------- */
+/// color||Color|0
+$--badge-background-color: $--color-danger !default;
+$--badge-radius: 10px !default;
+/// fontSize||Font|1
+$--badge-font-size: 12px !default;
+/// padding||Spacing|3
+$--badge-padding: 6px !default;
+/// height||Other|4
+$--badge-size: 18px !default;
+
+/* Card
+--------------------------*/
+/// color||Color|0
+$--card-border-color: $--border-color-lighter !default;
+$--card-border-radius: 4px !default;
+/// padding||Spacing|3
+$--card-padding: 20px !default;
+
+/* Slider
+--------------------------*/
+/// color||Color|0
+$--slider-main-background-color: $--color-primary !default;
+/// color||Color|0
+$--slider-runway-background-color: $--border-color-light !default;
+$--slider-button-hover-color: mix($--color-primary, black, 97%) !default;
+$--slider-stop-background-color: $--color-white !default;
+$--slider-disable-color: $--color-text-placeholder !default;
+$--slider-margin: 16px 0 !default;
+$--slider-border-radius: 3px !default;
+/// height|1|Other|4
+$--slider-height: 6px !default;
+/// height||Other|4
+$--slider-button-size: 16px !default;
+$--slider-button-wrapper-size: 36px !default;
+$--slider-button-wrapper-offset: -15px !default;
+
+/* Steps
+--------------------------*/
+$--steps-border-color: $--disabled-border-base !default;
+$--steps-border-radius: 4px !default;
+$--steps-padding: 20px !default;
+
+/* Menu
+--------------------------*/
+/// fontSize||Font|1
+$--menu-item-font-size: $--font-size-base !default;
+/// color||Color|0
+$--menu-item-font-color: $--color-text-primary !default;
+/// color||Color|0
+$--menu-background-color: $--color-white !default;
+$--menu-item-hover-fill: $--color-primary-light-9 !default;
+
+/* Rate
+--------------------------*/
+$--rate-height: 20px !default;
+/// fontSize||Font|1
+$--rate-font-size: $--font-size-base !default;
+/// height||Other|3
+$--rate-icon-size: 18px !default;
+/// margin||Spacing|2
+$--rate-icon-margin: 6px !default;
+$--rate-icon-color: $--color-text-placeholder !default;
+
+/* DatePicker
+--------------------------*/
+$--datepicker-font-color: $--color-text-regular !default;
+/// color|1|Color|0
+$--datepicker-off-font-color: $--color-text-placeholder !default;
+/// color||Color|0
+$--datepicker-header-font-color: $--color-text-regular !default;
+$--datepicker-icon-color: $--color-text-primary !default;
+$--datepicker-border-color: $--disabled-border-base !default;
+$--datepicker-inner-border-color: #e4e4e4 !default;
+/// color||Color|0
+$--datepicker-inrange-background-color: $--border-color-extra-light !default;
+/// color||Color|0
+$--datepicker-inrange-hover-background-color: $--border-color-extra-light !default;
+/// color||Color|0
+$--datepicker-active-color: $--color-primary !default;
+/// color||Color|0
+$--datepicker-hover-font-color: $--color-primary !default;
+$--datepicker-cell-hover-color: #fff !default;
+
+/* Loading
+--------------------------*/
+/// height||Other|4
+$--loading-spinner-size: 42px !default;
+/// height||Other|4
+$--loading-fullscreen-spinner-size: 50px !default;
+
+/* Scrollbar
+--------------------------*/
+$--scrollbar-background-color: rgba($--color-text-secondary, .3) !default;
+$--scrollbar-hover-background-color: rgba($--color-text-secondary, .5) !default;
+
+/* Carousel
+--------------------------*/
+/// fontSize||Font|1
+$--carousel-arrow-font-size: 12px !default;
+$--carousel-arrow-size: 36px !default;
+$--carousel-arrow-background: rgba(31, 45, 61, 0.11) !default;
+$--carousel-arrow-hover-background: rgba(31, 45, 61, 0.23) !default;
+/// width||Other|4
+$--carousel-indicator-width: 30px !default;
+/// height||Other|4
+$--carousel-indicator-height: 2px !default;
+$--carousel-indicator-padding-horizontal: 4px !default;
+$--carousel-indicator-padding-vertical: 12px !default;
+$--carousel-indicator-out-color: $--border-color-hover !default;
+
+/* Collapse
+--------------------------*/
+/// color||Color|0
+$--collapse-border-color: $--border-color-lighter !default;
+/// height||Other|4
+$--collapse-header-height: 48px !default;
+/// color||Color|0
+$--collapse-header-background-color: $--color-white !default;
+/// color||Color|0
+$--collapse-header-font-color: $--color-text-primary !default;
+/// fontSize||Font|1
+$--collapse-header-font-size: 13px !default;
+/// color||Color|0
+$--collapse-content-background-color: $--color-white !default;
+/// fontSize||Font|1
+$--collapse-content-font-size: 13px !default;
+/// color||Color|0
+$--collapse-content-font-color: $--color-text-primary !default;
+
+/* Transfer
+--------------------------*/
+$--transfer-border-color: $--border-color-lighter !default;
+$--transfer-border-radius: $--border-radius-base !default;
+/// height||Other|4
+$--transfer-panel-width: 200px !default;
+/// height||Other|4
+$--transfer-panel-header-height: 40px !default;
+/// color||Color|0
+$--transfer-panel-header-background-color: $--background-color-base !default;
+/// height||Other|4
+$--transfer-panel-footer-height: 40px !default;
+/// height||Other|4
+$--transfer-panel-body-height: 246px !default;
+/// height||Other|4
+$--transfer-item-height: 30px !default;
+/// height||Other|4
+$--transfer-filter-height: 32px !default;
+
+/* Header
+  --------------------------*/
+$--header-padding: 0 20px !default;
+
+/* Footer
+--------------------------*/
+$--footer-padding: 0 20px !default;
+
+/* Main
+--------------------------*/
+$--main-padding: 20px !default;
+
+/* Timeline
+--------------------------*/
+$--timeline-node-size-normal: 12px !default;
+$--timeline-node-size-large: 14px !default;
+$--timeline-node-color: $--border-color-light !default;
+
+/* Backtop
+--------------------------*/
+/// color||Color|0
+$--backtop-background-color: $--color-white !default;
+/// color||Color|0
+$--backtop-font-color: $--color-primary !default;
+/// color||Color|0
+$--backtop-hover-background-color: $--border-color-extra-light !default;
+
+/* Link
+--------------------------*/
+/// fontSize||Font|1
+$--link-font-size: $--font-size-base !default;
+/// fontWeight||Font|1
+$--link-font-weight: $--font-weight-primary !default;
+/// color||Color|0
+$--link-default-font-color: $--color-text-regular !default;
+/// color||Color|0
+$--link-default-active-color: $--color-primary !default;
+/// color||Color|0
+$--link-disabled-font-color: $--color-text-placeholder !default;
+/// color||Color|0
+$--link-primary-font-color: $--color-primary !default;
+/// color||Color|0
+$--link-success-font-color: $--color-success !default;
+/// color||Color|0
+$--link-warning-font-color: $--color-warning !default;
+/// color||Color|0
+$--link-danger-font-color: $--color-danger !default;
+/// color||Color|0
+$--link-info-font-color: $--color-info !default;
+/* Calendar
+--------------------------*/
+/// border||Other|4
+$--calendar-border: $--table-border !default;
+/// color||Other|4
+$--calendar-selected-background-color: #F2F8FE !default;
+$--calendar-cell-width: 85px !default;
+
+/* Form
+-------------------------- */
+/// fontSize||Font|1
+$--form-label-font-size: $--font-size-base !default;
+
+/* Avatar
+--------------------------*/
+/// color||Color|0
+$--avatar-font-color: #fff !default;
+/// color||Color|0
+$--avatar-background-color: #C0C4CC !default;
+/// fontSize||Font Size|1
+$--avatar-text-font-size: 14px !default;
+/// fontSize||Font Size|1
+$--avatar-icon-font-size: 18px !default;
+/// borderRadius||Border|2
+$--avatar-border-radius: $--border-radius-base !default;
+/// size|1|Avatar Size|3
+$--avatar-large-size: 40px !default;
+/// size|1|Avatar Size|3
+$--avatar-medium-size: 36px !default;
+/// size|1|Avatar Size|3
+$--avatar-small-size: 28px !default;
+
+/* Break-point
+--------------------------*/
+$--sm: 768px !default;
+$--md: 992px !default;
+$--lg: 1200px !default;
+$--xl: 1920px !default;
+
+$--breakpoints: (
+  'xs' : (max-width: $--sm - 1),
+  'sm' : (min-width: $--sm),
+  'md' : (min-width: $--md),
+  'lg' : (min-width: $--lg),
+  'xl' : (min-width: $--xl)
+);
+
+$--breakpoints-spec: (
+  'xs-only' : (max-width: $--sm - 1),
+  'sm-and-up' : (min-width: $--sm),
+  'sm-only': "(min-width: #{$--sm}) and (max-width: #{$--md - 1})",
+  'sm-and-down': (max-width: $--md - 1),
+  'md-and-up' : (min-width: $--md),
+  'md-only': "(min-width: #{$--md}) and (max-width: #{$--lg - 1})",
+  'md-and-down': (max-width: $--lg - 1),
+  'lg-and-up' : (min-width: $--lg),
+  'lg-only': "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})",
+  'lg-and-down': (max-width: $--xl - 1),
+  'xl-only' : (min-width: $--xl),
+);

文件差异内容过多而无法显示
+ 4990 - 0
package-lock.json


+ 46 - 0
package.json

@@ -0,0 +1,46 @@
+{
+  "name": "test-vmc",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve -mode development",
+    "build:app": "vue-cli-service build -mode production",
+    "build:module": "vue-cli-service build --target lib src/module.js"
+  },
+  "dependencies": {
+    "cnpm": "^6.1.1",
+    "core-js": "^3.3.2",
+    "default-passive-events": "^2.0.0",
+    "element-ui": "^2.13.2",
+    "moment": "^2.27.0",
+    "vue": "^2.6.10",
+    "vue-module-loader": "^1.0.3",
+    "vue-router": "^3.1.3",
+    "vuex": "^3.0.1"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^4.0.0",
+    "@vue/cli-plugin-eslint": "^4.0.0",
+    "@vue/cli-plugin-router": "^4.0.0",
+    "@vue/cli-plugin-vuex": "^4.0.0",
+    "@vue/cli-service": "^4.0.0",
+    "@vue/eslint-config-prettier": "^5.0.0",
+    "axios": "^0.19.2",
+    "babel-eslint": "^10.0.3",
+    "element-theme-chalk": "^2.13.2",
+    "eslint": "^5.16.0",
+    "eslint-plugin-prettier": "^3.1.1",
+    "eslint-plugin-vue": "^5.0.0",
+    "node-sass": "^4.14.1",
+    "prettier": "^1.18.2",
+    "qs": "^6.9.4",
+    "sass-loader": "^9.0.0",
+    "sass-resources-loader": "^2.0.3",
+    "stylus": "^0.54.7",
+    "stylus-loader": "^3.0.2",
+    "vue-axios": "^2.1.5",
+    "vue-template-compiler": "^2.6.10"
+  },
+  "description": "test",
+  "author": "ln"
+}

+ 5 - 0
postcss.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  plugins: {
+    autoprefixer: {}
+  }
+};

二进制
public/favicon.ico


+ 22 - 0
public/index.html

@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<meta name="viewport" content="width=device-width,initial-scale=1.0">
+	<link rel="icon" href="<%= BASE_URL %>favicon.ico">
+	<!--引入UI组件库(1.1版本) -->
+	<title>湖羊养殖</title>
+</head>
+
+<body>
+	<noscript>
+		<strong>We're sorry but admincraft-module doesn't work properly without JavaScript enabled. Please enable it to
+			continue.</strong>
+	</noscript>
+	<div id="app"></div>
+	<!-- built files will be auto injected -->
+</body>
+
+</html>

+ 387 - 0
public/libs/H264SPSParser.js

@@ -0,0 +1,387 @@
+//import Map from './Map.js';
+
+let BITWISE0x00000007 = 0x00000007;
+let BITWISE0x7 = 0x7;
+let BITWISE2 = 2;
+let BITWISE3 = 3;
+let BITWISE4 = 4;
+let BITWISE5 = 5;
+let BITWISE6 = 6;
+let BITWISE8 = 8;
+let BITWISE12 = 12;
+let BITWISE15 = 15;
+let BITWISE16 = 16;
+let BITWISE32 = 32;
+let BITWISE64 = 64;
+let BITWISE255 = 255;
+let BITWISE256 = 256;
+
+function H264SPSParser() {
+    let vBitCount = 0;
+    let spsMap = null;
+    let fps = null;
+
+
+    function constructor() {
+        spsMap = new Map();
+    }
+
+    constructor.prototype = {
+        parse (pSPSBytes) {
+            //console.log("=========================SPS START=========================");
+            vBitCount = 0;
+            spsMap.clear();
+
+            // forbidden_zero_bit, nal_ref_idc, nal_unit_type
+            spsMap.set("forbidden_zero_bit", readBits(pSPSBytes, 1));
+            spsMap.set("nal_ref_idc", readBits(pSPSBytes, BITWISE2));
+            spsMap.set("nal_unit_type", readBits(pSPSBytes, BITWISE5));
+
+            // profile_idc
+            spsMap.set("profile_idc", readBits(pSPSBytes, BITWISE8));
+            spsMap.set("profile_compatibility", readBits(pSPSBytes, BITWISE8));
+
+            // spsMap.set("constrained_set0_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set1_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set2_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set3_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set4_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("constrained_set5_flag", readBits(pSPSBytes, 1));
+            // spsMap.set("reserved_zero_2bits", readBits(pSPSBytes, 2));
+
+            // level_idc
+            spsMap.set("level_idc", readBits(pSPSBytes, BITWISE8));
+            spsMap.set("seq_parameter_set_id", ue(pSPSBytes, 0));
+
+            let profileIdc = spsMap.get("profile_idc");
+            let BITWISE100 = 100;
+            let BITWISE110 = 110;
+            let BITWISE122 = 122;
+            let BITWISE244 = 244;
+            let BITWISE44 = 44;
+            let BITWISE83 = 83;
+            let BITWISE86 = 86;
+            let BITWISE118 = 118;
+            let BITWISE128 = 128;
+            let BITWISE138 = 138;
+            let BITWISE139 = 139;
+            let BITWISE134 = 134;
+
+            if ((profileIdc === BITWISE100) || (profileIdc === BITWISE110) ||
+                (profileIdc === BITWISE122) || (profileIdc === BITWISE244) ||
+                (profileIdc === BITWISE44) || (profileIdc === BITWISE83) ||
+                (profileIdc === BITWISE86) || (profileIdc === BITWISE118) ||
+                (profileIdc === BITWISE128) || (profileIdc === BITWISE138) ||
+                (profileIdc === BITWISE139) || (profileIdc === BITWISE134)) {
+                spsMap.set("chroma_format_idc", ue(pSPSBytes, 0));
+                if (spsMap.get("chroma_format_idc") === BITWISE3) {
+                    spsMap.set("separate_colour_plane_flag", readBits(pSPSBytes, 1));
+                }
+
+                spsMap.set("bit_depth_luma_minus8", ue(pSPSBytes, 0));
+                spsMap.set("bit_depth_chroma_minus8", ue(pSPSBytes, 0));
+                spsMap.set("qpprime_y_zero_transform_bypass_flag", readBits(pSPSBytes, 1));
+                spsMap.set("seq_scaling_matrix_present_flag", readBits(pSPSBytes, 1));
+
+                if (spsMap.get("seq_scaling_matrix_present_flag")) {
+                    let num = spsMap.get("chroma_format_idc") !== BITWISE3 ? BITWISE8 : BITWISE12;
+                    let seqScalingListPresentFlag = new Array(num);
+                    for (let i = 0; i < num; i++) {
+                        seqScalingListPresentFlag[i] = readBits(pSPSBytes, 1);
+
+                        if (seqScalingListPresentFlag[i]) {
+                            let slNumber = i < BITWISE6 ? BITWISE16 : BITWISE64;
+                            let lastScale = 8;
+                            let nextScale = 8;
+                            let deltaScale = 0;
+
+                            for (let j = 0; j < slNumber; j++) {
+                                if (nextScale) {
+                                    deltaScale = se(pSPSBytes, 0);
+                                    nextScale = (lastScale + deltaScale + BITWISE256) % BITWISE256;
+                                }
+                                lastScale = (nextScale === 0) ? lastScale : nextScale;
+                            }
+                        }
+                    }
+                    spsMap.set("seq_scaling_list_present_flag", seqScalingListPresentFlag);
+                }
+            }
+            spsMap.set("log2_max_frame_num_minus4", ue(pSPSBytes, 0));
+            spsMap.set("pic_order_cnt_type", ue(pSPSBytes, 0));
+
+            if (spsMap.get("pic_order_cnt_type") === 0) {
+                spsMap.set("log2_max_pic_order_cnt_lsb_minus4", ue(pSPSBytes, 0));
+            } else if (spsMap.get("pic_order_cnt_type") === 1) {
+                spsMap.set("delta_pic_order_always_zero_flag", readBits(pSPSBytes, 1));
+                spsMap.set("offset_for_non_ref_pic", se(pSPSBytes, 0));
+                spsMap.set("offset_for_top_to_bottom_field", se(pSPSBytes, 0));
+                spsMap.set("num_ref_frames_in_pic_order_cnt_cycle", ue(pSPSBytes, 0));
+                for (let numR = 0; numR < spsMap.get("num_ref_frames_in_pic_order_cnt_cycle"); numR++) {
+                    spsMap.set("num_ref_frames_in_pic_order_cnt_cycle", se(pSPSBytes, 0));
+                }
+            }
+            spsMap.set("num_ref_frames", ue(pSPSBytes, 0));
+            spsMap.set("gaps_in_frame_num_value_allowed_flag", readBits(pSPSBytes, 1));
+            spsMap.set("pic_width_in_mbs_minus1", ue(pSPSBytes, 0));
+            spsMap.set("pic_height_in_map_units_minus1", ue(pSPSBytes, 0));
+            spsMap.set("frame_mbs_only_flag", readBits(pSPSBytes, 1));
+
+            if (spsMap.get("frame_mbs_only_flag") === 0) {
+                spsMap.set("mb_adaptive_frame_field_flag", readBits(pSPSBytes, 1));
+            }
+            spsMap.set("direct_8x8_interence_flag", readBits(pSPSBytes, 1));
+            spsMap.set("frame_cropping_flag", readBits(pSPSBytes, 1));
+            if (spsMap.get("frame_cropping_flag") === 1) {
+                spsMap.set("frame_cropping_rect_left_offset", ue(pSPSBytes, 0));
+                spsMap.set("frame_cropping_rect_right_offset", ue(pSPSBytes, 0));
+                spsMap.set("frame_cropping_rect_top_offset", ue(pSPSBytes, 0));
+                spsMap.set("frame_cropping_rect_bottom_offset", ue(pSPSBytes, 0));
+            }
+
+            //vui parameters
+            spsMap.set("vui_parameters_present_flag", readBits(pSPSBytes, 1));
+            if (spsMap.get("vui_parameters_present_flag")) {
+                vuiParameters(pSPSBytes);
+            }
+
+            //console.log("=========================SPS END=========================");
+
+
+            return true;
+        },
+        getSizeInfo () {
+            let SubWidthC = 0;
+            let SubHeightC = 0;
+
+            if (spsMap.get("chroma_format_idc") === 0) { //monochrome
+                SubWidthC = SubHeightC = 0;
+            } else if (spsMap.get("chroma_format_idc") === 1) { //4:2:0
+                SubWidthC = SubHeightC = BITWISE2;
+            } else if (spsMap.get("chroma_format_idc") === BITWISE2) { //4:2:2
+                SubWidthC = BITWISE2;
+                SubHeightC = 1;
+            } else if (spsMap.get("chroma_format_idc") === BITWISE3) { //4:4:4
+                if (spsMap.get("separate_colour_plane_flag") === 0) {
+                    SubWidthC = SubHeightC = 1;
+                } else if (spsMap.get("separate_colour_plane_flag") === 1) {
+                    SubWidthC = SubHeightC = 0;
+                }
+            }
+
+            let PicWidthInMbs = spsMap.get("pic_width_in_mbs_minus1") + 1;
+
+            let PicHeightInMapUnits = spsMap.get("pic_height_in_map_units_minus1") + 1;
+            let FrameHeightInMbs = (BITWISE2 - spsMap.get("frame_mbs_only_flag")) * PicHeightInMapUnits;
+
+            let cropLeft = 0;
+            let cropRight = 0;
+            let cropTop = 0;
+            let cropBottom = 0;
+
+            if (spsMap.get("frame_cropping_flag") === 1) {
+                cropLeft = spsMap.get("frame_cropping_rect_left_offset");
+                cropRight = spsMap.get("frame_cropping_rect_right_offset");
+                cropTop = spsMap.get("frame_cropping_rect_top_offset");
+                cropBottom = spsMap.get("frame_cropping_rect_bottom_offset");
+            }
+            let decodeSize = (PicWidthInMbs * BITWISE16) * (FrameHeightInMbs * BITWISE16);
+            let width = (PicWidthInMbs * BITWISE16) - (SubWidthC * (cropLeft + cropRight));
+            let height = (FrameHeightInMbs * BITWISE16) -
+                (SubHeightC * (BITWISE2 - spsMap.get("frame_mbs_only_flag")) * (cropTop + cropBottom));
+
+            let sizeInfo = {
+                'width': width,
+                'height': height,
+                'decodeSize': decodeSize,
+            };
+
+            return sizeInfo;
+        },
+        getSpsValue (key) {
+            return spsMap.get(key);
+        },
+        getCodecInfo () {
+            let profileIdc = spsMap.get("profile_idc").toString(BITWISE16);
+            let profileCompatibility = spsMap.get("profile_compatibility") < BITWISE15 ?
+                "0" + spsMap.get("profile_compatibility").toString(BITWISE16) :
+                spsMap.get("profile_compatibility").toString(BITWISE16);
+
+            let levelIdc = spsMap.get("level_idc").toString(BITWISE16);
+
+            //console.log("getCodecInfo = " + (profile_idc + profile_compatibility + level_idc));
+            return profileIdc + profileCompatibility + levelIdc;
+
+        },
+
+        getSpsMap() {
+            return spsMap;
+        },
+
+        getFPS() {
+            return fps;
+        }
+    }
+
+    return new constructor();
+
+    function getBit(base, offset) {
+        let offsetData = offset;
+        let vCurBytes = (vBitCount + offsetData) >> BITWISE3;
+        offsetData = (vBitCount + offset) & BITWISE0x00000007;
+        return (((base[(vCurBytes)])) >> (BITWISE0x7 - (offsetData & BITWISE0x7))) & 0x1;
+    }
+
+    function readBits(pBuf, vReadBits) {
+        let vOffset = 0;
+        let vTmp = 0,
+            vTmp2 = 0;
+
+        if (vReadBits === 1) {
+            vTmp = getBit(pBuf, vOffset);
+        } else {
+            for (let i = 0; i < vReadBits; i++) {
+                vTmp2 = getBit(pBuf, i);
+                vTmp = (vTmp << 1) + vTmp2;
+            }
+        }
+
+        vBitCount += vReadBits;
+        return vTmp;
+    }
+
+    function ue(base, offset) {
+        let zeros = 0,
+            vTmp = 0,
+            vReturn = 0;
+        let vIdx = offset;
+        do {
+            vTmp = getBit(base, vIdx++);
+            if (vTmp === 0) {
+                zeros++;
+            }
+        } while (0 === vTmp);
+
+        if (zeros === 0) {
+            vBitCount += 1;
+            return 0;
+        }
+
+        vReturn = 1 << zeros;
+
+        for (let i = zeros - 1; i >= 0; i--, vIdx++) {
+            vTmp = getBit(base, vIdx);
+            vReturn |= vTmp << i;
+        }
+
+        let addBitCount = (zeros * BITWISE2) + 1;
+        vBitCount += addBitCount;
+
+        return (vReturn - 1);
+    }
+
+    function se(base, offset) {
+        let vReturn = ue(base, offset);
+
+        if (vReturn & 0x1) {
+            return (vReturn + 1) / BITWISE2;
+        } else {
+            return -vReturn / BITWISE2;
+        }
+    }
+
+    function hrdParameters(pSPSBytes) {
+        spsMap.set("cpb_cnt_minus1", ue(pSPSBytes, 0));
+        spsMap.set("bit_rate_scale", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("cpb_size_scale", readBits(pSPSBytes, BITWISE4));
+        let cpdCntMinus1 = spsMap.get("cpb_cnt_minus1");
+        let bitRateValueMinus1 = new Array(cpdCntMinus1);
+        let cpbSizeValueMinus1 = new Array(cpdCntMinus1);
+        let cbrFlag = new Array(cpdCntMinus1);
+        //Todo: 原本为i <= cpdCntMinus1,运行到此处时直接停住,原因不明,改为<后正常
+        for (let i = 0; i < cpdCntMinus1; i++) {
+            bitRateValueMinus1[i] = ue(pSPSBytes, 0);
+            cpbSizeValueMinus1[i] = ue(pSPSBytes, 0);
+            cbrFlag[i] = readBits(pSPSBytes, 1);
+        }
+        spsMap.set("bit_rate_value_minus1", bitRateValueMinus1);
+        spsMap.set("cpb_size_value_minus1", cpbSizeValueMinus1);
+        spsMap.set("cbr_flag", cbrFlag);
+
+        spsMap.set("initial_cpb_removal_delay_length_minus1", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("cpb_removal_delay_length_minus1", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("dpb_output_delay_length_minus1", readBits(pSPSBytes, BITWISE4));
+        spsMap.set("time_offset_length", readBits(pSPSBytes, BITWISE4));
+    }
+
+    function vuiParameters(pSPSBytes) {
+        spsMap.set("aspect_ratio_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("aspect_ratio_info_present_flag")) {
+            spsMap.set("aspect_ratio_idc", readBits(pSPSBytes, BITWISE8));
+            //Extended_SAR
+            if (spsMap.get("aspect_ratio_idc") === BITWISE255) {
+                spsMap.set("sar_width", readBits(pSPSBytes, BITWISE16));
+                spsMap.set("sar_height", readBits(pSPSBytes, BITWISE16));
+            }
+        }
+
+        spsMap.set("overscan_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("overscan_info_present_flag")) {
+            spsMap.set("overscan_appropriate_flag", readBits(pSPSBytes, 1));
+        }
+        spsMap.set("video_signal_type_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("video_signal_type_present_flag")) {
+            spsMap.set("video_format", readBits(pSPSBytes, BITWISE3));
+            spsMap.set("video_full_range_flag", readBits(pSPSBytes, 1));
+            spsMap.set("colour_description_present_flag", readBits(pSPSBytes, 1));
+            if (spsMap.get("colour_description_present_flag")) {
+                spsMap.set("colour_primaries", readBits(pSPSBytes, BITWISE8));
+                spsMap.set("transfer_characteristics", readBits(pSPSBytes, BITWISE8));
+                spsMap.set("matrix_coefficients", readBits(pSPSBytes, BITWISE8));
+            }
+        }
+        spsMap.set("chroma_loc_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("chroma_loc_info_present_flag")) {
+            spsMap.set("chroma_sample_loc_type_top_field", ue(pSPSBytes, 0));
+            spsMap.set("chroma_sample_loc_type_bottom_field", ue(pSPSBytes, 0));
+        }
+        spsMap.set("timing_info_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("timing_info_present_flag")) {
+            spsMap.set("num_units_in_tick", readBits(pSPSBytes, BITWISE32));
+            spsMap.set("time_scale", readBits(pSPSBytes, BITWISE32));
+            spsMap.set("fixed_frame_rate_flag", readBits(pSPSBytes, 1));
+
+            fps =  spsMap.get("time_scale") / spsMap.get("num_units_in_tick");
+            if(spsMap.get("fixed_frame_rate_flag")) {
+                fps = fps / 2;
+            }
+        }
+        spsMap.set("nal_hrd_parameters_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("nal_hrd_parameters_present_flag")) {
+            hrdParameters(pSPSBytes);
+        }
+        spsMap.set("vcl_hrd_parameters_present_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("vcl_hrd_parameters_present_flag")) {
+            hrdParameters(pSPSBytes);
+        }
+        if (spsMap.get("nal_hrd_parameters_present_flag") ||
+            spsMap.get("vcl_hrd_parameters_present_flag")) {
+            spsMap.set("low_delay_hrd_flag", readBits(pSPSBytes, 1));
+        }
+        spsMap.set("pic_struct_present_flag", readBits(pSPSBytes, 1));
+        spsMap.set("bitstream_restriction_flag", readBits(pSPSBytes, 1));
+        if (spsMap.get("bitstream_restriction_flag")) {
+            spsMap.set("motion_vectors_over_pic_boundaries_flag", readBits(pSPSBytes, 1));
+            spsMap.set("max_bytes_per_pic_denom", ue(pSPSBytes, 0));
+            spsMap.set("max_bits_per_mb_denom", ue(pSPSBytes, 0));
+            spsMap.set("log2_max_mv_length_horizontal", ue(pSPSBytes, 0));
+            spsMap.set("log2_max_mv_length_vertical", ue(pSPSBytes, 0));
+            spsMap.set("max_num_reorder_frames", ue(pSPSBytes, 0));
+            spsMap.set("max_dec_frame_buffering", ue(pSPSBytes, 0));
+        }
+    }
+}
+
+
+
+//export default H264SPSParser;

+ 667 - 0
public/libs/H264Session.js

@@ -0,0 +1,667 @@
+function H264Session() {
+    let rtpTimeStamp = 0;
+    let size1M = 1048576; //1024 * 1024
+    let inputBuffer = new Uint8Array(size1M);
+    let spsSegment = null;
+    let ppsSegment = null;
+
+    let SPSParser = null;
+
+    let width = 0;
+    let height = 0;
+    let inputLength = 0;
+
+    let initalSegmentFlag = true; //用于确定是否是initSegment
+    let initalMediaFrameFlag = true;
+
+    let frameRate = null; //根据SDP或者SPS设置
+    let preSample = null; //上一个Sample
+    let durationTimeCount = 0;
+    let frameCount = 0;
+    let inputSegBufferSub = null;
+
+    //MSE使用的数据以及相关配置,顺序codecInfo -> initSegmentData -> mediaSample -> frameData
+    //时间戳用于绘制人脸框
+    let decodedData = {
+        frameData: null, //视频数据
+        timeStamp: null, //时间戳
+        initSegmentData: null, //MP4配置,用于initsegment
+        mediaSample: null, //使用duration控制每一帧的播放时间
+        codecInfo: "", //MSE init时传入,用于创建mediasource
+    };
+    let FRAMETYPE = {
+        1: 'P',
+        5: 'I',
+        6: 'SEI',
+        7: 'I'
+    };
+    let frameType = '';
+    let decodeMode = 'video';
+    let outputSize = 0;
+    let curSize = 0;
+
+    const PREFIX = new Uint8Array(['0x00', '0x00', '0x00', '0x01']);
+
+    let firstIframe = false;
+
+    let SEIInfo = {
+        ivs: null,
+        timestamp: null,
+    };
+
+    let preWidth = null,
+        preHeight = null;
+    let resetTimeCount = 0;
+    let lastTimeStamp = 0;
+    //const RESETTIME = 162000000;
+    const RESETTIME = 4320000;
+    let SEIBuffer = null;
+    let lastSEITime = 0;
+
+    function constructor() {
+
+    }
+
+    constructor.prototype = {
+        init() {
+            SPSParser = new H264SPSParser();
+            this.resolutionChangedCallback = () => {
+            };
+        },
+
+        remuxRTPData(rtspInterleaved, rtpHeader, rtpPayload) {
+            //console.log(rtspInterleaved)
+            //console.log(rtpHeader)
+            let PaddingSize = 0;
+            let extensionHeaderLen = 0; //如果RtpHeader.X=1,则在RTP报头后跟有一个扩展报头
+            let PAYLOAD = null;
+//console.log(rtpHeader)
+//console.log(rtspInterleaved, rtpHeader, rtpPayload.subarray(0,5))
+            let RtpHeader = {
+                V: rtpHeader[0] >>> 6,
+                P: rtpHeader[0] & 0x20,
+                X: rtpHeader[0] & 0x10,
+                CC: rtpHeader[0] & 0x0F,
+                M: (rtpHeader[1] & 0x80) >> 7,
+                PT: rtpHeader[1] & 127,
+                SN: (rtpHeader[2] << 8) + rtpHeader[3],
+                timeStamp: (rtpHeader[4] << 24) + (rtpHeader[5] << 16) + (rtpHeader[6] << 8) + rtpHeader[7],
+                SSRC: (rtpHeader[8] << 24) + (rtpHeader[9] << 16) + (rtpHeader[10] << 8) + rtpHeader[11],
+            };
+            if (RtpHeader.P) { //填充
+                PaddingSize = rtpPayload[rtpPayload.length - 1];
+                // console.log("Padding - " + PaddingSize);
+            }
+
+            if (RtpHeader.X) { //扩展
+                extensionHeaderLen = (((rtpPayload[2] << 8) | rtpPayload[3]) * 4) + 4;
+                console.log('X: ' + rtpPayload[0])
+            }
+//console.log('extensionHeaderLen: '+ extensionHeaderLen)
+            PAYLOAD = rtpPayload.subarray(extensionHeaderLen, rtpPayload.length - PaddingSize);
+            rtpTimeStamp = RtpHeader.timeStamp;
+
+            //console.log(rtpTimeStamp, rtpHeader[4], rtpHeader[5], rtpHeader[6] , rtpHeader[7], PAYLOAD[0] & 0x1f)
+            /* 载荷结构(https://blog.csdn.net/davebobo/article/details/52994596)
+            +---------------+
+            |0|1|2|3|4|5|6|7|
+            +-+-+-+-+-+-+-+-+
+            |F|NRI|  Type   |
+            +---------------+
+            Type = 1-23 单个NAL单元包
+            Type = 24,25, 26, 27聚合包
+            Type = 28,29, 分片单元
+            */
+            //console.log(rtspInterleaved,rtpHeader, PAYLOAD[0]);
+            let nalType = (PAYLOAD[0] & 0x1f);
+            //console.log(PAYLOAD[0] + ' nalType: ' + nalType);
+
+//console.log('rtpPayload.length: ' + rtpPayload.length)
+//console.log(nalType, PAYLOAD[0])
+//console.log('nalType: ' + nalType, RtpHeader.M)
+            switch (nalType) {
+                case 6: //SEI
+                    //console.log(PAYLOAD, String.fromCharCode.apply(null, PAYLOAD))
+                    if (SEIParse(PAYLOAD) === null) {
+                        return;
+                    }
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    break;
+                case 7: //SPS
+                    //console.log('SPS');
+                    SPSParser.parse(removeH264or5EmulationBytes(PAYLOAD));
+                    let sizeInfo = SPSParser.getSizeInfo();
+                    //console.log(SPSParser.getSpsMap())
+                    width = sizeInfo.width;
+                    height = sizeInfo.height;
+
+                    if (preWidth !== width || preHeight !== height) {
+                        console.log('resolution changed!');
+                        console.log('preWidth: ', preWidth, ' preHeight: ', preHeight, ' width: ', width, ' height: ', height);
+                        preWidth = width;
+                        preHeight = height;
+                    }
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    spsSegment = PAYLOAD;
+                    //console.log('width: ',width, 'height: ', height)
+                    curSize = sizeInfo.decodeSize;
+                    firstIframe = true;
+//console.log(spsSegment)
+                    if (frameRate === null) {
+                        frameRate = SPSParser.getFPS();
+                    }
+                    break;
+                case 8: //PPS
+                    //console.log('PPS')
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    ppsSegment = PAYLOAD;
+//console.log(ppsSegment)
+                    break;
+                case 28: //FU
+                    //console.log('FU');
+                    let startBit = ((PAYLOAD[1] & 0x80) === 0x80),
+                        endBit = ((PAYLOAD[1] & 0x40) === 0x40),
+                        fuType = PAYLOAD[1] & 0x1f,
+                        payloadStartIndex = 2;
+                    //console.log('startBit: ' + startBit + ' endBit: ' + endBit)
+                    //console.log('fuType: ' + fuType)
+                    if (startBit === true && endBit === false) {
+                        let newNalHeader = new Uint8Array(1);
+                        newNalHeader[0] = ((PAYLOAD[0] & 0xe0) | fuType);
+                        //console.log('newNalHeader: ', newNalHeader[0])
+                        //console.log('fuType: ' + fuType)
+                        //console.log((PAYLOAD[2] << 8) + PAYLOAD[3])
+//console.log(new Uint8Array(PAYLOAD.subarray(0, 100)));
+                        if (false) { //赛兰摄像头,SPS,PPS,I帧打在一个RTP包中
+                            PAYLOAD[1] = newNalHeader[0];
+                            SPSParser.parse(removeH264or5EmulationBytes(PAYLOAD.subarray(1, 27)));
+                            let sizeInfo = SPSParser.getSizeInfo();
+//console.log(sizeInfo, SPSParser.getSpsMap())
+                            //SPS
+                            width = sizeInfo.width;
+                            height = sizeInfo.height;
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(1, 27));
+                            spsSegment = PAYLOAD.subarray(1, 27);
+                            //console.log('width: ',width, 'height: ', height)
+                            curSize = sizeInfo.decodeSize;
+                            firstIframe = true;
+
+                            //PPS
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(30, 34));
+                            ppsSegment = PAYLOAD.subarray(30, 34);
+
+                            //I
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(38, PAYLOAD.length));
+
+                        } else {
+                            //console.log(newNalHeader[0] & 0x1f)
+                            inputBuffer = setBuffer(inputBuffer, PREFIX);
+                            inputBuffer = setBuffer(inputBuffer, newNalHeader);
+                            inputBuffer = setBuffer(inputBuffer, PAYLOAD.subarray(payloadStartIndex, PAYLOAD.length));
+                        }
+
+                    } else {
+                        //console.log(startBit, endBit, 'endBit')
+                        inputBuffer = setBuffer(inputBuffer,
+                            PAYLOAD.subarray(payloadStartIndex, PAYLOAD.length));
+                    }
+//console.log(startBit,endBit)
+                    // if(endBit === true) {
+                    //     end = true;
+                    // }
+                    break;
+                case 1:
+                    inputBuffer = setBuffer(inputBuffer, PREFIX);
+                    inputBuffer = setBuffer(inputBuffer, PAYLOAD);
+                    break;
+                default:
+                    //console.log('nalType: ' + nalType);
+                    //console.log(PAYLOAD)
+                    break;
+            }
+//console.log('M: ' + RtpHeader.M + ' ' + (rtpHeader[1] & 0x80))
+            //check marker bit
+            if (RtpHeader.M) {
+                if (!firstIframe) {
+                    inputLength = 0;
+                    return;
+                }
+                let inputBufferSub = inputBuffer.subarray(0, inputLength);
+                frameType = FRAMETYPE[inputBufferSub[4] & 0x1f];
+
+                //只根据视频帧计算resetTimeCount
+                if (frameType !== 'SEI') {
+                    // rtp时间戳周期为RESETTIME,如果单向递增,设为0
+                    if (lastTimeStamp - rtpTimeStamp > (RESETTIME / 2)) { //判断lastTimeStamp远大于rtpTimeStamp,防止后一帧比前一帧先到的情况
+                        //console.log(lastTimeStamp - rtpTimeStamp)
+                        console.warn('时间戳重置', lastTimeStamp, rtpTimeStamp, frameType, new Date())
+                        resetTimeCount++;
+                    }
+                    rtpTimeStamp = rtpTimeStamp + RESETTIME * resetTimeCount;
+                } else {
+                    //同一帧的SEI比视频发送慢时
+                    if (rtpTimeStamp - lastTimeStamp > (RESETTIME / 2)) {
+                        console.warn('SEI翻转', rtpTimeStamp, lastTimeStamp);
+                        rtpTimeStamp = rtpTimeStamp + RESETTIME * (resetTimeCount - 1);
+                    } else {
+                        rtpTimeStamp = rtpTimeStamp + RESETTIME * resetTimeCount;
+                    }
+                    //同一帧的SEI比视频发送快时
+                    // if(rtpTimeStamp > lastTimeStamp) {
+                    //     rtpTimeStamp = rtpTimeStamp + RESETTIME * resetTimeCount;
+                    // } else {
+                    //     rtpTimeStamp = rtpTimeStamp + RESETTIME * (resetTimeCount + 1);
+                    // }
+                }
+//console.log('frameType: ', frameType, 'rtpTimeStamp: ', rtpTimeStamp)
+                if (frameType === 'SEI') {
+                    //SEI被分片(nal === 28)时,分片包发送完后marker为1,不会和视频帧一起
+                    SEIBuffer = inputBuffer.subarray(4, inputLength);
+                    //console.log(SEIBuffer)
+                    inputBufferSub = new Uint8Array();
+                }
+                if (SEIBuffer) {
+                    let SEI = SEIParse(SEIBuffer);
+                    if (SEI) {
+                        SEIInfo.ivs = SEI;
+                        SEIInfo.timestamp = rtpTimeStamp;
+                        decodedData.SEIInfo = SEIInfo;
+                        if ((rtpTimeStamp - lastSEITime) !== (90000 / frameRate)) {
+                            //console.log('SEI 时间差:', (rtpTimeStamp - lastTime), rtpTimeStamp, lastTime)
+                        }
+                        lastSEITime = rtpTimeStamp;
+                        SEIInfo = {
+                            ivs: null,
+                            timestamp: 0,
+                        };
+                    }
+                    SEIBuffer = null;
+                }
+
+                if (!initalSegmentFlag) {
+                    decodedData.initSegmentData = null;
+                    decodedData.codecInfo = null;
+                } else {
+                    initalSegmentFlag = false;
+                    const info = {
+                        id: 1,
+                        width: width,
+                        height: height,
+                        type: "video",
+                        profileIdc: SPSParser.getSpsValue("profile_idc"),
+                        profileCompatibility: 0,
+                        levelIdc: SPSParser.getSpsValue("level_idc"),
+                        sps: [spsSegment],
+                        pps: [ppsSegment],
+                        timescale: 1e3,
+                        fps: frameRate
+                    };
+                    decodedData.initSegmentData = info;
+                    decodedData.codecInfo = SPSParser.getCodecInfo();
+                    //console.log(info.pps)
+                }
+
+                if (frameType === 'I') {
+//console.log('ppsSegment: ', ppsSegment)
+                    let h264parameterLength = spsSegment.length + ppsSegment.length + 8;
+                    inputSegBufferSub = inputBufferSub.subarray(h264parameterLength, inputBufferSub.length);
+                } else {
+                    inputSegBufferSub = inputBufferSub.subarray(0, inputBufferSub.length);
+                }
+                if (inputSegBufferSub.length) {
+                    let segSize = inputSegBufferSub.length - 4;
+                    //mp4 box头
+                    inputSegBufferSub[0] = (segSize & 0xFF000000) >>> 24;
+                    inputSegBufferSub[1] = (segSize & 0xFF0000) >>> 16;
+                    inputSegBufferSub[2] = (segSize & 0xFF00) >>> 8;
+                    inputSegBufferSub[3] = (segSize & 0xFF);
+
+                    decodedData.frameData = new Uint8Array(inputSegBufferSub);
+
+                    let sample = {
+                        duration: Math.round((1 / frameRate) * 1000),
+                        size: inputSegBufferSub.length,
+                        frame_time_stamp: null,
+                        frameDuration: null,
+                    };
+                    sample.frame_time_stamp = rtpTimeStamp; //Todo:暂时为null,通过帧率控制duration
+                    if (initalMediaFrameFlag) {
+                        sample.frameDuration = 0;
+                        initalMediaFrameFlag = false;
+                    } else {
+                        if (frameRate) {
+                            frameCount++;
+                            if (!(frameCount % frameRate)) { //每秒最后一帧时
+                                sample.frameDuration = 1000 - durationTimeCount;
+                                frameCount = 0;
+                                durationTimeCount = 0;
+                            } else {
+                                sample.frameDuration = Math.round(1000 / frameRate);
+                                durationTimeCount += Math.round(1000 / frameRate);
+                            }
+                        } else {
+                            sample.frameDuration = (sample.frame_time_stamp - preSample.frame_time_stamp) / 90; // 时钟频率90000,timescale=1000
+                        }
+                        //console.log(sample.frameDuration)
+                    }
+                    preSample = sample;
+                    decodedData.mediaSample = sample;
+                    decodedData.timeStamp = rtpTimeStamp;
+                }
+                this.handleDecodedData(decodedData);
+                inputLength = 0;
+                decodedData.SEIInfo = null;
+                inputSegBufferSub = null;
+                if (frameType !== 'SEI') {
+                    lastTimeStamp = RtpHeader.timeStamp;
+                }
+                frameType = '';
+            }
+            //console.log('xxxxxxxxxxxxxxxxxxxxxxxxx')
+        },
+
+        set rtpSessionCallback(func) {
+            this.handleDecodedData = func;
+        },
+
+        setFrameRate(fps) {
+            frameRate = fps;
+            //console.log('frameRate: ', frameRate)
+        },
+
+        setResolutionChangedCallback(callback) {
+            this.resolutionChangedCallback = callback;
+        }
+    }
+
+    return new constructor();
+
+    function setBuffer(buffer1, buffer2) {
+        let bufferTemp = buffer1;
+        if ((inputLength + buffer2.length) > buffer1.length) {
+            bufferTemp = new Uint8Array(buffer1.length + size1M);
+        }
+
+        bufferTemp.set(buffer2, inputLength);
+        inputLength += buffer2.length;
+        return bufferTemp;
+    }
+}
+
+
+/**
+ * 去除SPS中的Emulation字节
+ * @param data SPS源数据
+ * @returns {Array} 去除后Emulation字节后的SPS
+ */
+function removeH264or5EmulationBytes(data) {
+    let toSize = 0;
+    let i = 0;
+    let to = [];
+    let dataLength = data.length;
+    while (i < dataLength) {
+        if (i + 2 < dataLength && data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 3) {
+            to[toSize] = to[toSize + 1] = 0;
+            toSize += 2;
+            i += 3;
+        } else {
+            to[toSize] = data[i];
+            toSize += 1;
+            i += 1;
+        }
+    }
+    return to;
+}
+
+/**
+ * 解析SEI信息
+ * @param data
+ * @return {Array}
+ */
+function SEIParse(data) {
+    //console.log(data)
+    if ((data[0] & 0x1f) !== 6) {
+        //非SEI
+        return null;
+    }
+
+    if (data[1] !== 0x55 || data[2] !== 0x4C || data[3] !== 0x53 || data[4] !== 0x40) {
+        //ULS@开头
+        console.warn('unknown SEI type',data);
+        return null;
+    }
+
+    let dataLength = data.length;
+    let type = (data[5] << 8) + data[6];
+    let checkSum = (data[7] << 8) + data[8];
+    // if(dataLength !== (checkSum + 1 + 4 + 4)) {
+    //     console.log('SEI check fail!');
+    //     return null;
+    // }
+    let result;
+    data = data.subarray(9);
+    switch (type) {
+        case 0:
+            result = parseFace(data);
+            break;
+        case 1:
+            //console.log(parseBody(data))
+            result = parseBody(data);
+            break;
+        case 2:
+            result = parseRegion(data);
+            break;
+        case 3:
+            result = parseBodyEx(data);
+            break;
+        case 4:
+            result = parseOverSpeed(data);
+            break;
+        default:
+            result = null;
+            break;
+    }
+    return result;
+}
+
+function parseFace(data) {
+    //console.log(data)
+    let dataLength = data.length;
+    let contents = [];
+    while (dataLength > 0) {
+        //console.log('dataLength: ', dataLength)
+        let x0 = ((data[4] & 0x7f) << 8) + data[5],
+            y0 = ((data[6] & 0x7f) << 8) + data[7],
+            width = ((data[8] & 0x7f) << 8) + data[9] - x0,
+            height = ((data[10] & 0x7f) << 8) + data[11] - y0;
+        let content = {
+            type: 'rect',
+            id: (data[2] << 8) + data[3],
+            rect: [x0, y0, width, height],
+            state: data[1] & 0x01,
+            quality: (data[1] & 0x02) >> 1,
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(12);
+        dataLength = data.length;
+    }
+
+    return contents;
+}
+
+function parseBody(data) {
+    let dataLength = data.length;
+    let contents = [];
+    while (dataLength > 0) {
+        //console.log('dataLength: ', dataLength)
+        let x0 = ((data[4] & 0x7f) << 8) + data[5],
+            y0 = ((data[6] & 0x7f) << 8) + data[7],
+            width = ((data[8] & 0x7f) << 8) + data[9] - x0,
+            height = ((data[10] & 0x7f) << 8) + data[11] - y0,
+            boxConfidence = ((data[12] & 0x7f) << 8) + data[13];
+        let points = [];
+
+        for (let i = 0; i < 17; i++) {
+            let point = {
+                x: ((data[16 + i * 8] & 0x7f) << 8) + data[17 + i * 8],
+                y: ((data[18 + i * 8] & 0x7f) << 8) + data[19 + i * 8],
+                confidence: ((data[20 + i * 8] & 0x7f) << 8) + data[21 + i * 8],
+                // x: Math.random() * 8191,
+                // y: Math.random() * 8191,
+                // confidence: 1,
+            };
+            points.push(point);
+        }
+        let content = {
+            type: 'coco-pose',
+            id: (data[2] << 8) + data[3],
+            handsUp: data[1] & 0x04,
+            boundingBox: [x0, y0, width, height],
+            boxConfidence,
+            points: parseBodyToTree(points),
+            state: data[1] & 0x01,
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(152);
+        dataLength = data.length;
+
+    }
+    return contents;
+}
+
+function parseRegion(data) {
+    let dataLength = data.length;
+    let contents = [];
+    while (dataLength > 0) {
+        let pointNum = (data[0] << 8) + data[1],
+            state = data[3] & 0x03,
+            area = [];
+
+        for (let i = 0; i < pointNum; i++) {
+            let point = {
+                x: ((data[i * 4 + 4] & 0x7f) << 8) + data[i * 4 + 5],
+                y: ((data[i * 4 + 6] & 0x7f) << 8) + data[i * 4 + 7],
+            };
+            area.push(point);
+        }
+        let content = {
+            type: 'region-detect',
+            state,
+            area
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(pointNum * 4 + 4);
+        dataLength = data.length;
+    }
+    return contents;
+}
+
+function parseBodyEx(data) {
+    let dataLength = data.length;
+    let contents = [];
+    while (dataLength > 0) {
+        //console.log('dataLength: ', dataLength)
+        let x0 = ((data[4] & 0x7f) << 8) + data[5],
+            y0 = ((data[6] & 0x7f) << 8) + data[7],
+            width = ((data[8] & 0x7f) << 8) + data[9] - x0,
+            height = ((data[10] & 0x7f) << 8) + data[11] - y0,
+            boxConfidence = ((data[12] & 0x7f) << 8) + data[13];
+        let points = [];
+
+        for (let i = 0; i < 17; i++) {
+            let point = {
+                x: ((data[16 + i * 8] & 0x7f) << 8) + data[17 + i * 8],
+                y: ((data[18 + i * 8] & 0x7f) << 8) + data[19 + i * 8],
+                confidence: ((data[20 + i * 8] & 0x7f) << 8) + data[21 + i * 8],
+            };
+            points.push(point);
+        }
+        let guides = [
+            {
+                x: ((data[16 + 17 * 8] & 0x7f) << 8) + data[17 + 17 * 8],
+                y: ((data[18 + 17 * 8] & 0x7f) << 8) + data[19 + 17 * 8],
+            },
+            {
+                x: ((data[20 + 17 * 8] & 0x7f) << 8) + data[21 + 17 * 8],
+                y: ((data[22 + 17 * 8] & 0x7f) << 8) + data[23 + 17 * 8],
+            }
+        ];
+        let content = {
+            type: 'coco-poseex',
+            id: (data[2] << 8) + data[3],
+            Loiter: data[1] & 0x03,
+            Standing: (data[1] & 0x04) >> 2,
+            Alone: (data[1] & 0x08) >> 3,
+            boundingBox: [x0, y0, width, height],
+            boxConfidence,
+            points: parseBodyToTree(points),
+            guides,
+            state: 1
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(160);
+        dataLength = data.length;
+
+    }
+    return contents;
+}
+
+function parseOverSpeed(data) {
+    let dataLength = data.length;
+    let contents = [];
+    while (dataLength > 0) {
+        //console.log('dataLength: ', dataLength)
+        let speed = ((data[4] & 0x7f) << 8) + data[5],
+            overSpeed = data[1] & 0x01;
+        let content = {
+            type: 'over-speed',
+            id: (data[2] << 8) + data[3],
+            speed,
+            overSpeed,
+            state: 1,
+        };
+        Array.prototype.push.apply(contents, [content]);
+        data = data.subarray(8);
+        dataLength = data.length;
+    }
+    return contents;
+}
+
+/**
+ * 将智能帧中的人体姿态点转化为树结构(双亲表示法)
+ * @param points
+ */
+function parseBodyToTree(points) {
+    let newPoints = [];
+    newPoints[0] = {...points[0], parent: -1, pointColor: '#FF0002', lineColor: '#FF0002'};
+    newPoints[1] = {...points[1], parent: 0, pointColor: '#FF0002', lineColor: '#FF0002'};
+    newPoints[2] = {...points[2], parent: 0, pointColor: '#FF0002', lineColor: '#FF0002'};
+    newPoints[3] = {...points[5], parent: 17, pointColor: '#D9E34F', lineColor: '#FF0002'};
+    newPoints[4] = {...points[6], parent: 17, pointColor: '#D9E34F', lineColor: '#FF0002'};
+    newPoints[5] = {...points[3], parent: 1, pointColor: '#00FF00', lineColor: '#FF0002'};
+    newPoints[6] = {...points[4], parent: 2, pointColor: '#FFAC00', lineColor: '#FF0002'};
+    newPoints[7] = {...points[7], parent: 3, pointColor: '#00FF45', lineColor: '#'};
+    newPoints[8] = {...points[11], parent: 17, pointColor: '#EEC446', lineColor: '#'};
+    newPoints[9] = {...points[8], parent: 4, pointColor: '#43D3AF', lineColor: '#'};
+    newPoints[10] = {...points[12], parent: 17, pointColor: '#7A93E8', lineColor: '#'};
+    newPoints[11] = {...points[9], parent: 7, pointColor: '#EFB842', lineColor: '#'};
+    newPoints[12] = {...points[13], parent: 8, pointColor: '#E56C00', lineColor: '#'};
+    newPoints[13] = {...points[10], parent: 9, pointColor: '#47CD43', lineColor: '#0096FF'};
+    newPoints[14] = {...points[14], parent: 10, pointColor: '#3868D2', lineColor: '#00FF51'};
+    newPoints[15] = {...points[15], parent: 12, pointColor: '#DF4D01', lineColor: '#5100FF'};
+    newPoints[16] = {...points[16], parent: 14, pointColor: '#1E48D4', lineColor: '#00FFA0'};
+    newPoints[17] = {
+        x: (points[5].x + points[6].x) / 2,
+        y: (points[5].y + points[6].y) / 2,
+        parent: -1,
+        pointColor: '#D9E34F',
+        lineColor: '#00FFA0'
+    };
+    return newPoints;
+}

+ 108 - 0
public/libs/videoWorker.js

@@ -0,0 +1,108 @@
+importScripts(
+    './H264SPSParser.js',
+    './H264Session.js',
+);
+
+
+addEventListener('message', receiveMessage);
+
+let sdpInfo = null;
+let rtpSession = null;
+let videoCHID = -1;
+let videoRtpSessionsArray = [];
+
+function  receiveMessage(event) {
+    //console.log(event.data)
+    var message = event.data;
+
+    switch (message.type) {
+        case 'sdpInfo':
+            sdpInfo = message.data;
+
+            initRTPSession(sdpInfo.sdpInfo);
+        case 'rtpDataArray':
+            //console.log(message.data.length)
+            for (let num = 0; num < message.data.length; num++) {
+                receiveMessage({
+                    'type': 'rtpData',
+                    'data': message.data[num],
+                });
+            }
+            break;
+        case 'rtpData':
+            videoCHID = message.data.rtspInterleave[1];
+            if (typeof videoRtpSessionsArray[videoCHID] !== "undefined") {
+                videoRtpSessionsArray[videoCHID].remuxRTPData(message.data.rtspInterleave,
+                    message.data.header, message.data.payload);
+            }else { // RTCP包
+                //console.log('Interleave:  ' + videoCHID);
+                //console.log(message.data.rtspInterleave, message.data.header);
+                //return;
+            }
+            break;
+    }
+}
+
+function initRTPSession(sdpInfo) {
+    for(let [i, len] = [0, sdpInfo.length]; i < len; i++) {
+        if(sdpInfo[i].codecName === 'H264') {
+            //console.log(sdpInfo)
+            rtpSession = new H264Session();
+            rtpSession.init();
+            rtpSession.rtpSessionCallback = RtpReturnCallback;
+            if(sdpInfo[i].Framerate) {
+                rtpSession.setFrameRate(sdpInfo[i].Framerate);
+            }
+        }
+
+        if(rtpSession !== null) {
+            videoCHID = sdpInfo[i].RtpInterlevedID;
+            videoRtpSessionsArray[videoCHID] = rtpSession;
+        }
+    }
+}
+
+function RtpReturnCallback(dataInfo) {
+
+    if(dataInfo === null || dataInfo === undefined) {
+        //console.log('数据为空')
+        return;
+    }
+    let mediaData = dataInfo;
+    if(mediaData.decodeMode === 'canvas') {
+        sendMessage('YUVData', mediaData.frameData);
+        return;
+    }
+    //console.log( mediaData.SEIInfo)
+    if(mediaData.initSegmentData !== null && mediaData.initSegmentData !== undefined) {
+        //sendMessage('codecInfo', mediaData.codecInfo)
+        //sendMessage('initSegment', mediaData.initSegmentData);
+        sendMessage('videoInit', mediaData);
+        sendMessage('firstvideoTimeStamp', mediaData.timeStamp);
+
+    }
+    if(mediaData.SEIInfo !== null && mediaData.SEIInfo !== undefined) {//SEI信息
+        sendMessage('SEI', mediaData.SEIInfo);
+    }
+
+    if (mediaData.frameData && mediaData.frameData.length > 0) {
+        sendMessage('videoTimeStamp', mediaData.timeStamp);
+        sendMessage('mediaSample', mediaData.mediaSample);
+        //console.log(mediaData.frameData.length)
+        sendMessage('videoRender', mediaData.frameData);
+    }
+    mediaData = null;
+}
+
+function sendMessage(type, data) {
+    let event = {
+        type: type,
+        data: data
+    }
+    if(type === 'videoRender') {
+        postMessage(event, [data.buffer]);
+    }else {
+        postMessage(event);
+    }
+    event = null;
+}

+ 24 - 0
src/App.vue

@@ -0,0 +1,24 @@
+<template>
+    <div id="app">
+        <router-view />
+    </div>
+</template>
+
+<script>
+export default {
+    created() {}
+};
+</script>
+
+<style lang="scss">
+#app {
+    height: 100%;
+    margin: 0;
+}
+body,
+html {
+    height: 100%;
+    width: 100%;
+    margin: 0 0 0 0;
+}
+</style>

+ 83 - 0
src/api/breed.js

@@ -0,0 +1,83 @@
+import { ajax } from "../sdk/ajax";
+
+/* seedSheepFile import { reqSeedSheepList } from '@/api/breed.js' */
+// 获取种羊档案
+export const reqSeedSheepList = (data) => ajax("post", "/farm-huyang/sheep/list", data)
+
+// 新增种羊档案
+export const reqAddSeedSheepFile = (data) => ajax("post", "/farm-huyang/sheep/add", data)
+
+// 删除种羊档案
+export const reqDelSeedSheepFile = (data) => ajax("post", "/farm-huyang/sheep/delete", data)
+
+
+/* 采精记录  Semen*/
+export const reqSemenList = (data) => ajax("post", "/farm-huyang/semen/list", data)
+
+export const reqAddOrUpdateSemen = (data) => ajax("post", "/farm-huyang/semen/addOrUpdate", data)
+
+export const reqDelSemen = (id) => ajax("post", "/farm-huyang/semen/delete", {id})
+
+
+/* 查情记录  matingS*/
+export const reqmatingSList = (data) => ajax("post", "/farm-huyang/estrus/list", data)
+
+export const reqAddOrUpdatematingS = (data) => ajax("post", "/farm-huyang/estrus/addOrUpdate", data)
+
+export const reqDelmatingS = (id) => ajax("post", "/farm-huyang/estrus/delete", {id})
+
+
+/* 配种记录  Mating*/
+export const reqMatingList = (data) => ajax("post", "/farm-huyang/breeding/list", data)
+
+export const reqAddOrUpdateMating = (data) => ajax("post", "/farm-huyang/breeding/addOrUpdate", data)
+
+export const reqDelMating = (id) => ajax("post", "/farm-huyang/breeding/delete", {id})
+
+
+/* 妊检记录  PregnancyTest*/
+export const reqPregnancyTestList = (data) => ajax("post", "/farm-huyang/pregnancy/list", data)
+
+export const reqAddOrUpdatePregnancyTest = (data) => ajax("post", "/farm-huyang/pregnancy/addOrUpdate", data)
+
+export const reqDelPregnancyTest = (id) => ajax("post", "/farm-huyang/pregnancy/delete", {id})
+
+
+/* 分娩记录  Parturition*/
+export const reqParturitionList = (data) => ajax("post", "/farm-huyang/deliver/list", data)
+
+export const reqAddOrUpdateParturition = (data) => ajax("post", "/farm-huyang/deliver/addOrUpdate", data)
+
+export const reqDelParturition = (id) => ajax("post", "/farm-huyang/deliver/delete", {id})
+
+
+/* 断奶记录  Weaning*/
+export const reqWeaningList = (data) => ajax("post", "/farm-huyang/weaning/list", data)
+
+export const reqAddOrUpdateWeaning = (data) => ajax("post", "/farm-huyang/weaning/addOrUpdate", data)
+
+export const reqDelWeaning = (id) => ajax("post", "/farm-huyang/weaning/delete", {id})
+
+
+/* 离场记录  OffField*/
+export const reqOffFieldList = (data) => ajax("post", "/farm-huyang/departure/list", data)
+
+export const reqAddOrUpdateOffField = (data) => ajax("post", "/farm-huyang/departure/addOrUpdate", data)
+
+export const reqDelOffField = (id) => ajax("post", "/farm-huyang/departure/delete", {id})
+
+
+/* 转舍记录  ShiftField*/
+export const reqShiftFieldList = (data) => ajax("post", "/farm-huyang/transfer/list", data)
+
+export const reqAddOrUpdateShiftField = (data) => ajax("post", "/farm-huyang/transfer/addOrUpdate", data)
+
+export const reqDelShiftField = (id) => ajax("post", "/farm-huyang/transfer/delete", {id})
+
+
+/* 商品羊档案 CommoditySheepFile reqAddOrUpdateCommoditySheepFile */
+export const reqCommoditySheepFileList = (data) => ajax("post", "/farm-huyang/commercial/list", data)
+
+export const reqAddCommoditySheepFile = (data) => ajax("post", "/farm-huyang/commercial/add", data)
+
+export const reqDelCommoditySheepFile = (id) => ajax("post", "/farm-huyang/commercial/delete", {id})

+ 32 - 0
src/api/fileInfo.js

@@ -0,0 +1,32 @@
+import { ajax } from "../sdk/ajax";
+
+/* 档案信息 */
+/* 企业信息 */
+export const reqFirminfo = () => ajax("get", "/publics/sysconf/get", {code: 'huyang_company'})
+
+export const reqUpdateFirm = (data) => ajax("post", "/publics/sysconf/update", data)
+
+
+/* 牧场信息 */
+export const reqPastureInfo = () => ajax("get", "/publics/sysconf/get", {code: 'huyang_farm_01'})
+
+export const reqUpdatePasture = (data) => ajax("get", "/publics/sysconf/update", data)
+
+
+
+/* 栋舍信息  Build = areaInfo*/
+export const reqBuildList = (data) => ajax("post", "/farm-huyang/building/list", data)
+
+export const reqAddOrUpdateBuild = (data) => ajax("post", "/farm-huyang/building/addOrUpdate", data)
+
+export const reqDelBuild = (id) => ajax("post", "/farm-huyang/building/delete", {id})
+
+
+
+/* 员工信息  Worker*/
+export const reqWorkerList = (data) => ajax("post", "/farm-huyang/employee/list", data)
+
+export const reqAddOrUpdateWorker = (data) => ajax("post", "/farm-huyang/employee/addOrUpdate", data)
+
+export const reqDelWorker = (id) => ajax("post", "/farm-huyang/employee/delete", {id})
+

+ 11 - 0
src/api/login.js

@@ -0,0 +1,11 @@
+import { ajax } from "../sdk/ajax";
+
+
+/* 登录 */
+export const reqLogin = (data) => ajax("post", "/core/auth/login", data)
+
+/* 选择组织 */
+export const reqOrgChoose = () => ajax("get", "/core/employ-relation/under-list")
+
+
+export const reqOrganizationId = (data) => ajax("POST", "/core/auth/choose-org",data)

+ 36 - 0
src/api/material.js

@@ -0,0 +1,36 @@
+import { ajax, upload } from "../sdk/ajax";
+// 物料管理
+
+/* 基础信息  BasicsInfo*/
+export const reqBasicsInfoList = (data) => ajax("post", "/farm-huyang/materiel/list", data)
+
+export const reqAddOrUpdateBasicsInfo = (data) => ajax("post", "/farm-huyang/materiel/addOrUpdate", data)
+
+export const reqDelBasicsInfo = (id) => ajax("post", "/farm-huyang/materiel/delete", {id})
+
+
+/* 物料库存  Store*/
+export const reqStoreList = (data) => ajax("post", "/farm-huyang/stock/list", data)
+
+export const reqAddStore = (data) => ajax("post", "/farm-huyang/stock/add", data)
+
+
+/* 物料入库  MInStore*/
+export const reqMInStoreList = (data) => ajax("post", "/farm-huyang/stockIn/list", data)
+
+export const reqAddMInStore = (data) => ajax("post", "/farm-huyang/stockIn/add", data)
+
+export const reqDelMInStore = (id) => ajax("post", "/farm-huyang/stockIn/delete", {id})
+
+
+/* 物料出库  MOutStore*/
+export const reqMOutStoreList = (data) => ajax("post", "/farm-huyang/stockOut/list", data)
+
+export const reqAddMOutStore = (data) => ajax("post", "/farm-huyang/stockOut/add", data)
+
+export const reqDelMOutStore = (id) => ajax("post", "/farm-huyang/stockOut/delete", {id})
+
+
+/* 图片上传 */
+// export const reqUploadImg = (data) => upload("/farm-huyang/common/pic", data)
+

+ 34 - 0
src/api/production.js

@@ -0,0 +1,34 @@
+import { ajax } from "../sdk/ajax";
+
+
+/* 批次管理  Batch*/
+export const reqBatchList = (data) => ajax("post", "/farm-huyang/batch/list", data)
+
+export const reqSeedEweSheepList = (data) => ajax("post", "/farm-huyang/commercial/listForBatch", data)
+
+export const reqAddBatch = (data) => ajax("post", "/farm-huyang/batch/create", data)
+
+
+
+/* 调拨转舍  ShiftField*/
+export const reqShiftFieldList = (data) => ajax("post", "/farm-huyang/batchTransfer/list", data)
+
+export const reqAddShiftField = (data) => ajax("post", "/farm-huyang/batchTransfer/add", data)
+
+
+/* 死淘管理  DieWeedOut*/
+export const reqDieWeedOutList = (data) => ajax("post", "/farm-huyang/culling/list", data)
+
+export const reqAddDieWeedOut = (data) => ajax("post", "/farm-huyang/culling/add", data)
+
+
+/* 耳标管理  EarTag*/
+export const reqEarTagList = (data) => ajax("post", "/farm-huyang/earTag/list", data)
+
+export const reqAddEarTag = (data) => ajax("post", "/farm-huyang/earTag/add", data)
+
+
+/* 检测报告  ExaminingReport*/
+export const reqExaminingReportList = (data) => ajax("post", "/farm-huyang/test/list", data)
+
+export const reqAddExaminingReport = (data) => ajax("post", "/farm-huyang/test/add", data)

+ 5 - 0
src/assets/css/reset.scss

@@ -0,0 +1,5 @@
+/* 公用scss */
+div,h1,h2,h3,h4,h5,h3,body,html,ul,li,p{margin: 0;padding: 0;}
+a{text-decoration: none;}
+li{list-style:none;} 
+/*css初始化完成*/

二进制
src/assets/deliveryRoom_1.png


二进制
src/assets/deliveryRoom_2.png


二进制
src/assets/deliveryRoom_3.png


二进制
src/assets/deliveryRoom_4.png


二进制
src/assets/login_bg.jpg


二进制
src/assets/logo.png


文件差异内容过多而无法显示
+ 1 - 0
src/assets/logo2.png


+ 127 - 0
src/components/uploadImg/test.vue

@@ -0,0 +1,127 @@
+<template>
+    <div>
+        <el-upload
+            action="#"
+            list-type="picture-card"
+            :before-upload="beforeUpload"
+            :auto-upload="true"
+        >
+            <i slot="default" class="el-icon-plus"></i>
+            <div slot="file" slot-scope="{file}">
+                <img class="el-upload-list__item-thumbnail" :src="file.url" alt />
+                <!-- <img class="el-upload-list__item-thumbnail" :src="imgUrl" alt /> -->
+                <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
+                        v-if="!disabled"
+                        class="el-upload-list__item-delete"
+                        @click="handleDownload(file)"
+                    >
+                        <i class="el-icon-download"></i>
+                    </span>
+                    <span
+                        v-if="!disabled"
+                        class="el-upload-list__item-delete"
+                        @click="handleRemove(file)"
+                    >
+                        <i class="el-icon-delete"></i>
+                    </span>
+                </span>
+            </div>
+        </el-upload>
+        <el-dialog :visible.sync="dialogVisible">
+            <img width="100%" :src="imgUrl" alt />
+        </el-dialog>
+    </div>
+</template>
+
+
+<script>
+import { reqUploadImg } from "@/api/material.js";
+// http://192.168.1.5:8016/files/2ceed3f6bfbfd9fc6d6c9b8c455158ec-1000.jpg  $attrs.value
+// http://192.168.1.5:8016/files/v2-996be5e52e4b43d08ae6ca8cae80b0fd_r.jpg
+// http://192.168.1.5:8016/files/v2-a862735c06feb9edce4369859daf5c12_r.jpg
+export default {
+    data() {
+        return {
+            dialogVisible: false,
+            disabled: false
+        };
+    },
+    props: {
+        value: String
+    },
+    watch: {
+        value(v, ov) {
+            console.log(v);
+        }
+    },
+    computed: {
+        imgUrl() {
+            return this.value;
+        }
+    },
+    created() {},
+    methods: {
+        beforeUpload(file) {
+            let formData = new FormData();
+            formData.append("photo", file, encodeURIComponent(file.name));
+            reqUploadImg(formData)
+                .then(res => {
+                    console.log(res);
+                    // this.$attrs.value = res
+                    // this.value = res;
+                    this.$emit("on-msg", res);
+                    // this.$set(this, 'value', res)
+                    console.log();
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+            return false;
+        },
+        handleRemove(file) {
+            console.log(file);
+        },
+        handlePictureCardPreview(file) {
+            this.imgUrl = file.url;
+            this.dialogVisible = true;
+        },
+        handleDownload(file) {
+            console.log(file);
+        }
+    }
+};
+</script>
+
+
+<style lang="scss" scope>
+.avatar-uploader .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 {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+}
+.avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+}
+</style>

+ 118 - 0
src/components/uploadImg/uploadImg.vue

@@ -0,0 +1,118 @@
+<template>
+    <div>
+        <!-- :action="serverAddress+'/farm-huyang/common/pic'"  photo-->
+        <!-- :action="serverAddress+'/publics/pic/upload'" pic -->
+        <el-upload
+            class="avatar-uploader"
+            :action="serverAddress+'/publics/pic/upload'"
+            :headers="{'x-auth-token': token}"
+            name="pic"
+            drag
+            :show-file-list="false"
+            :on-success="handleAvatarSuccess"
+            :before-upload="beforeAvatarUpload"
+        >
+            <img v-if="imgUrl" :src="imgUrl" class="avatar" />
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+        </el-upload>
+        <el-dialog :visible.sync="dialogVisible" append-to-body>
+            <img width="100%" :src="imgUrl" alt />
+        </el-dialog>
+        <el-link type="primary" @click="showBigImg">查看大图</el-link>
+    </div>
+</template>
+
+
+<script>
+import { reqUploadImg } from "@/api/material.js";
+import config from "@/sdk/config";
+const { serverAddress, IMG_BASE } = config;
+
+export default {
+    data() {
+        return {
+            serverAddress,
+            dialogVisible: false
+        };
+    },
+    props: {
+        value: String
+    },
+
+    computed: {
+        imgUrl() {
+            if(this.value) {
+                return IMG_BASE + this.value;
+            } else {
+                return ''
+            }
+        }
+    },
+    beforeCreate() {
+        this.token = localStorage.getItem("token");
+    },
+    created() {},
+    methods: {
+        aa(a) {
+            console.log(a);
+        },
+        handleAvatarSuccess(res, file) {
+            console.log(res);
+            this.$emit("on-msg", res);
+            // let imageUrl = URL.createObjectURL(file.raw);
+            // console.log(file)
+            // console.log(file.raw)
+            // console.log(imageUrl)
+            // console.log(typeof imageUrl)
+        },
+        beforeAvatarUpload(file) {
+            const isJPG = file.type === "image/jpeg" || "image/png";
+            const isLt2M = file.size / 1024 / 1024 <= 10;
+            console.log(file)
+            if (!isJPG) {
+                this.$message.error("上传图片只能是 JPG 或 png 格式!");
+            }
+            if (!isLt2M) {
+                this.$message.error("上传图片大小不能超过 10MB!");
+            }
+            return isJPG && isLt2M;
+        },
+        showBigImg() {
+            if(!this.imgUrl) {
+                this.$message.warning('请上传图片!');
+                return
+            }
+            this.dialogVisible = true
+        }
+    }
+};
+</script>
+
+
+<style lang="scss" scope>
+.avatar-uploader .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 {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+}
+.avatar {
+    // width: 178px;
+    width: 100%;
+    // height: 178px;
+    // height: 100%;
+    display: block;
+}
+</style>

+ 27 - 0
src/main.js

@@ -0,0 +1,27 @@
+import Vue from 'vue'
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import vueModuleLoader from 'vue-module-loader'
+import localModule from './module'
+import './assets/css/reset.scss'
+import 'default-passive-events' // ( https://www.jianshu.com/p/23850d4cade8 )
+// import echarts from "echarts";
+import moment from 'moment'
+moment.locale('zh-cn');  // 汉化
+Vue.prototype.$moment = moment; 
+// Vue.prototype.$echarts = echarts
+
+Vue.use(vueModuleLoader, { store }).use(ElementUI);
+
+
+const app = new Vue({
+	router,
+	store,
+	render: h => h(App)
+})
+
+app.$moduleLoader(localModule)
+app.$mount('#app')

+ 11 - 0
src/module.js

@@ -0,0 +1,11 @@
+import routes from './router/routes'
+import storeModule from './store/store-module'
+
+export default function(Vue) {
+  Vue.config.productionTip = false
+  this.$router.addRoutes(routes)
+  this.$store.registerModule('main', storeModule)
+  this.$eventBus.on('visitedAbout', () => {
+    alert('用户访问了about页面99。')
+  })
+}

+ 43 - 0
src/router/index.js

@@ -0,0 +1,43 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+// import store from '../store'
+
+import App from '../App.vue'
+import Login from '../views/Login/Login.vue'
+import Home from '../views/Home/Home.vue'
+
+
+Vue.use(VueRouter)
+
+const routes = [
+	{
+		path: '/',
+		component: App,
+		children: [
+			{
+				path: '',
+				redirect: '/login'
+			},
+		]
+	},
+	{
+		path: '/login',
+		name: 'login',
+		component: Login
+	},
+	{
+		path: '/home',
+		component: Home
+	},
+	{
+		path: '*',
+		name: '*',
+		component: Login
+	}
+]
+
+const router = new VueRouter({
+	routes
+})
+
+export default router

+ 70 - 0
src/router/routes.js

@@ -0,0 +1,70 @@
+import Home from '../views/Home/Home.vue'
+/* 档案信息 */
+import firmInfo from '@/views/fileInfo/firmInfo.vue'
+import pastureInfo from '@/views/fileInfo/pastureInfo.vue'
+import areaInfo from '@/views/fileInfo/areaInfo.vue'
+import workerInfo from '@/views/fileInfo/workerInfo.vue'
+
+/* 繁殖管理 */
+import seedSheepFile from '@/views/breed/seedSheepFile.vue'
+import commoditySheepFile from '@/views/breed/commoditySheepFile.vue'
+import collectSeedLog from '@/views/breed/collectSeedLog.vue'
+import matingSuccLog from '@/views/breed/matingSuccLog.vue'
+import matingLog from '@/views/breed/matingLog.vue'
+
+
+export default [
+	{
+		path: '/home',
+		component: Home,
+		children: [
+			/* 档案信息 */
+			{
+				path: 'firmInfo',
+				name: 'firmInfo',
+				component: firmInfo
+			},
+			{
+				path: 'pastureInfo',
+				name: 'pastureInfo',
+				component: pastureInfo
+			},
+			{
+				path: 'areaInfo',
+				name: 'areaInfo',
+				component: areaInfo
+			},
+			{
+				path: 'workerInfo',
+				name: 'workerInfo',
+				component: workerInfo
+			},
+			/* 繁殖管理 */
+			{
+				path: 'seedSheepFile',
+				name: 'seedSheepFile',
+				component: seedSheepFile
+			},
+			{
+				path: 'commoditySheepFile',
+				name: 'commoditySheepFile',
+				component: commoditySheepFile
+			},
+			{
+				path: 'collectSeedLog',
+				name: 'collectSeedLog',
+				component: collectSeedLog
+			},
+			{
+				path: 'matingSuccLog',
+				name: 'matingSuccLog',
+				component: matingSuccLog
+			},
+			{
+				path: 'matingLog',
+				name: 'matingLog',
+				component: matingLog
+			},
+		]
+	},
+]

+ 95 - 0
src/sdk/ajax.js

@@ -0,0 +1,95 @@
+import Vue from 'vue';
+import axios from 'axios';
+import VueAxios from 'vue-axios';
+import config from './config'
+import Qs from 'qs';
+
+const { serverAddress } = config
+
+// import DEV from "@/dev_config"; // 导入上线配置
+// const { ONLINE_BASE_HREF, SERVER_HREF } = DEV;
+
+Vue.use(VueAxios, axios)
+
+
+/* 常用ajax封装 (固定URL) */
+export const ajax = function (type = "post", url, params) {
+    let token = localStorage.getItem("token")
+    if (type.toLowerCase() == 'get') {
+        return new Promise((resole, reject) => {
+            axios({
+                method: type,
+                url: serverAddress + url,
+                params,
+                paramsSerializer: function (params) {
+                    return Qs.stringify(params, { arrayFormat: 'brackets' })
+                },
+                headers: {
+                    'Content-Type': 'application/x-www-form-urlencoded',
+                    'x-auth-token': token
+                }
+            }).then((res) => {
+                switch (res.data.errCode) {
+                    case 'request_not_authorize': // 登录过期
+                        let url = window.location.protocol + "//" + window.location.host + "/#/login"
+                        window.location.replace(url)
+                        break;
+                }
+                resole(res.data);
+            }).catch((err) => {
+                reject(err);
+            });
+        });
+    } else {
+        return new Promise((resole, reject) => {
+            axios({
+                method: type,
+                url: serverAddress + url,
+                params,
+                headers: {
+                    'Content-Type': 'application/x-www-form-urlencoded',
+                    'x-auth-token': token
+                }
+            }).then((res) => {
+                switch (res.data.errCode) {
+                    case 'request_not_authorize': // 登录过期
+                        let url = window.location.protocol + "//" + window.location.host + "/#/login"
+                        window.location.replace(url)
+                        break;
+                }
+                resole(res.data);
+            }).catch((err) => {
+                reject(err);
+            });
+        });
+    }
+}
+
+
+
+// export const upload = function (url, data) {
+//     let token = localStorage.getItem("token")
+//     return new Promise((resole, reject) => {
+//         axios({
+//             method: 'POST',
+//             url: serverAddress + url,
+//             data,
+//             headers: {
+//                 'Content-Type': 'multipart/form-data',
+//                 'x-auth-token': token
+//             }
+//         }).then((res) => {
+//             switch (res.data.errCode) {
+//                 case 'request_not_authorize': // 登录过期
+//                     let url = window.location.protocol + "//" + window.location.host + "/#/login"
+//                     window.location.replace(url)
+//                     break;
+//             }
+//             resole(res.data);
+//         }).catch((err) => {
+//             reject(err);
+//         });
+//     });
+// }
+
+

+ 6 - 0
src/sdk/config.js

@@ -0,0 +1,6 @@
+export default {
+  // http://192.168.1.6/uploads/20d27b607c8045279f7a41a7defa0d62.jpg
+  // http://115.238.57.190:8888/uploads/20d27b607c8045279f7a41a7defa0d62.jpg
+  serverAddress: 'http://115.238.57.190:8010',
+  IMG_BASE: 'http://115.238.57.190:8888/uploads/'
+}

+ 78 - 0
src/store/index.js

@@ -0,0 +1,78 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import publicType from './publicType.js' // 公共的类型 
+import { reqWorkerList, reqBuildList } from "@/api/fileInfo.js";
+import { reqBasicsInfoList, reqStoreList } from "@/api/material.js";
+import { reqBatchList } from "@/api/production.js";
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+	strict: true,
+	state: {
+		workerList: [{ id: 1 }], // 员工列表 (加{id:1} 是为了防止刷新时报错,因为设置默认值时用到过)
+		areaList: [{ id: 1 }],  // 栋舍列表
+		drugBasicsList: [{ id: 1 }],  // 基础药品列表
+		batchList: [],  // 批次列表
+		storeList: [],  // 库存列表
+		...publicType
+	},
+	getters: {},
+	mutations: {
+		setState(state, [key, val]) {
+			state[key] = val
+		}
+	},
+	actions: {
+		/* 获取员工列表 登录后再 home、workerInfo时调用了*/
+		getWorkerList({ commit }) {
+			reqWorkerList({
+				searchStr: '',
+				pageSize: 1000,
+				pageNum: 1
+			}).then(res => {
+				commit('setState', ['workerList', res.content])
+			})
+		},
+		/* 获取栋舍列表 登录后在  home、areaInfo时调用了*/
+		getAreaList({ commit }) {
+			reqBuildList({
+				searchStr: '',
+				pageSize: 1000,
+				pageNum: 1
+			}).then(res => {
+				commit('setState', ['areaList', res.content])
+			})
+		},
+		/* 获取基础药品列表 登录后在  home时调用了*/
+		getDrugBasicsList({ commit }) {
+			reqBasicsInfoList({
+				searchStr: '',
+				pageSize: 1000,
+				pageNum: 1
+			}).then(res => {
+				commit('setState', ['drugBasicsList', res.content])
+			})
+		},
+		/* 获取批次列表 登录后在 home、batch.vue时调用了*/
+		getBatchList({ commit }) {
+			reqBatchList({
+				searchStr: '',
+				pageSize: 1000,
+				pageNum: 1
+			}).then(res => {
+				commit('setState', ['batchList', res.content])
+			})
+		},
+		/* 获取库存列表 登录后在 storeList.vue时调用了*/
+		getStoreList({ commit }) {
+			reqStoreList({
+				searchStr: '',
+				pageSize: 1000,
+				pageNum: 1
+			}).then(res => {
+				commit('setState', ['storeList', res.content])
+			})
+		}
+	}
+})

+ 153 - 0
src/store/publicType.js

@@ -0,0 +1,153 @@
+// 种羊来源 类型
+const seedSheedSource = [
+    { label: "本场出生", value: 1 },
+    { label: "它场转入", value: 2 }
+]
+
+// 种羊等级
+const seedSheedLevel = [
+    { label: "甲", value: 1 },
+    { label: "乙", value: 2 },
+    { label: "丙", value: 3 },
+    { label: "丁", value: 4 }
+]
+
+// 种母羊状态
+const seedSheedStatus = [
+    { label: "后备", value: 1 },
+    // { label: "采精", value: 2 },
+    { label: "查情", value: 3 },
+    { label: "配种", value: 4 },
+    { label: "妊检", value: 5 },
+    { label: "分娩", value: 6 },
+    { label: "断奶", value: 7 },
+    { label: "淘汰", value: 8 }
+]
+
+// 种公羊状态
+const seedRamSheedStatus = [
+    { label: "后备", value: 1 },
+    { label: "配种", value: 4 }
+]
+
+// 商品羊状态
+const prductSheedStatus = [
+    { label: "羔羊", value: 1 },
+    { label: "育成羊", value: 2 },
+    { label: "商品羊", value: 3 },
+    { label: "无害化", value: 4 },
+    { label: "卖出", value: 5 }
+]
+
+
+// 精液色泽
+const seedColor = [
+    { label: "正常", value: 1 },
+    { label: "异常", value: 0 }
+]
+
+// 精液密度
+const seedDensity = [
+    { label: "密", value: 1 },
+    { label: "中", value: 2 },
+    { label: "稀", value: 3 }
+]
+
+// 怀孕状态
+const fetationStatus = [
+    { label: "正常", value: 1 },
+    { label: "空怀", value: 2 },
+    { label: "流产", value: 3 },
+    { label: "死胎", value: 4 }
+]
+
+// 发情状态
+const estrusStatus = [
+    { label: "未发情", value: 0 },
+    { label: "发情", value: 1 }
+]
+
+// 免疫类型
+const vaccineStyle = [
+    { label: "普免", value: 1 },
+    { label: "防疫", value: 2 }
+]
+
+// 羊类型 
+const sheepType = [
+    { label: "商品羊", value: 4 },
+    { label: "种母羊", value: 2 },
+    { label: "种公羊", value: 1 }
+]
+
+// 治疗状态
+const cureStatus = [
+    { label: "未治疗", value: 1 },
+    { label: "治疗中", value: 2 },
+    { label: "已治愈", value: 3 }
+]
+
+// 药品有效期单位
+const periodOfValidityUnit = [
+    { label: "天", value: 1 },
+    { label: "月", value: 2 },
+    { label: "年", value: 3 }
+]
+
+// 药品状态(基础信息)
+const drugStatus = [
+    { label: "禁用", value: 0 },
+    { label: "可用", value: 1 }
+]
+
+// 无害化确认状态 (修改此处, 需要修改 [ harmless/harmlessConfirm.vue ] 下的列表操作)
+const harmlessConfirmStatus = [
+    { label: "未确认", value: 0 },
+    { label: "已确认", value: 1 }
+]
+
+// 检测羊对象类型 (examiningReport.vue) 
+const examiningSheepType = [
+    { label: "羊只", value: 1 },
+    { label: "批次", value: 2 }
+]
+
+// 检测结果类型 (examiningReport.vue) 
+const examiningReportType = [
+    { label: "未通过", value: 0 },
+    { label: "通过", value: 1 }
+]
+
+// 设备类型  
+const deviceType = [
+    { label: "温度", value: 1 },
+    { label: "湿度", value: 2 },
+    { label: "摄像头", value: 3 }
+]
+
+// 设备状态  
+const deviceStatus = [
+    { label: "正常工作", value: 1 },
+    { label: "暂停使用", value: 2 },
+    { label: "故障", value: 3 }
+]
+
+/* workerList 员工列表  动态获取了 在home.vue中获取了 */
+/* areaList 栋舍信息  动态获取了 在home.vue中获取了 */
+/* drugBasicsList 基础药品列表   动态获取了 在home.vue中获取了 */
+/* batchList 批次列表   动态获取了 在home.vue、batch.vue中获取了 */
+/* storeList  // 库存列表   动态获取了 在home.vue、storeList.vue中获取了 */
+
+
+
+
+export default {
+    seedSheedSource, seedSheedLevel, seedSheedStatus, seedRamSheedStatus, prductSheedStatus, seedColor, seedDensity,
+    fetationStatus, estrusStatus, vaccineStyle, sheepType, cureStatus, periodOfValidityUnit, 
+    drugStatus, harmlessConfirmStatus, examiningSheepType, examiningReportType, deviceType,
+    deviceStatus
+}
+
+
+
+

+ 7 - 0
src/store/store-module.js

@@ -0,0 +1,7 @@
+export default {
+  namespaced: true,
+  state: {
+    title: 'vue-module'
+  },
+  mutations: {}
+}

+ 234 - 0
src/views/Home/Home.vue

@@ -0,0 +1,234 @@
+<template>
+    <div class="home">
+        <header class="header">
+            <div class="left">
+                湖羊大屏管理
+                <el-button
+                    @click="onMenuCollapse"
+                    circle
+                    style="font-size: 20px"
+                    :icon="menuCollapse? 'el-icon-s-unfold' : 'el-icon-s-fold'"
+                ></el-button>
+            </div>
+            <div class="right">
+                <span class="warp">
+                    <el-dropdown  @command="onLogOut">
+                        <span class="el-dropdown-link">
+                            账号管理
+                            <i class="el-icon-arrow-down el-icon--right"></i>
+                        </span>
+                        <el-dropdown-menu slot="dropdown">
+                            <el-dropdown-item>退出登录</el-dropdown-item>
+                            <el-dropdown-item>切换账号</el-dropdown-item>
+                        </el-dropdown-menu>
+                    </el-dropdown>
+                </span>
+                <span>
+                    <el-dropdown @command="onLogOut">
+                        <span class="el-dropdown-link">
+                            权限切换
+                            <i class="el-icon-arrow-down el-icon--right"></i>
+                        </span>
+                        <el-dropdown-menu slot="dropdown">
+                            <el-dropdown-item disabled>权限一</el-dropdown-item>
+                            <el-dropdown-item divided>权限二</el-dropdown-item>
+                        </el-dropdown-menu>
+                    </el-dropdown>
+                </span>
+            </div>
+        </header>
+        <section class="section">
+            <div class="tac">
+                <div class="col1">
+                    <el-menu
+                        default-active="2"
+                        class="el-menu-vertical-demo"
+                        @open="handleOpen"
+                        @close="handleClose"
+                        :collapse="menuCollapse"
+                        :unique-opened="true"
+                        :default-openeds="defaultUnfoldedMenu"
+                        select="1-1"
+                        background-color="#545c64"
+                        text-color="#fff"
+                        active-text-color="#ffd04b"
+                    >
+                        <div v-for="(item, index1) in menuData " :key="index1">
+                            <el-submenu
+                                v-if="item.childList && item.childList.length > 0"
+                                :index="`${index1}`"
+                            >
+                                <template slot="title">
+                                    <i :class="item.iconClassName"></i>
+                                    <span slot="title">{{ !menuCollapse? item.optionName : '' }}</span>
+                                </template>
+                                <el-menu-item
+                                    v-for="(item1, index2) in item.childList"
+                                    :key="`${index1}-${index2}`"
+                                    :index="`${index1}-${index2}`"
+                                    :routerName="item1.routerName"
+                                    @click="onClickMenu(item1)"
+                                >{{ item1.optionName }}</el-menu-item>
+                            </el-submenu>
+                            <el-menu-item
+                                v-else
+                                :index="`${index1}`"
+                                :disabled="item.disabled"
+                                :routerName="item.routerName"
+                                @click="onClickMenu(item)"
+                            >
+                                <i :class="item.iconClassName"></i>
+                                <span slot="title">{{ !menuCollapse? item.optionName : '' }}</span>
+                            </el-menu-item>
+                        </div>
+                    </el-menu>
+                </div>
+
+                <div class="col2">
+                    <div class="warp">
+                        <router-view />
+                    </div>
+                </div>
+
+            </div>
+        </section>
+    </div>
+</template>
+
+<script>
+import { menuData } from "./mencCofig.js";
+
+export default {
+    data() {
+        return {
+            // 菜单配置
+            menuData,
+            menuCollapse: false, //是否水平折叠收起菜单
+            defaultUnfoldedMenu: [menuData[0].index], // 默认展开第一项
+        };
+    },
+    created() {
+        this.defaultUnfoldedMenu = [
+            localStorage.getItem("defaultUnfoldedMenu")
+        ];
+        this.menuCollapse = JSON.parse(localStorage.getItem("menuCollapse"));
+        
+    },
+    mounted() {
+        // 获取员工列表 给后面下拉选择器使用
+        this.$store.dispatch('getWorkerList')
+        // 获取栋舍列表 给后面下拉选择器使用
+        this.$store.dispatch('getAreaList')
+        // 获取基础药品列表 给后面下拉选择器使用
+        this.$store.dispatch('getDrugBasicsList')
+        // 获取批次列表 给后面下拉选择器使用
+        this.$store.dispatch('getBatchList')
+        // 获取库存列表 给后面下拉选择器使用
+        this.$store.dispatch('getStoreList')
+    },
+    methods: {
+        // 收取菜单按钮
+        onMenuCollapse() {
+            this.menuCollapse = !this.menuCollapse;
+            localStorage.setItem("menuCollapse", this.menuCollapse);
+            this.defaultUnfoldedMenu = [
+                localStorage.getItem("defaultUnfoldedMenu")
+            ];
+        },
+        // 菜单展开
+        handleOpen(key, keyPath) {
+            localStorage.setItem("defaultUnfoldedMenu", "" + key);
+        },
+        // 菜单收取
+        handleClose(key, keyPath) {},
+        // 点击菜单项
+        onClickMenu(item) {
+            let _this = this;
+            // 如果要跳转的路由和当前路由一致就 return
+            if (this.$router.history.current.name == item.routerName) return;
+            this.$router.push({
+                name: item.routerName
+            });
+        },
+        onLogOut() {
+            this.$router.replace('login')
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.home {
+    height: 100%;
+    overflow: hidden;
+    box-sizing: border-box;
+    background-color: #eee;
+    display: flex;
+    flex-direction: column;
+    >.header {
+        background-color: #4b545e;
+        height: 40px;
+        padding: 10px 20px;
+        margin-bottom: 5px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .left {
+            font-size: 25px;
+            color: #fff;
+            /deep/ .is-circle {
+                margin-left: 40px;
+            }
+        }
+        .right {
+            .warp {
+                margin-right: 20px;
+            }
+        }
+    }
+    .section {
+        flex: 1;
+        box-sizing: border-box;
+        overflow: auto;
+        .tac {
+            flex: 1;
+            display: flex;
+            height: 96%;
+            box-sizing: border-box;
+            .col1 {
+                margin-right: 5px;
+                background-color: #545c64;
+                border-radius: 15px;
+                // background-image: linear-gradient(to bottom, rgb(85, 70, 148) , rgb(41, 33, 85), rgb(41, 33, 85));
+            }
+            .col2 {
+                flex: 1;
+                background-color: #fff;
+                padding: 0 15px 15px 15px;
+                border-radius: 5px;
+                margin-right: 5px;
+                height: 100%;
+                overflow: auto;
+                
+                .warp {
+                    margin: 15px;
+                }
+            }
+        }
+    }
+    // border: 1px solid #f00;
+}
+
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+    width: 200px;
+    min-height: 400px;
+}
+// 下拉菜单
+.el-dropdown-link {
+    cursor: pointer;
+    color: #fff;
+}
+.el-icon-arrow-down {
+    font-size: 12px;
+}
+</style>

+ 114 - 0
src/views/Home/mencCofig.js

@@ -0,0 +1,114 @@
+
+export const menuData = [
+    {
+        optionName: "档案信息",
+        iconClassName: "el-icon-files",
+        disabled: false, // 是否禁用
+        childList: [
+            {
+                optionName: '企业信息',
+                routerName: "firmInfo"
+            },
+            {
+                optionName: '牧场信息',
+                routerName: "pastureInfo"
+            },
+            {
+                optionName: '栋舍信息',
+                routerName: "areaInfo"
+            },
+            {
+                optionName: '员工信息',
+                routerName: "workerInfo"
+            }
+        ]
+    },
+    {
+        optionName: "繁殖管理",
+        iconClassName: "el-icon-magic-stick",
+        disabled: false, // 是否禁用
+        childList: [
+            {
+                optionName: '种羊档案',
+                routerName: "seedSheepFile"
+            },
+            {
+                optionName: '商品羊档案',
+                routerName: "commoditySheepFile"
+            },
+            {
+                optionName: '采精记录',
+                routerName: "collectSeedLog"
+            },
+            {
+                optionName: '查情记录',
+                routerName: "matingSuccLog"
+            },
+            {
+                optionName: '配种记录',
+                routerName: "matingLog"
+            },
+        ]
+    },
+    
+]
+
+// export default {menuData}
+
+
+
+
+/* 菜单配置 描述 */
+const menuData描述 = [
+    // 有子菜单 并且字菜单分组的
+    {
+        oneMenuName: "导航一", // 一级菜单名
+        iconClassName: "aaa", // element-ui图标名
+        childList: [ // 分组的
+            {
+                groupName: '组名一',
+                list: [
+                    {
+                        optionName: '选项1',
+                        routerName: "home"
+                    },
+                    {}
+                ],
+            },
+            {
+                groupName: '组名二',
+                list: [
+                    {
+                        optionName: '选项1',
+                        routerName: "home"
+                    },
+                    {}
+                ],
+            }
+        ],
+    },
+    // 有子菜单 字菜单不分组的
+    {
+        oneMenuName: "导航二",
+        iconClassName: "el-icon-menu",
+        disabled: false, // 是否禁用
+        childList: [ // 不分组的
+            {
+                optionName: '选项1',
+                routerName: "home"
+            },
+            {}
+        ]
+    },
+    // 无子菜单的
+    {
+        oneMenuName: "导航三",
+        iconClassName: "el-icon-document",
+        routerName: "home",
+        disabled: false
+    },
+
+    "导航四"
+]
+
+

+ 167 - 0
src/views/Login/Login.vue

@@ -0,0 +1,167 @@
+<template>
+    <div class="login">
+        <div class="shade">
+            <header class="header">
+                <img class="logo" src="../../assets/logo.png" alt="长兴湖羊LOGO" />
+                长兴湖羊
+            </header>
+            <article class="article">
+                <h1>登录界面</h1>
+                <el-form label-position="right" label-width="80px" :model="form">
+                    <el-form-item label="账号:">
+                        <el-input v-model="form.userName" placeholder="请输入账号"></el-input>
+                    </el-form-item>
+                    <el-form-item label="密码:">
+                        <el-input v-model="form.userPwd" placeholder="请输入密码" show-password></el-input>
+                    </el-form-item>
+                    <el-form-item>
+                        <el-button type="primary" @click="onSignIn">登录</el-button>
+                    </el-form-item>
+                </el-form>
+            </article>
+            <el-dialog title="请选择一个组织" :visible.sync="isShowDialog" append-to-body>
+                <el-select v-model="orgSelected">
+                    <el-option
+                        v-for="item in orgList"
+                        :key="item.id"
+                        :value="item.id"
+                        :label="item.orgName"
+                    ></el-option>
+                </el-select>
+                <div slot="footer">
+                    <el-button @click="isShowDialog=false">取 消</el-button>
+                    <el-button type="primary" @click="handleSet">设置</el-button>
+                </div>
+            </el-dialog>
+        </div>
+    </div>
+</template>
+<script>
+import { reqLogin, reqOrgChoose, reqOrganizationId } from "@/api/login";
+
+export default {
+    name: "login",
+    data() {
+        return {
+            form: {
+                userName: "huyang",
+                userPwd: "123456"
+            },
+            isShowDialog: false,
+            orgList: null,
+            orgSelected: null
+        };
+    },
+    created() {},
+    methods: {
+        /* 登录按钮 */
+        onSignIn() {
+            const loading = this.$loading({
+                lock: true,
+                text: "登录中...",
+                spinner: "el-icon-loading",
+                background: "rgba(0, 0, 0, 0.7)"
+            });
+            reqLogin(this.form)
+                .then(res => {
+                    loading.close();
+                    localStorage.setItem("token", res.token);
+                    this.doOrganizationChoose();
+                })
+                .catch(err => {
+                    console.log("登录失败", err);
+                    this.$message.error("登录失败:" + err);
+                });
+        },
+        handleSet: function() {
+            if (!this.orgSelected) {
+                this.$message.info("请先选择组织");
+            } else this.setOrganizationId(this.orgSelected);
+        },
+        doOrganizationChoose() {
+            this.loading = true;
+            reqOrgChoose()
+                .then(res => {
+                    if (res == null || res.length == 0) {
+                        this.$message.info("您没有加入任何组织!");
+                    } else if (res.length > 1) {
+                        this.isShowDialog = true;
+                        this.orgList = res;
+                    } else {
+                        this.setOrganizationId(res[0].id);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.loading = false;
+                    this.$message.error("登录失败:" + err);
+                });
+        },
+        setOrganizationId(id) {
+            if (!id) {
+                this.$message.error("发生了一点不愉快的错误!");
+                return;
+            }
+            this.loading = true;
+            reqOrganizationId({ orgId: id })
+                .then(res => {
+                    this.isShowDialog = false;
+                    //导航到 正式页面
+                    this.$router.replace("/home/firmInfo");
+                })
+                .catch(err => {
+                    if (err.errMsg) this.$message.error(err.errMsg);
+                    else this.$message.error("服务器发生异常");
+                })
+                .finally(res => {
+                    this.loading = false;
+                });
+        }
+    },
+    mounted() {}
+};
+</script>
+
+<style lang="scss" scoped>
+.login {
+    width: 100%;
+    height: 100%;
+    background: url(../../assets/login_bg.jpg) 0 0 no-repeat;
+    background-size: 100% 100%;
+    .shade {
+        height: 100%;
+        width: 100%;
+        background-color: #8899aa44;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        .header {
+            font-size: 60px;
+            color: #eee;
+            margin: 180px 0 50px 0;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            .logo {
+                height: 70px;
+                width: 70px;
+                margin-right: 20px;
+            }
+        }
+        .article {
+            width: 400px;
+            background-color: #ffffff44;
+            padding: 20px 60px 40px 20px;
+            border-radius: 20px;
+            h1 {
+                font-size: 20px;
+                color: #eee;
+                margin-left: 25px;
+            }
+            /deep/ .el-form-item .el-form-item__label {
+                color: #eee;
+            }
+        }
+    }
+}
+</style>

+ 52 - 0
src/views/aaaaaaaa.vue

@@ -0,0 +1,52 @@
+<template>
+    <div>
+        <el-form>
+            <el-form-item label="当前位置">
+                <el-select v-model="formData.position" filterable placeholder="请选择">
+                    <el-option
+                        v-for="item in $store.state['areaList']"
+                        :key="item.id"
+                        :label="item.name"
+                        :value="item.name"
+                    ></el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item label="密度">
+                <el-radio-group v-model="formData.density">
+                    <el-radio
+                        v-for="item in $store.state['seedDensity']"
+                        :key="item.value"
+                        :label="item.value"
+                    >{{ item.label }}</el-radio>
+                </el-radio-group>
+            </el-form-item>
+
+            <el-form-item label="配种时间">
+                <el-date-picker
+                    v-model="formData.opeTime"
+                    type="date"
+                    value-format="yyyy-MM-dd HH:mm:ss"
+                    placeholder="选择日期"
+                ></el-date-picker>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+
+
+<script>
+export default {
+    name: "Af",
+    data() {
+        return {
+            opeTime: this.$moment().format("YYYY-MM-DD"),
+            aa: this.$store.state['dispatchStatus'][0].value,
+        };
+    },
+    created() {},
+    methods: {
+        
+    }
+};
+</script>

+ 285 - 0
src/views/breed/collectSeedLog.vue

@@ -0,0 +1,285 @@
+<template>
+    <div class="collectSeedLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">采精记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请输入"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getSemenList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+                    <el-table-column prop="sheepId" label="种公羊编码"></el-table-column>
+                    <el-table-column label="等级">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedLevel']" :key="item.value">
+                                <span v-if="item.value == scope.row['level']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="采精时间" width="180">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="yield" label="射精量(ml)"></el-table-column>
+                    <el-table-column label="密度">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedDensity']" :key="item.value">
+                                <span v-if="item.value == scope.row['density']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="vigour" label="活力"></el-table-column>
+                    <el-table-column label="色泽">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedColor']" :key="item.value">
+                                <span v-if="item.value == scope.row['color']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="times" label="倍数"></el-table-column>
+                    <el-table-column prop="total" label="精液总量(ml)"></el-table-column>
+                    <el-table-column label="操作人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span v-if="item.id == scope.row['opeUser']">{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template v-slot="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addSemen" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="种公羊编号">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+                        <el-form-item label="等级">
+                            <el-select v-model="formData.level" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['seedSheedLevel']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                        <el-form-item label="采精时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+                        <el-form-item label="射精量(ml)">
+                            <el-input v-model="formData.yield"></el-input>
+                        </el-form-item>
+                        <el-form-item label="密度">
+                            <el-radio-group v-model="formData.density">
+                                <el-radio
+                                    v-for="item in $store.state['seedDensity']"
+                                    :key="item.value"
+                                    :label="item.value"
+                                >{{ item.label }}</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+                        <el-form-item label="活力">
+                            <el-input v-model="formData.vigour"></el-input>
+                        </el-form-item>
+                        <el-form-item label="色泽">
+                            <el-radio-group v-model="formData.color">
+                                <el-radio
+                                    v-for="item in $store.state['seedColor']"
+                                    :key="item.value"
+                                    :label="item.value"
+                                >{{ item.label }}</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+                        <el-form-item label="倍数">
+                            <el-input v-model="formData.times"></el-input>
+                        </el-form-item>
+                        <el-form-item label="精液总量(ml)">
+                            <el-input v-model="formData.total"></el-input>
+                        </el-form-item>
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addSemen')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqSemenList,
+    reqAddOrUpdateSemen,
+    reqDelSemen
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "collectSeedLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                sheepId: "12",
+                level: this.$store.state['seedSheedLevel'][0].value,
+                opeTime: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
+                yield: "0.4",
+                density: this.$store.state['seedDensity'][0].value,
+                vigour: "0.8",
+                color: this.$store.state['seedColor'][0].value,
+                times: "8",
+                total: "3",
+                opeUser: this.$store.state['workerList'][0].id
+            },
+            rules
+        };
+    },
+    created() {
+        // 采精记录列表
+        this.getSemenList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateSemen(this.formData)
+                        .then(res => {
+                            // 采精记录列表
+                            this.getSemenList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功!");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 采精记录列表
+        getSemenList() {
+            reqSemenList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelSemen(row.id)
+                .then(res => {
+                    // 采精记录列表
+                    this.getSemenList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error("删除失败!");
+                });
+        },
+        pageChange(p) {
+            console.log(p);
+            this.pageNum = p;
+            // 采精记录列表
+            this.getSemenList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 215 - 0
src/views/breed/commoditySheepFile.vue

@@ -0,0 +1,215 @@
+<template>
+    <!-- commoditySheepFile -->
+    <div class="CommoditySheepFile">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">商品羊档案</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getCommoditySheepFileList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table :data="tableData" tooltip-effect="dark" style="width: 100%">
+                    <el-table-column prop="id" label="商品羊编码"></el-table-column>
+
+                    <el-table-column prop="fatherId" label="父亲ID"></el-table-column>
+                    <el-table-column prop="motherId" label="母亲ID"></el-table-column>
+                    <el-table-column prop="birthWeight" label="出生重量(kg)"></el-table-column>
+                    <el-table-column label="出生时间">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['birthday'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="status" label="状态">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['prductSheedStatus']" :key="item.value">
+                                <span v-if="item.value == scope.row['status']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addCommoditySheepFile" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="商品羊编码">
+                            <el-input v-model="formData.id"></el-input>
+                        </el-form-item>
+                        <el-form-item label="母亲ID">
+                            <el-input v-model="formData.motherId"></el-input>
+                        </el-form-item>
+                        <el-form-item label="出生重量">
+                            <el-input v-model="formData.birthWeight"></el-input>
+                        </el-form-item>
+                        <el-form-item label="出生时间">
+                            <el-date-picker
+                                v-model="formData.birthday"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+                        <el-form-item label="状态">
+                            <el-select v-model="formData.status" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['prductSheedStatus']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addCommoditySheepFile')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqCommoditySheepFileList,
+    reqAddCommoditySheepFile,
+    reqDelCommoditySheepFile
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "CommoditySheepFile",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                id: "5300",
+                motherId: "1003",
+                birthWeight: "3.3",
+                birthday: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                status: this.$store.state["prductSheedStatus"][0].value
+            },
+            rules
+        };
+    },
+    created() {
+        // 商品羊档案列表
+        this.getCommoditySheepFileList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddCommoditySheepFile(this.formData)
+                        .then(res => {
+                            // 商品羊档案列表
+                            this.getCommoditySheepFileList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 商品羊档案列表
+        getCommoditySheepFileList() {
+            reqCommoditySheepFileList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelCommoditySheepFile(row.id)
+                .then(res => {
+                    // 商品羊档案列表
+                    this.getCommoditySheepFileList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error(err);
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 商品羊档案列表
+            this.getCommoditySheepFileList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 263 - 0
src/views/breed/matingLog.vue

@@ -0,0 +1,263 @@
+<template>
+    <div class="matingLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">配种记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getMatingList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table :data="tableData" tooltip-effect="dark" style="width: 100%">
+                    <el-table-column prop="id" label="序号"></el-table-column>
+
+                    <el-table-column prop="femaleSheepId" label="种母羊编码"></el-table-column>
+
+                    <el-table-column label="种母羊等级">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedLevel']" :key="item.value">
+                                <span v-if="item.value == scope.row['femaleLevel']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column prop="maleSheepId" label="种公羊编码"></el-table-column>
+
+                    <el-table-column label="种公羊等级">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedLevel']" :key="item.value">
+                                <span v-if="item.value == scope.row['maleLevel']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="配种时间">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="操作人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addMating" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="种母羊编码">
+                            <el-input v-model="formData.femaleSheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="种母羊等级">
+                            <el-select v-model="formData.femaleLevel" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['seedSheedLevel']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="种公羊编码">
+                            <el-input v-model="formData.maleSheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="种公羊等级">
+                            <el-select v-model="formData.maleLevel" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['seedSheedLevel']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="配种时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addMating')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqMatingList,
+    reqAddOrUpdateMating,
+    reqDelMating
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "matingLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                femaleSheepId: "182",
+                femaleLevel: this.$store.state["seedSheedLevel"][0].value,
+                maleSheepId: "121",
+                maleLevel: this.$store.state["seedSheedLevel"][0].value,
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                opeUser: this.$store.state["workerList"][0].id
+            },
+            rules
+        };
+    },
+    created() {
+        // 配种记录列表
+        this.getMatingList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateMating(this.formData)
+                        .then(res => {
+                            // 配种记录列表
+                            this.getMatingList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 配种记录列表
+        getMatingList() {
+            reqMatingList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelMating(row.id)
+                .then(res => {
+                    // 配种记录列表
+                    this.getMatingList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error("删除失败!");
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 配种记录列表
+            this.getMatingList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 259 - 0
src/views/breed/matingSuccLog.vue

@@ -0,0 +1,259 @@
+<template>
+    <div class="matingSSuccLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">查情记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getmatingSList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+
+                    <el-table-column prop="sheepId" label="种母羊编号"></el-table-column>
+
+                    <el-table-column label="种母羊等级">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedLevel']" :key="item.value">
+                                <span v-if="item.value == scope.row['level']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="查情时间">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="是否发情">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['estrusStatus']" :key="item.value">
+                                <span v-if="item.value == scope.row['ifEstrus']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="操作人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addmatingS" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="种母羊编码">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="等级">
+                            <el-select v-model="formData.level" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['seedSheedLevel']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="查情时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="是否发情">
+                            <el-radio-group v-model="formData.ifEstrus">
+                                <el-radio
+                                    v-for="item in $store.state['estrusStatus']"
+                                    :key="item.value"
+                                    :label="item.value"
+                                >{{ item.label }}</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addmatingS')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqmatingSList,
+    reqAddOrUpdatematingS,
+    reqDelmatingS
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "matingSSuccLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                sheepId: "182",
+                level: this.$store.state['seedSheedLevel'][0].value,
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                ifEstrus: this.$store.state['estrusStatus'][0].value,
+                opeUser: this.$store.state['workerList'][0].id,
+            },
+            rules
+        };
+    },
+    created() {
+        // 查情记录列表
+        this.getmatingSList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdatematingS(this.formData)
+                        .then(res => {
+                            // 查情记录列表
+                            this.getmatingSList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 查情记录列表
+        getmatingSList() {
+            reqmatingSList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelmatingS(row.id)
+                .then(res => {
+                    // 查情记录列表
+                    this.getmatingSList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error("删除失败!");
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 查情记录列表
+            this.getmatingSList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 244 - 0
src/views/breed/offFieldLog.vue

@@ -0,0 +1,244 @@
+<template>
+    <div class="offFieldLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">离场记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getOffFieldList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+                    <el-table-column prop="sheepId" label="羊只编码"></el-table-column>
+                    <el-table-column label="离场时间">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="ageOfDay" label="日龄(天)"></el-table-column>
+                    <el-table-column prop="weight" label="离场体重(kg)"></el-table-column>
+                    <el-table-column label="离场原因">
+                        <template v-slot="scope">
+                            <span v-if="scope.row['cause'] == 1">淘汰</span>
+                            <span v-if="scope.row['cause'] == 2">淘汰</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="饲养员">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ item.name }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="remark" label="备注"></el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addOffField" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="羊只编码">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="离场时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="日龄">
+                            <el-input v-model="formData.ageOfDay"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="离场体重(kg)">
+                            <el-input v-model="formData.weight"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="离场原因">
+                            <el-radio-group v-model="formData.cause">
+                                <el-radio :label="1">淘汰</el-radio>
+                                <el-radio :label="2">死亡</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+
+                        <el-form-item label="饲养员">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="备注">
+                            <el-input type="testarea" v-model="formData.remark"></el-input>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addOffField')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqOffFieldList,
+    reqAddOrUpdateOffField,
+    reqDelOffField
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "OffFieldLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                sheepId: "182",
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                ageOfDay: '32',
+                weight: 5.8,
+                cause: 1,
+                opeUser: this.$store.state['workerList'][0].id,
+                remark: "这只小羊不乖!!"
+            },
+            rules
+        };
+    },
+    created() {
+        // 离场记录  列表
+        this.getOffFieldList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateOffField(this.formData)
+                        .then(res => {
+                            // 离场记录 列表
+                            this.getOffFieldList();
+                            this.$message.success("成功!");
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 离场记录 列表
+        getOffFieldList() {
+            reqOffFieldList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelOffField(row.id)
+                .then(res => {
+                    // 离场记录 列表
+                    this.getOffFieldList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error(err);
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 离场记录 列表
+            this.getOffFieldList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 253 - 0
src/views/breed/parturitionLog.vue

@@ -0,0 +1,253 @@
+<template>
+    <div class="parturitionLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">分娩记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getParturitionList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+                    <el-table-column prop="sheepId" label="种母羊编号"></el-table-column>
+                    <el-table-column label="分娩时间" width="180">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="number" label="产羔个数"></el-table-column>
+                    <el-table-column prop="averageWeight" label="羔羊均重(kg)"></el-table-column>
+                    <el-table-column prop="healthyNum" label="健仔数"></el-table-column>
+                    <el-table-column prop="weakNum" label="弱仔数"></el-table-column>
+                    <el-table-column prop="mummyNum" label="木乃伊"></el-table-column>
+                    <el-table-column prop="deadNum" label="死羔数"></el-table-column>
+                    <el-table-column label="操作人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addParturition" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="种母羊编码">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="分娩时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="产羔个数">
+                            <el-input-number v-model="formData.number" :min="0" :max="5" label="描述文字"></el-input-number>
+                        </el-form-item>
+
+                        <el-form-item label="羔羊均重(kg)">
+                            <el-input v-model="formData.averageWeight"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="健仔数">
+                            <el-input-number v-model="formData.healthyNum" :min="0" :max="5" label="描述文字"></el-input-number>
+                        </el-form-item>
+
+                        <el-form-item label="弱仔数">
+                            <el-input-number v-model="formData.weakNum" :min="0" :max="5" label="描述文字"></el-input-number>
+                        </el-form-item>
+
+                        <el-form-item label="木乃伊">
+                            <el-input-number v-model="formData.mummyNum" :min="0" :max="5" label="描述文字"></el-input-number>
+                        </el-form-item>
+
+                        <el-form-item label="死羔数">
+                            <el-input-number v-model="formData.deadNum" :min="0" :max="5" label="描述文字"></el-input-number>
+                        </el-form-item>
+
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addParturition')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqParturitionList,
+    reqAddOrUpdateParturition,
+    reqDelParturition
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "parturitionLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                sheepId: "182",
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                number: 1,
+                averageWeight: '3.1',
+                healthyNum: 1,
+                weakNum: 0,
+                mummyNum: 0,
+                deadNum: 0,
+                opeUser: this.$store.state['workerList'][0].id,
+            },
+            rules
+        };
+    },
+    created() {
+        // 分娩记录列表
+        this.getParturitionList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateParturition(this.formData)
+                        .then(res => {
+                            // 分娩记录列表
+                            this.getParturitionList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error(err);
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 分娩记录列表
+        getParturitionList() {
+            reqParturitionList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelParturition(row.id)
+                .then(res => {
+                    // 分娩记录列表
+                    this.getParturitionList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error(err);
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 分娩记录列表
+            this.getParturitionList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 281 - 0
src/views/breed/pregnancyTestLog.vue

@@ -0,0 +1,281 @@
+<template>
+    <div class="pregnancyTestLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">妊检记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getPregnancyTestList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+
+                    <el-table-column prop="sheepId" label="种母羊编号"></el-table-column>
+
+                    <el-table-column label="妊检时间">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="状态">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['fetationStatus']" :key="item.value">
+                                <span v-if="item.value == scope.row['status']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column label="操作人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+
+                    <el-table-column prop="position" label="当前位置"></el-table-column>
+
+                    <el-table-column prop="number" label="怀胎个数"></el-table-column>
+
+                    <el-table-column prop="remark" label="备注"></el-table-column>
+
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form
+                        ref="addPregnancyTest"
+                        :model="formData"
+                        :rules="rules"
+                        label-width="140px"
+                    >
+                        <el-form-item label="种母羊编码">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="妊检时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="状态">
+                            <!-- <el-radio-group v-model="formData.ifEstrus">
+                                <el-radio
+                                    v-for="item in $store.state['fetationStatus']"
+                                    :key="item.value"
+                                    :label="item.value"
+                                >{{ item.label }}</el-radio>
+                            </el-radio-group> -->
+                            <el-select v-model="formData.status" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['fetationStatus']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="当前位置">
+                            <el-select v-model="formData.position" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['areaList']"
+                                    :key="item.id"
+                                    :label="item.name"
+                                    :value="item.name"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="怀胎个数">
+                            <el-input v-model="formData.number"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="备注">
+                            <el-input type="textarea" v-model="formData.remark"></el-input>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addPregnancyTest')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqPregnancyTestList,
+    reqAddOrUpdatePregnancyTest,
+    reqDelPregnancyTest
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "pregnancyTestLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                sheepId: "182",
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                status: this.$store.state['fetationStatus'][0].value,
+                opeUser: this.$store.state['workerList'][0].id,
+                position: null,
+                number: '2',
+                remark: '这只羊怀孕了',
+            },
+            rules
+        };
+    },
+    created() {
+        // 妊检记录列表
+        this.getPregnancyTestList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdatePregnancyTest(this.formData)
+                        .then(res => {
+                            // 妊检记录列表
+                            this.getPregnancyTestList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error(err);
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 妊检记录列表
+        getPregnancyTestList() {
+            reqPregnancyTestList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelPregnancyTest(row.id)
+                .then(res => {
+                    // 妊检记录列表
+                    this.getPregnancyTestList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error(err);
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 妊检记录列表
+            this.getPregnancyTestList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 303 - 0
src/views/breed/seedSheepFile.vue

@@ -0,0 +1,303 @@
+<template>
+    <div class="seedSheepFile">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">种羊档案</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="searchStr" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getSeedSheepList">查找</el-button>
+                </el-col>
+                <el-col :span="10">
+                    <el-button type="primary" @click="add">新增档案</el-button>暂时别删,要测试删除的话,先自己新增几条数据,别删已经存在的,这关乎到系谱信息档案
+                </el-col>
+                <el-col :span="4">
+                    <el-button-group>
+                        <el-button :type="sheepType==0?'primary':''" @click="shiftSheepType(0)">种母羊</el-button>
+                        <el-button :type="sheepType==1?'primary':''" @click="shiftSheepType(1)">种公羊</el-button>
+                    </el-button-group>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table :data="tableData" tooltip-effect="dark" style="width: 100%">
+                    <el-table-column prop="id" label="种羊编码" width="100"></el-table-column>
+                    <el-table-column label="入场时间" width="200">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['entryTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="dayOfAge" label="入场日龄"></el-table-column>
+                    <el-table-column label="种羊来源">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedSource']" :key="item.value">
+                                <span v-if="item.value == scope.row['source']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="position" label="当前位置"></el-table-column>
+                    <el-table-column label="当前状态">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedStatus']" :key="item.value">
+                                <span v-if="item.value == scope.row['status']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="cost" label="成本价格(元)"></el-table-column>
+                    <el-table-column prop="weight" label="体重(kg)"></el-table-column>
+                    <el-table-column prop="feederName" label="饲养员">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['feeder']"
+                                >{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="等级评级">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['seedSheedLevel']" :key="item.value">
+                                <span v-if="item.value == scope.row['level']">{{ item.label }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template v-slot="scope">
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增种羊档案" :visible.sync="isShow" width="45%">
+            <el-row type="flex">
+                <el-col :span="15">
+                    <el-form
+                        ref="addSeedSheepForm"
+                        :model="formData"
+                        :rules="rules"
+                        label-width="140px"
+                    >
+                        <el-form-item label="种羊编码">
+                            <el-input v-model="formData.id"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="日龄">
+                            <el-input v-model="formData.dayOfAge"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="种羊来源">
+                            <el-radio-group v-model="formData.source">
+                                <el-radio
+                                    v-for="item in $store.state['seedSheedSource']"
+                                    :key="item.value"
+                                    :label="item.value"
+                                >{{ item.label }}</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+
+                        <el-form-item label="当前位置">
+                            <el-select v-model="formData.position" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['areaList']"
+                                    :key="item.id"
+                                    :label="item.name"
+                                    :value="item.name"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item v-if="sheepType==0" label="当前状态" >
+                            <el-select v-model="formData.status" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['seedSheedStatus']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                        <el-form-item v-if="sheepType==1" label="当前状态">
+                            <el-select v-model="formData.status" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['seedRamSheedStatus']"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="成本价格(元)">
+                            <el-input v-model="formData.cost"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="体重(kg)">
+                            <el-input v-model="formData.weight"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="饲养员">
+                            <el-select v-model="formData.feeder" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="等级评级">
+                            <el-radio-group v-model="formData.level">
+                                <el-radio
+                                    v-for="item in $store.state['seedSheedLevel']"
+                                    :key="item.value"
+                                    :label="item.value"
+                                >{{ item.label }}</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addSeedSheepForm')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqSeedSheepList,
+    reqAddSeedSheepFile,
+    reqDelSeedSheepFile
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    data() {
+        return {
+            page: 1,
+            searchStr: "",
+            sheepType: 0,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            rules,
+            formData: {
+                id: '',
+                dayOfAge: "222",
+                source: 1,
+                position: "",
+                status: null,
+                cost: 3000,
+                weight: 48,
+                feeder: this.$store.state["workerList"][0].id,
+                level: 1
+            }
+        };
+    },
+    created() {
+        this.getSeedSheepList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    // 新增种羊档案
+                    this.formData.gender = this.sheepType
+                    reqAddSeedSheepFile(this.formData)
+                        .then(res => {
+                            // 获取种羊档案列表
+                            this.getSeedSheepList();
+                            // this.$message.success("新增种羊档案成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error(err);
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 获取种羊档案列表
+        getSeedSheepList() {
+            reqSeedSheepList({
+                pageNum: this.page,
+                pageSize,
+                gender: this.sheepType,
+                searchStr: this.searchStr
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        // 羊类型切换
+        shiftSheepType(sheepType) {
+            if(sheepType == this.sheepType) return
+            this.sheepType = sheepType
+            this.getSeedSheepList()
+        },
+
+        add() {
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelSeedSheepFile({ id: row.id })
+                .then(res => {
+                    this.getSeedSheepList();
+                    this.$message.success("删除种羊档案成功!");
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error("删除种羊档案失败!");
+                });
+        },
+        pageChange(p) {
+            this.page = p;
+            this.getSeedSheepList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 283 - 0
src/views/breed/shiftFieldLog.vue

@@ -0,0 +1,283 @@
+<template>
+    <div class="shiftFieldLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">转舍记录</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getShiftFieldList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+                    <el-table-column prop="sheepId" label="羊只编码"></el-table-column>
+                    <el-table-column label="转舍时间" width="180">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="转出栋舍">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['areaList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['fromBuilding']"
+                                >{{ item.name }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="fromEnclosure" label="转出栏位"></el-table-column>
+
+                    <el-table-column label="转入栋舍">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['areaList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['toBuilding']"
+                                >{{ item.name }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="toEnclosure" label="转入栏位"></el-table-column>
+
+                    <el-table-column prop="weight" label="转出重量(kg)"></el-table-column>
+                    <el-table-column label="饲养员">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ item.name }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="remark" label="备注"></el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addShiftField" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="羊只编码">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="转舍时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="转出栋舍">
+                            <el-select v-model="formData.opeUser" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['areaList']"
+                                    :key="item.id"
+                                    :label="`${item.name}`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                        <el-form-item label="转出栏位">
+                            <el-input v-model="formData.fromEnclosure"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="转入栋舍">
+                            <el-select v-model="formData.toBuilding" placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['areaList']"
+                                    :key="item.id"
+                                    :label="`${item.name}`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                        <el-form-item label="转入栏位">
+                            <el-input v-model="formData.toEnclosure"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="转出重量(kg)">
+                            <el-input v-model="formData.weight"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item label="备注">
+                            <el-input type="testarea" v-model="formData.remark"></el-input>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addShiftField')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqShiftFieldList,
+    reqAddOrUpdateShiftField,
+    reqDelShiftField
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "shiftFieldLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                sheepId: "182",
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                fromBuilding: this.$store.state['areaList'][0].id,
+                fromEnclosure: '01号栏位',
+                toBuilding: this.$store.state['areaList'][0].id,
+                toEnclosure: '02号栏位',
+                weight: '42',
+                opeUser: this.$store.state['workerList'][0].id,
+                remark: "这只羊不乖!!"
+            },
+            rules
+        };
+    },
+    created() {
+        // 转舍记录  列表
+        this.getShiftFieldList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateShiftField(this.formData)
+                        .then(res => {
+                            // 转舍记录 列表
+                            this.getShiftFieldList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error(err);
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 转舍记录 列表
+        getShiftFieldList() {
+            reqShiftFieldList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelShiftField(row.id)
+                .then(res => {
+                    // 转舍记录 列表
+                    this.getShiftFieldList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error(err);
+                });
+        },
+        pageChange(p) {
+            this.pageNum = p;
+            // 转舍记录 列表
+            this.getShiftFieldList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 236 - 0
src/views/breed/weaningLog.vue

@@ -0,0 +1,236 @@
+<template>
+    <div class="weaningLog">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">断奶信息</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getWeaningList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号"></el-table-column>
+                    <el-table-column label="断奶时间">
+                        <template v-slot="scope">
+                            <span>{{ scope.row['opeTime'].substr(0,10) }}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="sheepId" label="种母羊编码"></el-table-column>
+                    <el-table-column prop="number" label="羔羊数量(只)"></el-table-column>
+                    <el-table-column prop="weight" label="断奶均重量(kg)"></el-table-column>
+                    <el-table-column prop="cost" label="断奶成本(元)"></el-table-column>
+                    <el-table-column label="操作人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span
+                                    v-if="item.id == scope.row['opeUser']"
+                                >{{ `${item.name}(${item.position})` }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addWeaning" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="种母羊编码">
+                            <el-input v-model="formData.sheepId"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="断奶时间">
+                            <el-date-picker
+                                v-model="formData.opeTime"
+                                type="date"
+                                value-format="yyyy-MM-dd HH:mm:ss"
+                                placeholder="选择日期"
+                            ></el-date-picker>
+                        </el-form-item>
+
+                        <el-form-item label="羔羊数量">
+                            <el-input-number v-model="formData.number" :min="0" :max="5" label="描述文字"></el-input-number>
+                        </el-form-item>
+
+                        <el-form-item label="断奶均重量(kg)">
+                            <el-input v-model="formData.weight"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="断奶成本">
+                            <el-input v-model="formData.cost"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="操作人">
+                            <el-select v-model="formData.opeUser" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addWeaning')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqWeaningList,
+    reqAddOrUpdateWeaning,
+    reqDelWeaning
+} from "@/api/breed.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "weaningLog",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                opeTime: this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+                sheepId: "182",
+                number: 1,
+                weight: '3.1',
+                cost: '482',
+                opeUser: this.$store.state['workerList'][0].id,
+            },
+            rules
+        };
+    },
+    created() {
+        // 断奶信息列表
+        this.getWeaningList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateWeaning(this.formData)
+                        .then(res => {
+                            // 断奶信息列表
+                            this.getWeaningList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error(err);
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 断奶信息列表
+        getWeaningList() {
+            reqWeaningList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelWeaning(row.id)
+                .then(res => {
+                    // 断奶信息列表
+                    this.getWeaningList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error(err);
+                });
+        },
+        pageChange(p) {
+            console.log(p);
+            this.pageNum = p;
+            // 断奶信息列表
+            this.getWeaningList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 209 - 0
src/views/fileInfo/areaInfo.vue

@@ -0,0 +1,209 @@
+<template>
+    <!-- 静态  栋舍信息 areaInfo-->
+    <div class="areaInfo">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">栋舍信息</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getBuildList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号" width="80"></el-table-column>
+                    <el-table-column prop="name" label="栋舍" width="180"></el-table-column>
+                    <el-table-column prop="capacity" label="最大容量" width="180"></el-table-column>
+                    <el-table-column prop="manager" label="负责人">
+                        <template v-slot="scope">
+                            <div v-for="item in $store.state['workerList']" :key="item.value">
+                                <span v-if="item.id == scope.row['manager']">{{ item.name }}</span>
+                            </div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template slot-scope="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addBuild" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="栋舍名字">
+                            <el-input v-model="formData.name"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="最大容量">
+                            <el-input v-model="formData.capacity"></el-input>
+                        </el-form-item>
+
+                        <el-form-item label="负责人">
+                            <el-select v-model="formData.manager" filterable placeholder="请选择">
+                                <el-option
+                                    v-for="item in $store.state['workerList']"
+                                    :key="item.id"
+                                    :label="`${item.name}(${item.position})`"
+                                    :value="item.id"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addBuild')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqBuildList,
+    reqAddOrUpdateBuild,
+    reqDelBuild
+} from "@/api/fileInfo.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "areaInfo",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                name: "保育一舍",
+                capacity: "156",
+                manager: this.$store.state.workerList[0].id
+            },
+            rules
+        };
+    },
+    created() {
+        // 入库管理列表
+        this.getBuildList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateBuild(this.formData)
+                        .then(res => {
+                            // 入库管理列表
+                            this.getBuildList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            // this.isShow = false;
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                 
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 入库管理列表
+        getBuildList() {
+            reqBuildList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelBuild(row.id)
+                .then(res => {
+                    console.log(res);
+                    // 入库管理列表
+                    this.getBuildList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        pageChange(p) {
+            console.log(p);
+            this.pageNum = p;
+            // 入库管理列表
+            this.getBuildList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 121 - 0
src/views/fileInfo/firmInfo.vue

@@ -0,0 +1,121 @@
+<template>
+    <div class="firmInfo">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">企业信息</h2>
+        <div class="left">
+            <el-form ref="form" :model="form">
+                <el-form-item label="企业名称">
+                    <el-input v-model="form.name"></el-input>
+                </el-form-item>
+                <el-form-item label="邮箱">
+                    <el-input v-model="form.email"></el-input>
+                </el-form-item>
+                <el-form-item label="企业简介">
+                    <el-input type="textarea" v-model="form.decription"></el-input>
+                </el-form-item>
+                <el-form-item label="国家地区">
+                    <el-input v-model="form.province"></el-input>
+                </el-form-item>
+                <el-form-item label="所在省市">
+                    <el-row type="flex" justify="space-between">
+                        <el-col :span="11">
+                            <el-input v-model="form.country"></el-input>
+                        </el-col>
+                        <el-col :span="11">
+                            <el-input v-model="form.city"></el-input>
+                        </el-col>
+                    </el-row>
+                </el-form-item>
+                <el-form-item label="详细地址">
+                    <el-input v-model="form.address"></el-input>
+                </el-form-item>
+                <el-form-item label="联系电话">
+                    <el-row type="flex" :gutter="19">
+                        <el-input v-model="form.tel"></el-input>
+                    </el-row>
+                </el-form-item>
+                <el-form-item>
+                    <el-button style="margin-left:60%" type="primary" @click="onSubmit">更新信息</el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+    </div>
+</template>
+
+<script>
+import { reqFirminfo, reqUpdateFirm } from "@/api/fileInfo.js";
+export default {
+    name: "firmInfo",
+    data() {
+        return {
+            // 保留接口结构
+            reqInfo: {},
+            form: {
+                name: "长兴湖羊",
+                email: "antdesign@alipay.com",
+                decription: "一个养殖平台",
+                province: "中国",
+                country: "浙江省",
+                city: "杭州市",
+                address: "西溪海创园",
+                tel: "0752-88888888"
+            }
+        };
+    },
+    created() {
+        this.getFirminfo();
+    },
+    methods: {
+        // 更新企业信息
+        onSubmit() {
+            let tempArr = [];
+            for (const key in this.form) {
+                tempArr.push({ key, val: this.form[key] });
+            }
+            this.reqInfo.conf = JSON.stringify({
+                data: JSON.stringify(tempArr)
+            });
+            reqUpdateFirm(this.reqInfo)
+                .then(res => {
+                    // this.$message.success("更新企业信息成功!");
+                    if (res.errCode) {
+                        this.$message.error(res.errMsg);
+                    } else {
+                        this.$message.success("成功");
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error("更新企业信息失败!");
+                });
+        },
+        // 获取企业信息
+        getFirminfo() {
+            reqFirminfo()
+                .then(res => {
+                    // 保留接口结构
+                    this.reqInfo = res;
+                    console.log(res);
+                    if (res.conf.data) {
+                        let obj = {};
+                        JSON.parse(res.conf.data).forEach(item => {
+                            obj[item.key] = item.val;
+                        });
+                        this.form = obj;
+                    }
+                })
+                .catch(err => {
+                    console.error(err);
+                });
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.firmInfo {
+    .left {
+        width: 400px;
+        margin-left: 50px;
+    }
+}
+</style>

+ 120 - 0
src/views/fileInfo/pastureInfo.vue

@@ -0,0 +1,120 @@
+<template>
+    <div class="pastureInfo">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">牧场信息</h2>
+        <div class="left">
+            <el-form ref="form" :model="form">
+                <el-form-item label="牧场名称">
+                    <el-input v-model="form.name"></el-input>
+                </el-form-item>
+                <el-form-item label="邮箱">
+                    <el-input v-model="form.email"></el-input>
+                </el-form-item>
+                <el-form-item label="牧场简介">
+                    <el-input type="textarea" v-model="form.description"></el-input>
+                </el-form-item>
+                <el-form-item label="主要负责人及电话">
+                    <el-row type="flex" :gutter="19">
+                        <el-col :span="8">
+                            <el-input v-model="form.manager"></el-input>
+                        </el-col>
+                        <el-col :span="15">
+                            <el-input v-model="form.managerPhone"></el-input>
+                        </el-col>
+                    </el-row>
+                </el-form-item>
+                <el-form-item label="所在省市">
+                    <el-row type="flex" justify="space-between">
+                        <el-col :span="11">
+                            <el-input v-model="form.province"></el-input>
+                        </el-col>
+                        <el-col :span="11">
+                            <el-input v-model="form.city"></el-input>
+                        </el-col>
+                    </el-row>
+                </el-form-item>
+                <el-form-item label="详细地址">
+                    <el-input v-model="form.address"></el-input>
+                </el-form-item>
+
+                <el-form-item>
+                    <el-button style="margin-left:60%" type="primary" @click="onSubmit">更新信息</el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+    </div>
+</template>
+
+<script>
+import { reqPastureInfo, reqUpdatePasture } from "@/api/fileInfo.js";
+export default {
+    data() {
+        return {
+            // 保留接口结构
+            reqInfo: {},
+            form: {
+                name: "西溪海创园",
+                email: "antdesign@alipay.com",
+                description: "一个养殖平台",
+                manager: "沈厂长",
+                managerPhone: "18202780511",
+                province: "浙江省",
+                city: "杭州市",
+                address: "西湖区工专路 77 号"
+            }
+        };
+    },
+    created() {
+        // 获取牧场信息
+        this.getPastureInfo();
+    },
+    methods: {
+        onSubmit() {
+            let tempArr = [];
+            for (const key in this.form) {
+                tempArr.push({ key, val: this.form[key] });
+            }
+            this.reqInfo.conf = JSON.stringify({
+                data: JSON.stringify(tempArr)
+            });
+            reqUpdatePasture(this.reqInfo)
+                .then(res => {
+                    // this.$message.success("更新企业信息成功!");
+                    if (res.errCode) {
+                        this.$message.error(res.errMsg);
+                    } else {
+                        this.$message.success("成功");
+                    }
+                })
+                .catch(err => {
+                    console.error(err);
+                    this.$message.error("更新企业信息失败!");
+                });
+        },
+        // 获取牧场信息
+        getPastureInfo() {
+            reqPastureInfo()
+                .then(res => {
+                    // 保留接口结构
+                    this.reqInfo = res;
+                    let obj = {};
+                    JSON.parse(res.conf.data).forEach(item => {
+                        obj[item.key] = item.val;
+                    });
+                    this.form = obj;
+                })
+                .catch(err => {
+                    console.error(err);
+                });
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.pastureInfo {
+    .left {
+        width: 500px;
+        margin-left: 50px;
+    }
+}
+</style>

+ 231 - 0
src/views/fileInfo/workerInfo.vue

@@ -0,0 +1,231 @@
+<template>
+    <div class="workerInfo">
+        <h2 style="margin-bottom: 20px;padding-bottom:7px;border-bottom:2px solid #ddd">员工信息</h2>
+        <header id="header">
+            <el-row type="flex" :gutter="20">
+                <el-col :span="4">
+                    <el-input v-model="search" placeholder="请选择"></el-input>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="getWorkerList">查找</el-button>
+                </el-col>
+                <el-col :span="4">
+                    <el-button type="primary" @click="add">新增</el-button>
+                </el-col>
+            </el-row>
+        </header>
+        <section>
+            <article class="table">
+                <el-table
+                    :data="tableData"
+                    tooltip-effect="dark"
+                    style="width: 100%"
+                >
+                    <el-table-column prop="id" label="序号" width="80"></el-table-column>
+                    <el-table-column prop="name" label="姓名" width="80"></el-table-column>
+                    <el-table-column prop="gender" label="性别" width="80">
+                        <template v-slot="scope">
+                            <span v-if="scope.row.gender==1">男</span>
+                            <span v-if="scope.row.gender==0">女</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="age" label="年龄" width="100"></el-table-column>
+                    <el-table-column prop="position" label="职位"></el-table-column>
+                    <el-table-column label="当前状态" >
+                        <template v-slot="scope">
+                            <span v-if="scope.row['status']==1">在职</span>
+                            <span v-else>离职</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column prop="phone" label="联系电话"></el-table-column>
+                    <el-table-column prop="birthPlace" label="户籍地"></el-table-column>
+                    <el-table-column prop="farmName" label="所属牧场"></el-table-column>
+                    <el-table-column prop="duty" label="责任区域"></el-table-column>
+                    <el-table-column prop="entryTime" label="入职时间" width="180"></el-table-column>
+                    <el-table-column label="操作" width="150">
+                        <template v-slot="scope">
+                            <el-button @click="edit(scope.row)" type="text" size="small">编辑</el-button>
+                            <el-popconfirm title="是否删除此设备的信息?" @onConfirm="del(scope.row)">
+                                <el-button slot="reference" type="text" size="small">删除</el-button>
+                            </el-popconfirm>
+                        </template>
+                    </el-table-column>
+                </el-table>
+
+                <el-row type="flex" justify="end">
+                    <el-col :span="8" class="pagination">
+                        <el-pagination
+                            @current-change="pageChange"
+                            background
+                            layout="prev, pager, next"
+                            :page-count="Number(totalPages)"
+                        ></el-pagination>
+                    </el-col>
+                </el-row>
+            </article>
+        </section>
+
+        <el-dialog title="新增/编辑" :visible.sync="isShow" width="40%">
+            <el-row type="flex">
+                <el-col :span="20">
+                    <el-form ref="addWorker" :model="formData" :rules="rules" label-width="140px">
+                        <el-form-item label="姓名">
+                            <el-input v-model="formData.name"></el-input>
+                        </el-form-item>
+                        <el-form-item label="性别">
+                            <el-radio-group v-model="formData.gender">
+                                <el-radio :label="1">男</el-radio>
+                                <el-radio :label="0">女</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+                        <el-form-item label="年龄">
+                            <el-input v-model="formData.age"></el-input>
+                        </el-form-item>
+                        <el-form-item label="所属牧场">
+                            <el-input v-model="formData.farmName"></el-input>
+                        </el-form-item>
+                        <el-form-item label="职位">
+                            <el-input v-model="formData.position"></el-input>
+                        </el-form-item>
+                        <el-form-item label="联系电话">
+                            <el-input v-model="formData.phone"></el-input>
+                        </el-form-item>
+                        <el-form-item label="户籍地">
+                            <el-input v-model="formData.birthPlace"></el-input>
+                        </el-form-item>
+                        <el-form-item label="责任区域">
+                            <el-input v-model="formData.duty"></el-input>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button @click="isShow=false">取 消</el-button>
+                            <el-button type="primary" @click="submitForm('addWorker')">保 存</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-col>
+            </el-row>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import {
+    reqWorkerList,
+    reqAddOrUpdateWorker,
+    reqDelWorker
+} from "@/api/fileInfo.js";
+
+const pageSize = 10;
+const rules = {};
+
+export default {
+    name: "workerInfo",
+    data() {
+        return {
+            search: "",
+            pageNum: 1,
+            tableData: [],
+            totalPages: 0,
+            isShow: false,
+            formData: {
+                name: "王炸",
+                gender: 1,
+                age: "22",
+                farmName: "xx牧场",
+                position: "饲养员",
+                phone: "18202780511",
+                birthPlace: "浙江",
+                duty: "保育一舍,保育二舍"
+            },
+            rules
+        };
+    },
+    created() {
+        // 入库管理列表
+        this.getWorkerList();
+    },
+    methods: {
+        submitForm(formName) {
+            this.$refs[formName].validate(valid => {
+                if (valid) {
+                    reqAddOrUpdateWorker(this.formData)
+                        .then(res => {
+                            // 入库管理列表
+                            this.getWorkerList();
+                            // this.$message.success("成功!");
+                            if (res.errCode) {
+                                this.$message.error(res.errMsg);
+                            } else {
+                                this.$message.success("成功");
+                            }
+                            this.isShow = false;
+                        })
+                        .catch(err => {
+                            console.log(err);
+                            this.$message.error("失败!");
+                        });
+                } else {
+                    return false;
+                }
+            });
+        },
+        // 入库管理列表
+        getWorkerList() {
+            reqWorkerList({
+                searchStr: this.search,
+                pageSize,
+                pageNum: this.pageNum
+            })
+                .then(res => {
+                    this.tableData = res.content;
+                    this.totalPages = res.totalPages;
+                })
+                .catch(err => {
+                    console.log(err);
+                });
+        },
+        add() {
+            this.isShow = true;
+            // 有id是update 没id是add
+            delete this.formData.id;
+        },
+        edit(row) {
+            this.formData = row;
+            this.isShow = true;
+        },
+        del(row) {
+            reqDelWorker(row.id)
+                .then(res => {
+                    // 入库管理列表
+                    this.getWorkerList();
+                    if (res.code == "success") {
+                        this.$message.success(res.msg);
+                    }
+                    if (res.errCode == "delete failed") {
+                        this.$message.error(res.errMsg);
+                    }
+                })
+                .catch(err => {
+                    console.log(err);
+                    this.$message.error("删除失败!");
+                });
+        },
+        pageChange(p) {
+            console.log(p);
+            this.pageNum = p;
+            // 入库管理列表
+            this.getWorkerList();
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+#header {
+    margin-bottom: 15px;
+}
+.table {
+    .pagination {
+        margin-top: 20px;
+    }
+}
+</style>

+ 30 - 0
vue.config.js

@@ -0,0 +1,30 @@
+module.exports = {
+  publicPath: './', // 这个值被设置为空字符串 ('') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打出来的包可以被部署在任意路径。
+  configureWebpack: {
+    resolve: {
+      symlinks: true
+    }
+  },
+  pluginOptions: {
+    'style-resources-loader': {
+      preProcessor: 'scss',
+      patterns: [
+        './src/assets/css/reset.scss'
+      ]
+    }
+  },
+  devServer: {
+    disableHostCheck: true
+    // proxy: {
+    //   '^/': {                //这里最好有一个 /
+    //     target: 'http://115.238.57.190:8010',         // 服务器端接口地址
+    //     ws: true,            //如果要代理 websockets,配置这个参数
+    //     // 如果是https接口,需要配置这个参数
+    //     changeOrigin: true,  //是否跨域
+    //     pathRewrite: {
+    //       '^/api': ''
+    //     }
+    //   }
+    // }
+  }
+}

文件差异内容过多而无法显示
+ 11935 - 0
yarn.lock