From 74da5f0d434681ca8e9090e242e7fd29c144ebcb Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期六, 15 二月 2025 16:15:02 +0800
Subject: [PATCH] 工时管理30%

---
 src/api/performance/manHour.js                       |  128 ++
 src/components/Table/lims-table.vue                  |  629 +++++++------
 src/views/standard/standardLibrary/index.vue         |   38 
 src/components/TableCard/index.vue                   |   71 +
 vue.config.js                                        |  149 +-
 src/components/Excel/luckysheet.vue                  |    2 
 src/views/performance/manHour/workTimeManagement.vue | 1143 ++++++++++++++++++++++++
 src/views/standard/model/index.vue                   |   66 
 src/views/performance/manHour/workTimeStatistics.vue |  176 +++
 src/api/standard/model.js                            |    6 
 src/views/performance/manHour/index.vue              |   56 +
 src/layout/components/AppMain.vue                    |   28 
 src/views/performance/class/index.vue                |    0 
 src/views/performance/manHour/workTimeConfig.vue     |  260 +++++
 14 files changed, 2,317 insertions(+), 435 deletions(-)

diff --git a/src/api/performance/manHour.js b/src/api/performance/manHour.js
new file mode 100644
index 0000000..67d27c8
--- /dev/null
+++ b/src/api/performance/manHour.js
@@ -0,0 +1,128 @@
+import request from "@/utils/request";
+
+// 鏌ヨ宸ユ椂姹囨��
+export function selectAuxiliaryAllByMonth(data) {
+  return request({
+    url: "/auxiliaryOriginalHours/selectAuxiliaryAllByMonth",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏌ヨ杈呭姪宸ユ椂
+export function selectAuxiliaryWorkingHoursDay(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/selectAuxiliaryWorkingHoursDay",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏌ヨ浜ч噺宸ユ椂
+export function selectAuxiliaryOutputWorkingHours(data) {
+  return request({
+    url: "/auxiliaryOutputWorkingHours/selectAuxiliaryOutputWorkingHours",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍒犻櫎杈呭姪宸ユ椂
+export function deleteAuxiliaryWorkingHoursDay(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/deleteAuxiliaryWorkingHoursDay",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏂板杈呭姪宸ユ椂
+export function insertAuxiliaryWorkingHoursDay(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/insertAuxiliaryWorkingHoursDay",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼杈呭姪宸ユ椂
+export function updateAuxiliaryWorkingHoursDay(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/updateAuxiliaryWorkingHoursDay",
+    method: "post",
+    data: data,
+  });
+}
+
+// 杈呭姪宸ユ椂--鎵瑰噯
+export function approve(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/approve",
+    method: "post",
+    data: data,
+  });
+}
+
+// 缁熻浜ч噺宸ユ椂姹囨�诲拰杈呭姪宸ユ椂姹囨��
+export function collectWorkingHours(data) {
+  return request({
+    url: "/auxiliaryOutputWorkingHours/collectWorkingHours",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏍规嵁缂栧彿褰撳墠鐢ㄦ埛淇℃伅鏌ヨ鎵�鍦ㄧ彮娆�
+export function selectshiftByUser(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/selectshiftByUser",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏍规嵁缂栧彿鏌ヨ杈呭姪宸ユ椂閰嶇疆淇℃伅
+export function selectAuxiliaryWorkingHoursByNumber(number) {
+  return request({
+    url:
+      "/auxiliaryWorkingHoursDay/selectAuxiliaryWorkingHoursByNumber?number=" +
+      number,
+    method: "post",
+  });
+}
+
+// 杈呭姪宸ユ椂瀵煎嚭
+export function exportAssistantHours(data) {
+  return request({
+    url: "/auxiliaryWorkingHoursDay/exportAssistantHours",
+    method: "post",
+    data: data,
+  });
+}
+
+// 浜ч噺宸ユ椂瀵煎嚭
+export function exportOutputHours(data) {
+  return request({
+    url: "/auxiliaryOutputWorkingHours/exportOutputHours",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏌ヨ杈呭姪宸ユ椂
+export function selectAuxiliaryWorkingHours(data) {
+  return request({
+    url: "/auxiliaryWorkingHours/selectAuxiliaryWorkingHours",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇瀹為獙瀹ゅ悕绉�
+export function obtainItemParameterList(query) {
+  return request({
+    url: "/laboratoryScope/obtainItemParameterList",
+    method: "get",
+    params: query,
+  });
+}
diff --git a/src/api/standard/model.js b/src/api/standard/model.js
index 2c47cc2..52707ad 100644
--- a/src/api/standard/model.js
+++ b/src/api/standard/model.js
@@ -1,11 +1,11 @@
 import request from "@/utils/request";
 
 // 鏌ヨ瀹㈡埛鍒楄〃
-export function selectStandardTemplatePageList(query) {
+export function selectStandardTemplatePageList(data) {
   return request({
     url: "/StandardTemplate/selectStandardTemplatePageList",
-    method: "get",
-    params: query,
+    method: "post",
+    data: data,
   });
 }
 
diff --git a/src/components/Excel/luckysheet.vue b/src/components/Excel/luckysheet.vue
index 0301f5a..4e5cc32 100644
--- a/src/components/Excel/luckysheet.vue
+++ b/src/components/Excel/luckysheet.vue
@@ -63,8 +63,10 @@
   methods: {
     templateWrite() {
       var option = {};
+      console.log(2222, this.data);
       if (this.data != null && this.data != "") {
         option = JSON.parse(this.data);
+        console.log(11111, option);
       } else {
         let rowlen = {};
         let columnlen = {};
diff --git a/src/components/Table/lims-table.vue b/src/components/Table/lims-table.vue
index df1c423..d453b9e 100644
--- a/src/components/Table/lims-table.vue
+++ b/src/components/Table/lims-table.vue
@@ -1,305 +1,368 @@
- <template>
-    <div>
-      <!-- 琛ㄦ牸 -->
-      <el-table
-          ref="multipleTable"
-          v-loading="tableLoading"
-          :border="border"
-          :data="tableData"
-          :header-cell-style="{ background: '#f8f8f9', color: '#515a6e' }"
-          :height="height"
-          :highlight-current-row="highlightCurrentRow"
-          :row-class-name="rowClassName"
-          :row-style="rowStyle"
-          :row-key="rowKey"
-          stripe
-          style="width: 100%; "
-          tooltip-effect="dark"
-          @row-click="rowClick"
-          @current-change="currentChange"
-          @selection-change="handleSelectionChange"
+<template>
+  <div>
+    <!-- 琛ㄦ牸 -->
+    <el-table
+      ref="multipleTable"
+      v-loading="tableLoading"
+      :border="border"
+      :data="tableData"
+      :header-cell-style="{ background: '#f8f8f9', color: '#515a6e' }"
+      :height="height"
+      :highlight-current-row="highlightCurrentRow"
+      :row-class-name="rowClassName"
+      :row-style="rowStyle"
+      :row-key="rowKey"
+      stripe
+      style="width: 100%"
+      tooltip-effect="dark"
+      @row-click="rowClick"
+      @current-change="currentChange"
+      @selection-change="handleSelectionChange"
+    >
+      <template v-if="isSelection">
+        <el-table-column type="selection" width="55" />
+      </template>
+      <template>
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+      </template>
+
+      <template v-for="(item, index) in column">
+        <el-table-column
+          :column-key="item.columnKey"
+          :filter-method="item.filterHandler"
+          :filter-multiple="item.filterMultiple"
+          :filtered-value="item.filteredValue"
+          :filters="item.filters"
+          :fixed="item.fixed"
+          :label="item.label"
+          :min-width="item.minWidth"
+          :prop="item.prop"
+          :show-overflow-tooltip="item.showOverflowTooltip"
+          :sortable="item.sortable ? true : false"
+          :type="item.type"
+          :width="item.width"
+          align="center"
         >
-        <template v-if="isSelection">
-          <el-table-column type="selection" width="55" />
-        </template>
-        <template>
-          <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        </template>
+          <!-- <div class="123" v-if="item.type == ''"> -->
+          <template
+            v-if="item.hasOwnProperty('colunmTemplate')"
+            :slot="item.colunmTemplate"
+            slot-scope="scope"
+          >
+            <slot
+              v-if="item.theadSlot"
+              :index="index"
+              :name="item.theadSlot"
+              :row="scope.row"
+            />
+          </template>
 
-        <template v-for="(item, index) in column">
-          <el-table-column :column-key="item.columnKey" :filter-method="item.filterHandler"
-            :filter-multiple="item.filterMultiple" :filtered-value="item.filteredValue"
-            :filters="item.filters" :fixed="item.fixed" :label="item.label"
-            :min-width="item.minWidth" :prop="item.prop"
-            :show-overflow-tooltip="item.showOverflowTooltip"
-            :sortable="item.sortable ? true : false" :type="item.type" :width="item.width"
-            align="center">
-            <!-- <div class="123" v-if="item.type == ''"> -->
-            <template v-if="item.hasOwnProperty('colunmTemplate')" :slot="item.colunmTemplate"
-                      slot-scope="scope">
-              <slot v-if="item.theadSlot" :index="index" :name="item.theadSlot" :row="scope.row" />
-            </template>
+          <template slot-scope="scope">
+            <!-- 鎻掓Ы -->
+            <div v-if="item.dataType == 'slot'">
+              <slot
+                v-if="item.slot"
+                :index="scope.$index"
+                :name="item.slot"
+                :row="scope.row"
+              />
+            </div>
+            <!-- 杩涘害鏉� -->
+            <div v-else-if="item.dataType == 'progress'">
+              <el-progress :percentage="Number(scope.row[item.prop])" />
+            </div>
 
-            <template slot-scope="scope">
-              <!-- 鎻掓Ы -->
-              <div v-if="item.dataType == 'slot'">
-                <slot v-if="item.slot" :index="scope.$index" :name="item.slot" :row="scope.row" />
-              </div>
-              <!-- 杩涘害鏉� -->
-              <div v-else-if="item.dataType == 'progress'">
-                <el-progress :percentage="Number(scope.row[item.prop])" />
-              </div>
+            <!-- tag -->
+            <div v-else-if="item.dataType == 'tag'">
+              <el-tag
+                v-if="
+                  typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
+                  'string'
+                "
+                :title="scope.row[item.prop] | formatters(item.formatData)"
+                :type="formatType(scope.row[item.prop], item.formatType)"
+                >{{
+                  scope.row[item.prop] | formatters(item.formatData)
+                }}</el-tag
+              >
+              <el-tag
+                v-for="(tag, index) in dataTypeFn(
+                  scope.row[item.prop],
+                  item.formatData
+                )"
+                v-else-if="
+                  typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
+                  'object'
+                "
+                :key="index"
+                :title="scope.row[item.prop] | formatters(item.formatData)"
+                :type="formatType(tag, item.formatType)"
+                >{{
+                  item.tagGroup
+                    ? tag[item.tagGroup.label]
+                      ? tag[item.tagGroup.label]
+                      : tag
+                    : tag
+                }}</el-tag
+              >
+              <el-tag
+                v-else
+                :title="scope.row[item.prop] | formatters(item.formatData)"
+                :type="formatType(scope.row[item.prop], item.formatType)"
+                >{{
+                  scope.row[item.prop] | formatters(item.formatData)
+                }}</el-tag
+              >
+            </div>
 
-              <!-- tag -->
-              <div v-else-if="item.dataType == 'tag'">
-                <el-tag v-if="typeof dataTypeFn(scope.row[item.prop], item.formatData) == 'string'"
-                        :title="scope.row[item.prop] | formatters(item.formatData)"
-                        :type="formatType(scope.row[item.prop], item.formatType)">{{ scope.row[item.prop] | formatters(item.formatData) }}</el-tag>
-                <el-tag v-for="(tag, index) in dataTypeFn(scope.row[item.prop], item.formatData)"
-                        v-else-if="typeof dataTypeFn(scope.row[item.prop], item.formatData) == 'object'"
-                        :key="index" :title="scope.row[item.prop] | formatters(item.formatData)"
-                        :type="formatType(tag, item.formatType)">{{ item.tagGroup ? tag[item.tagGroup.label] ? tag[item.tagGroup.label] : tag : tag }}</el-tag>
-                <el-tag v-else :title="scope.row[item.prop] | formatters(item.formatData)"
-                        :type="formatType(scope.row[item.prop], item.formatType)">{{ scope.row[item.prop] | formatters(item.formatData) }}</el-tag>
-              </div>
-
-              <!-- 鎸夐挳 -->
-              <div v-else-if="item.dataType == 'action'">
-                <template v-for="(o, key) in item.operation">
+            <!-- 鎸夐挳 -->
+            <div v-else-if="item.dataType == 'action'">
+              <template v-for="(o, key) in item.operation">
+                <el-button
+                  v-if="o.type != 'upload'"
+                  v-show="o.showHide ? o.showHide(scope.row) : true"
+                  :disabled="o.disabled ? o.disabled(scope.row) : false"
+                  :icon="o.icon | iconFn(scope.row)"
+                  :plain="o.plain"
+                  :size="o.size"
+                  :style="{ color: o.color }"
+                  :type="o.type | typeFn(scope.row)"
+                  @click="o.clickFun(scope.row)"
+                >
+                  {{ o.name }}
+                </el-button>
+                <el-upload
+                  action="#"
+                  :on-change="
+                    (file, fileList) => o.clickFun(scope.row, file, fileList)
+                  "
+                  :multiple="o.multiple ? o.multiple : false"
+                  :limit="o.limit ? o.limit : 1"
+                  :disabled="o.disabled ? o.disabled(scope.row) : false"
+                  :accept="
+                    o.accept
+                      ? o.accept
+                      : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
+                  "
+                  v-if="o.type == 'upload'"
+                  style="display: inline-block; width: 50px"
+                  v-show="o.showHide ? o.showHide(scope.row) : true"
+                  :auto-upload="false"
+                  :on-exceed="onExceed"
+                  :show-file-list="false"
+                >
                   <el-button
-                      v-if="o.type!='upload'"
-                      v-show="o.showHide ? o.showHide(scope.row) : true"
-                      :disabled="o.disabled ? o.disabled(scope.row) : false"
-                      :icon="o.icon | iconFn(scope.row)"
-                      :plain="o.plain" :size="o.size"
-                      :style="{ 'color': o.color }"
-                      :type="o.type | typeFn(scope.row)"
-                      @click="o.clickFun(scope.row)">
-                    {{ o.name }}
-                  </el-button>
-                  <el-upload
-                    action="#"
-                    :on-change="(file, fileList)=>o.clickFun(scope.row,file, fileList)"
-                    :multiple="o.multiple?o.multiple:false"
-                    :limit="o.limit?o.limit:1"
+                    :size="o.size ? o.size : 'small'"
+                    type="text"
                     :disabled="o.disabled ? o.disabled(scope.row) : false"
-                    :accept="o.accept?o.accept:'.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'"
-                    v-if="o.type=='upload'" style="display: inline-block;width: 50px;"
-                    v-show="o.showHide ? o.showHide(scope.row) : true"
-                    :auto-upload="false"
-                    :on-exceed="onExceed"
-                    :show-file-list="false">
-                    <el-button :size="o.size?o.size:'small'" type="text" :disabled="o.disabled ? o.disabled(scope.row) : false">{{o.name}}</el-button>
-                  </el-upload>
-                </template>
-              </div>
-              <!-- 榛樿绾睍绀烘暟鎹� -->
-              <div v-else>
-                <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
-                <span v-else>{{ scope.row[item.prop] | formatters(item.formatData) }}</span>
-              </div>
-            </template>
-          </el-table-column>
-        </template>
-      </el-table>
-      <pagination
-      v-show="page.total>0"
+                    >{{ o.name }}</el-button
+                  >
+                </el-upload>
+              </template>
+            </div>
+            <!-- 榛樿绾睍绀烘暟鎹� -->
+            <div v-else>
+              <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
+              <span v-else>{{
+                scope.row[item.prop] | formatters(item.formatData)
+              }}</span>
+            </div>
+          </template>
+        </el-table-column>
+      </template>
+    </el-table>
+    <pagination
+      v-show="page.total > 0"
       :total="page.total"
       :page.sync="page.current"
       :limit.sync="page.size"
       @pagination="pagination"
     />
-    </div>
-  </template>
+  </div>
+</template>
 
-  <script>
-  // 娉細浠ヤ笅鏄墍鏈夐厤缃」锛屽叾涓渶甯镐娇鐢ㄧ殑灏辨槸label銆亀idth銆乸rop銆乨ataType銆乻lot
-  // label 锛氬垪鍚嶏紝灏辨槸琛ㄥご涓婄殑鏍囩鍙粈涔堜簺浠�涔堬紝绫诲瀷 string
-  // width锛氳鍒楀搴︼紝 string
-  // prop锛�  table缁戝畾鏁版嵁瀛楁 string,杩欎竴鍒楄灞曠ず鍝釜tableData閲岄潰鐨勫瓧娈靛氨鍐欏摢涓瓧娈�
-  // dataType锛�  鍐呯疆澶氫釜鍩烘湰鐨別lement缁勪欢鍙緵鐩存帴浣跨敤 string
-  // slot  褰揱dataType`涓篳slot`鏃跺繀甯﹀弬鏁帮紝鍙傛暟鍊间负鎻掓Ы鐨� `slot` 鍊� string锛屽叿浣撲娇鐢ㄦ柟娉曡鐪嬩笅闈㈢殑绗�4鐐箂lot鎻掓Ы鐨勪娇鐢�
-  // fixed锛氬垪鏄惁鍥哄畾鍦ㄥ乏渚ф垨鑰呭彸渚э紝true 琛ㄧず鍥哄畾鍦ㄥ乏渚� string, boolean
-  // sortable 瀵瑰簲鍒楁槸鍚﹀彲浠ユ帓搴� boolean, string
-  // filters 鏁版嵁杩囨护鐨勯�夐」锛屾暟缁勬牸寮忥紝鏁扮粍涓殑鍏冪礌闇�瑕佹湁 text 鍜� value 灞炴�с�侫rray
-  // columnKey 锛歝olumn 鐨� key锛屽鏋滈渶瑕佷娇鐢� filter-change 浜嬩欢锛屽垯闇�瑕佹灞炴�ф爣璇嗘槸鍝釜 column 鐨勭瓫閫夋潯浠�
-  // filteredValue  閫変腑鐨勬暟鎹繃婊ら」锛屽鏋滈渶瑕佽嚜瀹氫箟琛ㄥご杩囨护鐨勬覆鏌撴柟寮忥紝鍙兘浼氶渶瑕佹灞炴�с��
-  // filterMultiple  鏁版嵁杩囨护鐨勯�夐」鏄惁澶氶��
-  // minWidth 瀵瑰簲鍒楃殑鏈�灏忓搴︼紝涓� width 鐨勫尯鍒槸 width 鏄浐瀹氱殑锛宮in-width 浼氭妸鍓╀綑瀹藉害鎸夋瘮渚嬪垎閰嶇粰璁剧疆浜� min-width 鐨勫垪 string
-  // formatData  瀵规暟鎹繘琛屾暟鎹鐞嗭紝鎺ュ彈涓�涓洖璋冨嚱鏁� (params?: {prop}) => {}
-  // formatType  褰� `dataType`涓� `tag`鏃讹紝瀵规爣绛鹃鑹茶缃� (params?: {prop}) => { return 'danger'| 'success'... }`
-  // operation 褰� `dataType` 涓� `option`鏃讹紝瀵规寜閽殑 閰嶇疆锛屽叿浣撻厤缃」浠ヤ笅鍥句负鍑唎bject
-  // tagGroup 褰� `dataType`涓� `tag`鏃讹紝缁戝畾鏁版嵁闆嗗瓧娈垫樉绀哄悕绉� object
-  /**
-   * 鎻掓Ы鐨勪娇鐢ㄦ柟娉�:
-   */
-  /* <div
+<script>
+// 娉細浠ヤ笅鏄墍鏈夐厤缃」锛屽叾涓渶甯镐娇鐢ㄧ殑灏辨槸label銆亀idth銆乸rop銆乨ataType銆乻lot
+// label 锛氬垪鍚嶏紝灏辨槸琛ㄥご涓婄殑鏍囩鍙粈涔堜簺浠�涔堬紝绫诲瀷 string
+// width锛氳鍒楀搴︼紝 string
+// prop锛�  table缁戝畾鏁版嵁瀛楁 string,杩欎竴鍒楄灞曠ず鍝釜tableData閲岄潰鐨勫瓧娈靛氨鍐欏摢涓瓧娈�
+// dataType锛�  鍐呯疆澶氫釜鍩烘湰鐨別lement缁勪欢鍙緵鐩存帴浣跨敤 string
+// slot  褰揱dataType`涓篳slot`鏃跺繀甯﹀弬鏁帮紝鍙傛暟鍊间负鎻掓Ы鐨� `slot` 鍊� string锛屽叿浣撲娇鐢ㄦ柟娉曡鐪嬩笅闈㈢殑绗�4鐐箂lot鎻掓Ы鐨勪娇鐢�
+// fixed锛氬垪鏄惁鍥哄畾鍦ㄥ乏渚ф垨鑰呭彸渚э紝true 琛ㄧず鍥哄畾鍦ㄥ乏渚� string, boolean
+// sortable 瀵瑰簲鍒楁槸鍚﹀彲浠ユ帓搴� boolean, string
+// filters 鏁版嵁杩囨护鐨勯�夐」锛屾暟缁勬牸寮忥紝鏁扮粍涓殑鍏冪礌闇�瑕佹湁 text 鍜� value 灞炴�с�侫rray
+// columnKey 锛歝olumn 鐨� key锛屽鏋滈渶瑕佷娇鐢� filter-change 浜嬩欢锛屽垯闇�瑕佹灞炴�ф爣璇嗘槸鍝釜 column 鐨勭瓫閫夋潯浠�
+// filteredValue  閫変腑鐨勬暟鎹繃婊ら」锛屽鏋滈渶瑕佽嚜瀹氫箟琛ㄥご杩囨护鐨勬覆鏌撴柟寮忥紝鍙兘浼氶渶瑕佹灞炴�с��
+// filterMultiple  鏁版嵁杩囨护鐨勯�夐」鏄惁澶氶��
+// minWidth 瀵瑰簲鍒楃殑鏈�灏忓搴︼紝涓� width 鐨勫尯鍒槸 width 鏄浐瀹氱殑锛宮in-width 浼氭妸鍓╀綑瀹藉害鎸夋瘮渚嬪垎閰嶇粰璁剧疆浜� min-width 鐨勫垪 string
+// formatData  瀵规暟鎹繘琛屾暟鎹鐞嗭紝鎺ュ彈涓�涓洖璋冨嚱鏁� (params?: {prop}) => {}
+// formatType  褰� `dataType`涓� `tag`鏃讹紝瀵规爣绛鹃鑹茶缃� (params?: {prop}) => { return 'danger'| 'success'... }`
+// operation 褰� `dataType` 涓� `option`鏃讹紝瀵规寜閽殑 閰嶇疆锛屽叿浣撻厤缃」浠ヤ笅鍥句负鍑唎bject
+// tagGroup 褰� `dataType`涓� `tag`鏃讹紝缁戝畾鏁版嵁闆嗗瓧娈垫樉绀哄悕绉� object
+/**
+ * 鎻掓Ы鐨勪娇鐢ㄦ柟娉�:
+ */
+/* <div
        slot="protocolSlot"
        slot-scope="scope"
       >
           <span>{{ scope.row.protocol }}</span>
       </div>
   */
-  /**
-   * 浣跨敤formatData杩涜鏁版嵁澶勭悊
-   */
-  //  {
-  //           type: '',
-  //           label: '鍚敤鐘舵��',
-  //           prop: 'is_active',
-  //           formatData: (item) => {
-  //             const str = item == true ? '宸插惎鐢�' : '鏈惎鐢�'
-  //             return str
-  //           }
-  //         },
-  /**
-   * operation閰嶇疆
-   */
-  //  operation閰嶇疆涓昏鏄潵鐢ㄤ簬琛ㄦ牸閲岄潰鐨勬搷浣滈偅涓�鍒楋紝閫氬父灏变細鏈夊緢澶氭寜閽紝鏈変互涓嬪弬鏁帮細
-  // name锛氭寜閽悕绉帮紝string
-  // type锛氭寜閽被鍨嬶紝`string` | `danger | success`锛屼互elementUi 鍙傛暟涓哄噯
-  // size锛氭寜閽ぇ灏忥紝浠lementUi 鍙傛暟涓哄噯
-  // icon锛氭寜閽笂鐨刬con锛屼互elementUi 鍙傛暟涓哄噯
-  // plain锛氭寜elementUi 鏂囨。涓哄噯
-  // clickFun锛氭寜閽殑鍥炶皟鍑芥暟
-  export default {
-    name: 'ZTTable',
-    filters: {
-      iconFn(val, row) {
-        if (typeof (val) === 'function') {
-          return val(row);
-        } else return val;
-      },
-      typeFn(val, row) {
-        // console.log(val, row, '11111111');
-        if (typeof (val) === 'function') {
-          return val(row);
-        } else return val;
-      },
-      describeConts(val, describeCont) {
-        if (typeof (describeCont) === 'function') {
-          return describeCont(val);
-        } else return val;
-      },
-      formatters(val, format) {
-        if (typeof (format) === 'function') {
-          return format(val);
-        } else return val;
-      }
+/**
+ * 浣跨敤formatData杩涜鏁版嵁澶勭悊
+ */
+//  {
+//           type: '',
+//           label: '鍚敤鐘舵��',
+//           prop: 'is_active',
+//           formatData: (item) => {
+//             const str = item == true ? '宸插惎鐢�' : '鏈惎鐢�'
+//             return str
+//           }
+//         },
+/**
+ * operation閰嶇疆
+ */
+//  operation閰嶇疆涓昏鏄潵鐢ㄤ簬琛ㄦ牸閲岄潰鐨勬搷浣滈偅涓�鍒楋紝閫氬父灏变細鏈夊緢澶氭寜閽紝鏈変互涓嬪弬鏁帮細
+// name锛氭寜閽悕绉帮紝string
+// type锛氭寜閽被鍨嬶紝`string` | `danger | success`锛屼互elementUi 鍙傛暟涓哄噯
+// size锛氭寜閽ぇ灏忥紝浠lementUi 鍙傛暟涓哄噯
+// icon锛氭寜閽笂鐨刬con锛屼互elementUi 鍙傛暟涓哄噯
+// plain锛氭寜elementUi 鏂囨。涓哄噯
+// clickFun锛氭寜閽殑鍥炶皟鍑芥暟
+export default {
+  name: "ZTTable",
+  filters: {
+    iconFn(val, row) {
+      if (typeof val === "function") {
+        return val(row);
+      } else return val;
     },
-    props: {
-      isSelection: {
-        type: Boolean,
-        default: false
-      },
-      height: {
-        type: String,
-        default: null
-      },
-      tableLoading: {
-        type: Boolean,
-        default: false
-      },
-      handleSelectionChange: {
-        type: Function,
-        default: () => {
-          return () => {
-          };
-        }
-      },
-      rowClick: {
-        type: Function,
-        default: () => {
-          return () => {
-          };
-        }
-      },
-      currentChange: {
-        type: Function,
-        default: () => {
-          return () => {
-          };
-        }
-      },
-      border: {
-        type: Boolean,
-        default: false
-      },
-      highlightCurrentRow: {
-        type: Boolean,
-        default: false
-      },
-      headerCellStyle: {
-        type: Object,
-        default: () => {
-          return {};
-        }
-      },
-      column: {
-        type: Array,
-        default() {
-          return [];
-        }
-      },
-      rowClassName: {
-        type: Function,
-        default: () => {
-
-        }
-      },
-      rowStyle: {
-        type: Object || Function,
-        default: () => {
-        }
-      },
-      tableData: {
-        type: Array,
-        default() {
-          return [];
-        }
-      },
-      rowKey: {
-        type: String,
-        default: undefined
-      },
-      page:{
-        type:Object,
-        default() {
-          return {
-            total:0,
-            current:0,
-            size:10
-          };
-        }
-      }
+    typeFn(val, row) {
+      // console.log(val, row, '11111111');
+      if (typeof val === "function") {
+        return val(row);
+      } else return val;
     },
+    describeConts(val, describeCont) {
+      if (typeof describeCont === "function") {
+        return describeCont(val);
+      } else return val;
+    },
+    formatters(val, format) {
+      if (typeof format === "function") {
+        return format(val);
+      } else return val;
+    },
+  },
+  props: {
+    isSelection: {
+      type: Boolean,
+      default: false,
+    },
+    height: {
+      type: String,
+      default: null,
+    },
+    tableLoading: {
+      type: Boolean,
+      default: false,
+    },
+    handleSelectionChange: {
+      type: Function,
+      default: () => {
+        return () => {};
+      },
+    },
+    rowClick: {
+      type: Function,
+      default: () => {
+        return () => {};
+      },
+    },
+    currentChange: {
+      type: Function,
+      default: () => {
+        return () => {};
+      },
+    },
+    border: {
+      type: Boolean,
+      default: false,
+    },
+    highlightCurrentRow: {
+      type: Boolean,
+      default: false,
+    },
+    headerCellStyle: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+    column: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    rowClassName: {
+      type: Function,
+      default: () => {},
+    },
+    rowStyle: {
+      type: Object || Function,
+      default: () => {},
+    },
+    tableData: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    rowKey: {
+      type: String,
+      default: undefined,
+    },
+    page: {
+      type: Object,
+      default() {
+        return {
+          total: 0,
+          current: 0,
+          size: 10,
+        };
+      },
+    },
+  },
 
-    methods: {
-      formatType(val, format) {
-        if (typeof (format) === 'function') {
-          return format(val);
-        } else return '';
-      },
-      dataTypeFn(val, format) {
-        if (typeof (format) === 'function') {
-          return format(val);
-        } else return val;
-      },
-      setCurrent(row) {
-        this.$refs.multipleTable.setCurrentRow();
-      },
-      onExceed(){
-        this.$message.warning('瓒呭嚭鏂囦欢涓暟');
-      },
-      pagination(page,limit){
-        this.$emit('pagination',{pageNum: page, pageSize: limit});
-      }
-    }
-  };
-  </script>
+  methods: {
+    formatType(val, format) {
+      if (typeof format === "function") {
+        return format(val);
+      } else return "";
+    },
+    dataTypeFn(val, format) {
+      if (typeof format === "function") {
+        return format(val);
+      } else return val;
+    },
+    setCurrent(row) {
+      this.$refs.multipleTable.setCurrentRow();
+    },
+    onExceed() {
+      this.$message.warning("瓒呭嚭鏂囦欢涓暟");
+    },
+    pagination(page, limit) {
+      this.$emit("pagination", { pageNum: page, pageSize: limit });
+    },
+  },
+};
+</script>
 
-  <style scoped>
-  .el-table >>> .el-table__empty-text {
-    text-align: center
-  }
-  </style>
+<style scoped>
+.el-table >>> .el-table__empty-text {
+  text-align: center;
+}
+</style>
diff --git a/src/components/TableCard/index.vue b/src/components/TableCard/index.vue
new file mode 100644
index 0000000..67f98a5
--- /dev/null
+++ b/src/components/TableCard/index.vue
@@ -0,0 +1,71 @@
+<template>
+  <div class="table_card">
+    <div v-if="showTitle" class="title">
+      <span style="font-weight: bold">{{ title }}</span>
+    </div>
+    <div>
+      <slot name="tab"></slot>
+    </div>
+    <div v-if="showForm" class="table_card_form">
+      <slot name="form"></slot>
+    </div>
+    <div>
+      <slot name="table"></slot>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    title: {
+      type: String,
+      default: '鏍囬'
+    },
+    showTitle: {
+      type: Boolean,
+      default: true
+    },
+    showForm: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {};
+  }
+};
+</script>
+<style scoped>
+.table_card {
+  text-align: left;
+}
+
+.title {
+  position: relative;
+  font-size: 18px;
+  color: #333;
+  font-weight: 400;
+  padding-left: 10px;
+  margin-left: 15px;
+}
+
+.title::before {
+  position: absolute;
+  left: 0;
+  top: 4px;
+  content: '';
+  width: 4px;
+  height: 18px;
+  background-color: #3A7BFA;
+  border-radius: 2px;
+}
+
+.table_card_form {
+  display: flex;
+  justify-content: space-between;
+  height: 34px;
+  padding: 0 15px;
+  margin-bottom: 10px;
+}
+
+</style>
diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
index d39aaa6..1eb770d 100644
--- a/src/layout/components/AppMain.vue
+++ b/src/layout/components/AppMain.vue
@@ -10,36 +10,36 @@
 </template>
 
 <script>
-import iframeToggle from "./IframeToggle/index"
+import iframeToggle from "./IframeToggle/index";
 
 export default {
-  name: 'AppMain',
+  name: "AppMain",
   components: { iframeToggle },
   computed: {
     cachedViews() {
-      return this.$store.state.tagsView.cachedViews
+      return this.$store.state.tagsView.cachedViews;
     },
     key() {
-      return this.$route.path
-    }
+      return this.$route.path;
+    },
   },
   watch: {
     $route() {
-      this.addIframe()
-    }
+      this.addIframe();
+    },
   },
   mounted() {
-    this.addIframe()
+    this.addIframe();
   },
   methods: {
     addIframe() {
-      const {name} = this.$route
+      const { name } = this.$route;
       if (name && this.$route.meta.link) {
-        this.$store.dispatch('tagsView/addIframeView', this.$route)
+        this.$store.dispatch("tagsView/addIframeView", this.$route);
       }
-    }
-  }
-}
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
@@ -59,7 +59,7 @@
 .hasTagsView {
   .app-main {
     /* 84 = navbar + tags-view = 50 + 34 */
-    min-height: calc(100vh - 84px);
+    min-height: calc(100vh - 94px);
   }
 
   .fixed-header + .app-main {
diff --git a/src/views/performance/class/index.vue b/src/views/performance/class/index.vue
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/views/performance/class/index.vue
diff --git a/src/views/performance/manHour/index.vue b/src/views/performance/manHour/index.vue
new file mode 100644
index 0000000..9955ba5
--- /dev/null
+++ b/src/views/performance/manHour/index.vue
@@ -0,0 +1,56 @@
+<template>
+  <div class="work-time-management">
+    <div style="text-align: left">
+      <el-radio-group
+        v-model="currentComponent"
+        size="small"
+        style="margin-top: 16px; margin-left: 16px"
+      >
+        <el-radio-button
+          v-if="checkPermi(['performance:manHour:workTimeStatistics'])"
+          label="workTimeStatistics"
+        >
+          宸ユ椂姹囨��
+        </el-radio-button>
+        <el-radio-button
+          v-if="checkPermi(['performance:manHour:workTimeManagement'])"
+          label="workTimeManagement"
+        >
+          鏃ュ伐鏃剁鐞�
+        </el-radio-button>
+        <el-radio-button
+          v-if="checkPermi(['performance:manHour:workTimeConfig'])"
+          label="workTimeConfig"
+        >
+          杈呭姪宸ユ椂閰嶇疆
+        </el-radio-button>
+      </el-radio-group>
+    </div>
+    <component :is="currentComponent"></component>
+  </div>
+</template>
+
+<script>
+import workTimeStatistics from "./workTimeStatistics.vue";
+import workTimeManagement from "./workTimeManagement.vue";
+import workTimeConfig from "./workTimeConfig.vue";
+import { checkPermi } from "@/utils/permission"; // 鏉冮檺鍒ゆ柇鍑芥暟
+export default {
+  components: {
+    workTimeStatistics,
+    workTimeManagement,
+    workTimeConfig,
+  },
+  created() {},
+  data() {
+    return {
+      currentComponent: "workTimeStatistics",
+    };
+  },
+  methods: {
+    checkPermi,
+  },
+};
+</script>
+
+<style scoped></style>
diff --git a/src/views/performance/manHour/workTimeConfig.vue b/src/views/performance/manHour/workTimeConfig.vue
new file mode 100644
index 0000000..590c182
--- /dev/null
+++ b/src/views/performance/manHour/workTimeConfig.vue
@@ -0,0 +1,260 @@
+<template>
+  <div class="work-time-config">
+    <div class="search">
+      <div class="search_thing">
+        <div class="search_label">缂栧彿锛�</div>
+        <div class="search_input">
+          <el-input
+            size="small"
+            placeholder="璇疯緭鍏�"
+            clearable
+            v-model="queryParams.number"
+            @keyup.enter.native="refreshTable()"
+          ></el-input>
+        </div>
+      </div>
+      <div class="search_thing">
+        <div class="search_label">瀹為獙瀹わ細</div>
+        <el-select
+          v-model="queryParams.laboratory"
+          placeholder="鍏ㄩ儴"
+          size="small"
+          @change="refreshTable()"
+          clearable
+        >
+          <el-option
+            v-for="item in laboratoryList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search_thing">
+        <div class="search_label">閮ㄩ棬锛�</div>
+        <div class="search_input">
+          <el-input
+            size="small"
+            placeholder="璇疯緭鍏�"
+            clearable
+            v-model="queryParams.department"
+            @keyup.enter.native="refreshTable()"
+          ></el-input>
+        </div>
+      </div>
+      <div class="search_thing" style="padding-left: 30px">
+        <el-button size="small" @click="refresh()">閲� 缃�</el-button>
+        <el-button size="small" type="primary" @click="refreshTable()"
+          >鏌� 璇�</el-button
+        >
+      </div>
+      <el-button
+        size="small"
+        type="primary"
+        style="position: absolute; right: 50px"
+        @click="openAdd"
+        >鏂� 澧�</el-button
+      >
+    </div>
+    <div class="table">
+      <lims-table
+        :tableData="tableData"
+        :column="column"
+        :page="page"
+        :tableLoading="tableLoading"
+        :height="'calc(100vh - 150px)'"
+        @pagination="pagination"
+      ></lims-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import ValueTable from "@/components/Table/value-table.vue";
+import limsTable from "@/components/Table/lims-table.vue";
+import { checkPermi } from "@/utils/permission"; // 鏉冮檺鍒ゆ柇鍑芥暟
+import {
+  selectAuxiliaryWorkingHours,
+  insertAuxiliaryWorkingHoursDay,
+  obtainItemParameterList,
+} from "@/api/performance/manHour";
+export default {
+  components: {
+    ValueTable,
+    limsTable,
+  },
+  data() {
+    return {
+      laboratoryList: [],
+      partList: [],
+      addPower: true,
+      queryParams: {},
+      tableData: [],
+      column: [
+        { label: "缂栧彿", prop: "number" },
+        { label: "杈呭姪椤圭洰鍚嶇О", prop: "auxiliaryProject", width: "120px" },
+        { label: "瀹為獙瀹�", prop: "laboratory" },
+        { label: "鍗曚綅", prop: "unit" },
+        { label: "鏍稿噯宸ユ椂", prop: "approvedWorkingHour" },
+        { label: "閮ㄩ棬", prop: "department" },
+        { label: "澶囨敞", prop: "remarks" },
+        {
+          dataType: "action",
+          fixed: "right",
+          label: "鎿嶄綔",
+          width: "160px",
+          operation: [
+            {
+              name: "缂栬緫",
+              type: "text",
+              clickFun: (row) => {
+                this.handleEdit(row);
+              },
+              showHide: (row) => {
+                return this.checkPermi(["standard:model:edit"]);
+              },
+            },
+            {
+              name: "鍒犻櫎",
+              type: "text",
+              clickFun: (row) => {
+                this.handleDelete(row);
+              },
+              showHide: (row) => {
+                return this.checkPermi(["standard:model:del"]);
+              },
+            },
+          ],
+        },
+      ],
+      page: {
+        total: 0,
+        size: 10,
+        current: 0,
+      },
+      tableLoading: false,
+      unitList: [],
+    };
+  },
+  mounted() {
+    this.entityCopy = this.HaveJson(this.componentData.entity);
+    this.getPower();
+    this.obtainItemParameterList();
+    this.selectEnumByCategoryForUnit();
+  },
+  methods: {
+    checkPermi,
+    getList() {
+      this.tableLoading = true;
+      let param = { ...this.queryParams, ...this.page };
+      delete param.total;
+      selectAuxiliaryWorkingHours({ ...param })
+        .then((res) => {
+          this.tableLoading = false;
+          if (res.code === 200) {
+            this.tableData = res.data.records;
+            this.page.total = res.data.total;
+          }
+        })
+        .catch((err) => {
+          this.tableLoading = false;
+        });
+    },
+    pagination(current, size) {
+      this.page.current = current;
+      this.getList();
+    },
+    refresh() {
+      this.queryParams = {};
+      this.page.current = 1;
+      this.getList();
+    },
+    refreshTable() {
+      this.page.current = 1;
+      this.getList();
+    },
+    getPower(radio) {
+      let power = JSON.parse(sessionStorage.getItem("power"));
+      let up = false;
+      let del = false;
+      let add = false;
+      for (var i = 0; i < power.length; i++) {
+        if (power[i].menuMethod == "upDeviceParameter") {
+          up = true;
+        }
+        if (power[i].menuMethod == "delDeviceParameter") {
+          del = true;
+        }
+        if (power[i].menuMethod == "addDeviceParameter") {
+          add = true;
+        }
+      }
+      if (!up) {
+        this.componentData.do.splice(1, 1);
+      }
+      if (!del) {
+        this.componentData.do.splice(0, 1);
+      }
+      this.addPower = add;
+    },
+    openAdd() {
+      // this.$refs.ValueTable0.openAddDia(
+      //   this.$api.auxiliaryWorkingHours.insertAuxiliaryWorkingHours
+      // );
+    },
+    obtainItemParameterList() {
+      obtainItemParameterList().then((res) => {
+        let data = [];
+        res.data.forEach((a) => {
+          data.push({
+            label: a.laboratoryName,
+            value: a.id,
+          });
+        });
+        this.laboratoryList = data;
+      });
+    },
+    selectEnumByCategoryForUnit() {
+      this.getDicts("sys_unit").then((response) => {
+        this.unitList = response.data;
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.work-time-config {
+  height: 100%;
+}
+.search {
+  background-color: #fff;
+  height: 80px;
+  display: flex;
+  align-items: center;
+}
+
+.search_thing {
+  width: 250px;
+  display: flex;
+  align-items: center;
+}
+
+.search_label {
+  width: 70px;
+  font-size: 14px;
+  text-align: right;
+}
+
+.search_input {
+  width: calc(100% - 70px);
+}
+.table {
+  margin-top: 10px;
+  background-color: #fff;
+  width: calc(100% - 40px);
+  height: calc(100% - 60px - 80px - 10px - 24px);
+  padding: 20px;
+}
+</style>
diff --git a/src/views/performance/manHour/workTimeManagement.vue b/src/views/performance/manHour/workTimeManagement.vue
new file mode 100644
index 0000000..4bbe90d
--- /dev/null
+++ b/src/views/performance/manHour/workTimeManagement.vue
@@ -0,0 +1,1143 @@
+<template>
+  <!--鏃ュ伐鏃剁鐞�-->
+  <div class="work-time-management">
+    <div class="search">
+      <div class="search_thing" style="width: 200px">
+        <div class="search_label">鏄熸湡锛�</div>
+        <el-select
+          v-model="entity.weekDay"
+          clearable
+          placeholder="鍏ㄩ儴"
+          size="small"
+          @change="refreshTable()"
+        >
+          <el-option
+            v-for="item in weekList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search_thing" style="width: 390px">
+        <div class="search_label" style="width: 90px">鏃堕棿鑼冨洿锛�</div>
+        <div class="search_input">
+          <el-date-picker
+            v-model="entity.dateTime"
+            clearable
+            end-placeholder="缁撴潫鏃ユ湡"
+            format="yyyy-MM-dd"
+            range-separator="鑷�"
+            size="small"
+            start-placeholder="寮�濮嬫棩鏈�"
+            style="width: 100%"
+            type="daterange"
+            value-format="yyyy-MM-dd"
+            @change="refreshTable()"
+          >
+          </el-date-picker>
+        </div>
+      </div>
+      <!-- 浠ヤ笅杩欎袱涓负缁勯暱瑙掕壊鐗规湁鐨� -->
+      <div class="search_thing" style="width: 200px">
+        <div class="search_label">鍚嶅瓧锛�</div>
+        <el-input
+          v-model="entity.name"
+          clearable
+          placeholder="璇疯緭鍏�"
+          size="small"
+          @keyup.enter.native="refreshTable()"
+        ></el-input>
+      </div>
+      <div
+        v-if="currentTable == 'ValueTable1'"
+        class="search_thing"
+        style="width: 250px"
+      >
+        <div class="search_label" style="width: 120px">鏍峰搧缂栧彿锛�</div>
+        <el-input
+          v-model="entity.sample"
+          clearable
+          placeholder="璇疯緭鍏�"
+          size="small"
+          @keyup.enter.native="refreshTable()"
+        ></el-input>
+      </div>
+      <div
+        v-if="currentTable == 'ValueTable0'"
+        class="search_thing"
+        style="width: 200px"
+      >
+        <div class="search_label">鐘舵�侊細</div>
+        <el-select
+          v-model="entity.state"
+          placeholder="鍏ㄩ儴"
+          size="small"
+          @change="refreshTable()"
+        >
+          <el-option
+            v-for="item in stateList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </div>
+      <div class="search_thing" style="padding-left: 30px; width: 100px">
+        <el-button size="small" @click="refresh()">閲� 缃�</el-button>
+        <el-button size="small" type="primary" @click="refreshTable()"
+          >鏌� 璇�</el-button
+        >
+      </div>
+    </div>
+    <div
+      style="display: flex; align-items: center; justify-content: space-between"
+    >
+      <el-radio-group :key="'111'" v-model="currentTable" size="small">
+        <el-radio-button label="ValueTable0"> 杈呭姪宸ユ椂 </el-radio-button>
+        <el-radio-button label="ValueTable1"> 浜ч噺宸ユ椂 </el-radio-button>
+      </el-radio-group>
+      <div style="display: flex; align-items: center">
+        <p style="font-size: 14px; margin-right: 30px">
+          鎬诲伐鏃舵眹鎬伙細<span
+            v-if="totalInfo"
+            style="font-size: 16px; color: #3a7bfa"
+            >{{
+              totalInfo["浜ч噺宸ユ椂姹囨��"] + totalInfo["杈呭姪宸ユ椂姹囨��"]
+                ? Number(
+                    totalInfo["浜ч噺宸ユ椂姹囨��"] + totalInfo["杈呭姪宸ユ椂姹囨��"]
+                  ).tofixed(4)
+                : 0
+            }}</span
+          >&nbsp;&nbsp;&nbsp;&nbsp;浜ч噺宸ユ椂姹囨�伙細<span
+            v-if="totalInfo"
+            style="font-size: 16px; color: #3a7bfa"
+            >{{
+              totalInfo["浜ч噺宸ユ椂姹囨��"]
+                ? Number(totalInfo["浜ч噺宸ユ椂姹囨��"]).tofixed(4)
+                : 0
+            }}</span
+          >&nbsp;&nbsp;&nbsp;&nbsp;杈呭姪宸ユ椂姹囨�伙細<span
+            v-if="totalInfo"
+            style="font-size: 16px; color: #3a7bfa"
+            >{{
+              totalInfo["杈呭姪宸ユ椂姹囨��"]
+                ? Number(totalInfo["杈呭姪宸ユ椂姹囨��"]).tofixed(4)
+                : 0
+            }}</span
+          >
+        </p>
+        <el-button
+          v-show="
+            currentTable == 'ValueTable0' &&
+            checkPermi(['performance:manHour:workTimeManagement:add'])
+          "
+          size="small"
+          type="primary"
+          @click="openAdd"
+          >褰曞叆鏁版嵁</el-button
+        >
+        <el-button
+          v-if="down && currentTable === 'ValueTable0'"
+          :loading="outLoading"
+          size="small"
+          type="primary"
+          @click="handleOut"
+          >瀵� 鍑�</el-button
+        >
+        <el-button
+          v-if="down && currentTable === 'ValueTable1'"
+          :loading="outLoading"
+          size="small"
+          type="primary"
+          @click="handleOut1"
+          >瀵� 鍑�</el-button
+        >
+        <el-button
+          v-show="
+            currentTable == 'ValueTable0' &&
+            checkPermi(['performance:manHour:workTimeManagement:add'])
+          "
+          size="small"
+          type="primary"
+          @click="openBatchCheck(1)"
+          >鎵归噺鎵瑰噯</el-button
+        >
+      </div>
+    </div>
+    <div class="table">
+      <lims-table
+        :tableData="tableData"
+        :column="column"
+        :page="page"
+        :tableLoading="tableLoading"
+        :height="'calc(100vh - 320px)'"
+        v-if="currentTable == 'ValueTable0'"
+        @pagination="pagination"
+      ></lims-table>
+      <lims-table
+        :tableData="tableData0"
+        :column="column0"
+        :page="page0"
+        :tableLoading="tableLoading"
+        :height="'calc(100vh - 320px)'"
+        v-if="currentTable == 'ValueTable1'"
+        @pagination="pagination0"
+      ></lims-table>
+    </div>
+    <el-dialog
+      :before-close="handleClose"
+      :title="formData.id ? '缂栬緫' : '褰曞叆鏁版嵁'"
+      :visible.sync="addVisible"
+      width="600px"
+    >
+      <el-row style="display: flex; justify-content: space-around">
+        <el-col :span="12">
+          <el-form :model="formData" label-width="90px">
+            <el-form-item label="褰曞叆鏃堕棿:">
+              <el-radio-group v-model="formData.dateTime" size="small">
+                <el-radio :label="getYearAndMonthAndDays() + ' 00:00:00'"
+                  >浠婂ぉ</el-radio
+                >
+                <el-radio
+                  :label="
+                    getYearAndMonthAndDays(
+                      new Date(new Date().getTime() - 24 * 60 * 60 * 1000)
+                    ) + ' 00:00:00'
+                  "
+                  >鏄ㄥぉ</el-radio
+                >
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="骞翠唤:">
+              <el-input
+                v-model="formData.year"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鍛ㄦ:">
+              <el-input
+                v-model="formData.week"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鏄熸湡:">
+              <!-- <el-input v-model="formData.weekDay" size="small" disabled></el-input> -->
+              <el-select
+                v-model="formData.weekDay"
+                disabled
+                placeholder="璇烽�夋嫨"
+                size="small"
+              >
+                <el-option
+                  v-for="item in weekList"
+                  :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.shift"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :span="12">
+          <el-form :model="formData" label-width="90px">
+            <el-form-item label="缂栧彿:" required>
+              <el-input
+                v-model="formData.number"
+                size="small"
+                @blur="getInfoByCode"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鏁伴噺:" required>
+              <el-input v-model="formData.amount" size="small"></el-input>
+            </el-form-item>
+            <el-form-item label="鏍稿噯宸ユ椂:">
+              <el-input
+                v-model="formData.approvedWorkingHour"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="杈呭姪宸ユ椂:">
+              <el-input
+                v-model="formData.nonproductiveTime"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="杈呭姪椤圭洰:">
+              <el-input
+                v-model="formData.auxiliaryProject"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+          </el-form>
+        </el-col>
+      </el-row>
+      <el-form :model="formData" label-width="90px">
+        <el-form-item label="杈呭姪璇存槑:">
+          <el-input
+            v-model="formData.remarks"
+            :rows="3"
+            size="small"
+            type="textarea"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-row>
+          <el-button @click="handleClose">鍙� 娑�</el-button>
+          <el-button :loading="addLoad" type="primary" @click="submitAdd"
+            >纭� 瀹�</el-button
+          >
+        </el-row>
+      </span>
+    </el-dialog>
+    <!--    鎵瑰噯寮规-->
+    <el-dialog :title="title" :visible.sync="checkVisible" width="600px">
+      <el-row style="display: flex; justify-content: space-around">
+        <el-col :span="12">
+          <el-form :model="formData0" label-width="90px">
+            <el-form-item label="骞翠唤:">
+              <el-input
+                v-model="formData0.year"
+                :disabled="title == '鎵瑰噯'"
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鍛ㄦ:">
+              <el-input
+                v-model="formData0.week"
+                :disabled="title == '鎵瑰噯'"
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鏄熸湡:">
+              <el-select
+                v-model="formData0.weekDay"
+                :disabled="title == '鎵瑰噯'"
+                placeholder="璇烽�夋嫨"
+                size="small"
+              >
+                <el-option
+                  v-for="item in weekList"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="濮撳悕:">
+              <el-input
+                v-model="formData0.name"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鐝:">
+              <el-select
+                v-model="formData0.shift"
+                :disabled="title == '鎵瑰噯'"
+                placeholder="璇烽�夋嫨"
+                size="small"
+              >
+                <el-option
+                  v-for="item in classType"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="澶嶆牳璇存槑:">
+              <el-input
+                v-model="formData0.reviewerRemark"
+                :rows="3"
+                size="small"
+                type="textarea"
+              ></el-input>
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :span="12">
+          <el-form :model="formData0" label-width="90px">
+            <el-form-item label="缂栧彿:" required>
+              <el-input
+                v-model="formData0.number"
+                :disabled="title == '鎵瑰噯'"
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鏁伴噺:" required>
+              <el-input
+                v-model="formData0.amount"
+                :disabled="title == '鎵瑰噯'"
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="澶嶆牳鏁伴噺:" required>
+              <el-input
+                v-model="formData0.reviewerNumber"
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="鏍稿噯宸ユ椂:">
+              <el-input
+                v-model="formData0.approvedWorkingHour"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="澶嶆牳宸ユ椂:">
+              <el-input
+                v-model="formData0.reviewerNonproductiveTime"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+            <el-form-item label="杈呭姪椤圭洰:">
+              <el-input
+                v-model="formData0.auxiliaryProject"
+                disabled
+                size="small"
+              ></el-input>
+            </el-form-item>
+          </el-form>
+        </el-col>
+      </el-row>
+      <span slot="footer" class="dialog-footer">
+        <el-row>
+          <el-button :loading="checkLoadN" @click="submitCheck(0)"
+            >涓嶆壒鍑�</el-button
+          >
+          <el-button
+            :loading="checkLoadY"
+            type="primary"
+            @click="submitCheck(1)"
+            >鎵� 鍑�</el-button
+          >
+        </el-row>
+      </span>
+    </el-dialog>
+    <el-dialog
+      :before-close="closeBatchCheckDialog"
+      :title="batchCheckTitle"
+      :visible.sync="batchCheckDialog"
+      width="30%"
+    >
+      <span>{{ batchCheckDialogMessage }}</span>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="batchCheck(0)">涓嶆壒鍑�</el-button>
+        <el-button type="primary" @click="batchCheck(1)">鎵� 鍑�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import ValueTable from "@/components/Table/value-table.vue";
+import { getYearAndMonthAndDays } from "@/utils/date";
+import {
+  selectAuxiliaryWorkingHoursDay,
+  selectAuxiliaryOutputWorkingHours,
+  deleteAuxiliaryWorkingHoursDay,
+  insertAuxiliaryWorkingHoursDay,
+  updateAuxiliaryWorkingHoursDay,
+  approve,
+  collectWorkingHours,
+  selectshiftByUser,
+  selectAuxiliaryWorkingHoursByNumber,
+  exportAssistantHours,
+  exportOutputHours,
+} from "@/api/performance/manHour";
+import limsTable from "@/components/Table/lims-table.vue";
+import { checkPermi } from "@/utils/permission"; // 鏉冮檺鍒ゆ柇鍑芥暟
+export default {
+  components: {
+    ValueTable,
+    limsTable,
+  },
+  dicts: ["sys_class_type"],
+  data() {
+    return {
+      entity: {
+        dateTime: [],
+      },
+      down: false,
+      addFileVisible: false,
+      weekList: [
+        { label: "鍛ㄤ竴", value: "鍛ㄤ竴", type: "primary" },
+        { label: "鍛ㄤ簩", value: "鍛ㄤ簩", type: "primary" },
+        { label: "鍛ㄤ笁", value: "鍛ㄤ笁", type: "primary" },
+        { label: "鍛ㄥ洓", value: "鍛ㄥ洓", type: "primary" },
+        { label: "鍛ㄤ簲", value: "鍛ㄤ簲", type: "primary" },
+        { label: "鍛ㄥ叚", value: "鍛ㄥ叚", type: "primary" },
+        { label: "鍛ㄦ棩", value: "鍛ㄦ棩", type: "primary" },
+      ],
+      currentTable: "ValueTable0",
+      addVisible: false,
+      addLoad: false,
+      formData: {
+        dateTime: getYearAndMonthAndDays() + " 00:00:00",
+        year: new Date().getFullYear(),
+        week: this.getCurrentWeekNumber(),
+        weekDay: this.getWeek(),
+        shift: "",
+        number: "",
+        amount: "",
+        approvedWorkingHour: "", // 鏍稿噯宸ユ椂
+        nonproductiveTime: "",
+        auxiliaryProject: "",
+        remarks: "",
+      },
+      formData0: {
+        dateTime: 0,
+        year: new Date().getFullYear(),
+        week: this.getCurrentWeekNumber(),
+        weekDay: this.getWeek(),
+        createUser: "",
+        shift: "",
+        number: "",
+        reviewerNumber: "", // 澶嶆牳鏁伴噺
+        approvedWorkingHour: "", // 鏍稿噯宸ユ椂
+        reviewerNonproductiveTime: "", // 澶嶆牳宸ユ椂
+        auxiliaryProject: "",
+        reviewerRemark: "",
+        nameUser: "",
+        name: "",
+      },
+      checkVisible: false,
+      checkLoadN: false,
+      checkLoadY: false,
+      title: "鎵瑰噯",
+      classType: [],
+      stateList: [
+        {
+          value: "宸叉彁浜�",
+          label: "宸叉彁浜�",
+        },
+        {
+          value: "宸插鏍�",
+          label: "宸插鏍�",
+        },
+        {
+          value: "宸叉壒鍑�",
+          label: "宸叉壒鍑�",
+        },
+        {
+          value: "涓嶆壒鍑�",
+          label: "涓嶆壒鍑�",
+        },
+      ],
+      totalInfo: null,
+      auxiliaryWorking: null,
+      outLoading: false,
+      batchCheckTitle: "鎵归噺瀹℃牳",
+      batchCheckDialog: false,
+      ValueTable0Selected: [],
+      batchCheckDialogMessage: "",
+      tableData: [],
+      column: [
+        { label: "濮撳悕", prop: "name" },
+        { label: "缂栧彿", prop: "number" },
+        { label: "杈呭姪椤圭洰鍚嶇О", prop: "auxiliaryProject", width: "120px" },
+        {
+          label: "鐘舵��",
+          prop: "state",
+          dataType: "tag",
+          formatType: (params) => {
+            if (params == "宸叉彁浜�") {
+              return "primary";
+            } else if (params == "宸插鏍�") {
+              return "warning";
+            } else if (params == "宸叉壒鍑�") {
+              return "success";
+            } else if (params == "涓嶆壒鍑�") {
+              return "danger";
+            }
+          },
+        },
+        { label: "鏍稿噯宸ユ椂", prop: "approvedWorkingHour" },
+        { label: "鏁伴噺", prop: "amount" },
+        { label: "杈呭姪宸ユ椂", prop: "nonproductiveTime" },
+        { label: "杈呭姪璇存槑", prop: "remarks" },
+        { label: "澶嶆牳浜�", prop: "reviewer" },
+        { label: "澶嶆牳鏁伴噺", prop: "reviewerNumber" },
+        { label: "澶嶆牳宸ユ椂", prop: "reviewerNonproductiveTime" },
+        { label: "澶嶆牳璇存槑", prop: "reviewerRemark" },
+        { label: "骞�", prop: "year" },
+        {
+          label: "鐝",
+          prop: "shift",
+          dataType: "tag",
+          formatData: this.shifList,
+        },
+        { label: "鍛ㄦ", prop: "week" },
+        { label: "鏄熸湡", prop: "weekDay" },
+        { label: "鍒涘缓鏃堕棿", prop: "createTime" },
+        { label: "鏃ユ湡", prop: "dateTime" },
+        {
+          dataType: "action",
+          fixed: "right",
+          label: "鎿嶄綔",
+          width: "160px",
+          operation: [
+            {
+              name: "缂栬緫",
+              type: "text",
+              clickFun: (row) => {
+                this.handleEdit(row);
+              },
+              showHide: (row) => {
+                return this.checkPermi([
+                  "performance:manHour:workTimeManagement:edit",
+                ]);
+              },
+              disabled: (row) => {
+                return row.state === "宸叉壒鍑�";
+              },
+            },
+            {
+              name: "鍒犻櫎",
+              type: "text",
+              clickFun: (row) => {
+                this.handleDelete(row);
+              },
+              showHide: (row) => {
+                return this.checkPermi([
+                  "sperformance:manHour:workTimeManagement:del",
+                ]);
+              },
+              disabled: (row) => {
+                return row.state === "宸叉壒鍑�";
+              },
+            },
+            {
+              name: "鎵瑰噯",
+              type: "text",
+              clickFun: (row) => {
+                this.handleRatify(row);
+              },
+              showHide: (row) => {
+                return this.checkPermi([
+                  "performance:manHour:workTimeManagement:ratify",
+                ]);
+              },
+              disabled: (row) => {
+                return row.state === "宸叉壒鍑�";
+              },
+            },
+          ],
+        },
+      ],
+      page: {
+        total: 0,
+        size: 10,
+        current: 0,
+      },
+      tableLoading: false,
+      tableData0: [],
+      column0: [
+        { label: "妫�娴嬩汉", prop: "name" },
+        { label: "妫�娴嬮」鍒嗙被", prop: "inspectionItemClass" },
+        { label: "妫�娴嬮」", prop: "inspectionItem" },
+        { label: "妫�娴嬪瓙椤�", prop: "inspectionItemSubclass" },
+        { label: "鏍峰搧缂栧彿", prop: "sample" },
+        { label: "濮旀墭鍗曞彿", prop: "orderNo" },
+        { label: "鐢电紗鏍囪瘑", prop: "cableTag" },
+        { label: "浜ч噺宸ユ椂", prop: "outputWorkTime" },
+        { label: "宸ユ椂鍒嗙粍", prop: "manHourGroup" },
+        { label: "鍗曚环", prop: "price" },
+        { label: "鏃ユ湡", prop: "dateTime" },
+        { label: "鍛ㄦ", prop: "week" },
+        { label: "鏄熸湡", prop: "weekDay" },
+      ],
+      page0: {
+        total: 0,
+        size: 10,
+        current: 0,
+      },
+      shifList: [],
+    };
+  },
+  watch: {
+    "formData.dateTime"(val) {
+      if (val == getYearAndMonthAndDays() + " 00:00:00") {
+        this.formData.year = new Date().getFullYear();
+        this.formData.week = this.getCurrentWeekNumber();
+        this.formData.weekDay = this.getWeek();
+      } else {
+        var today = new Date(); // 鑾峰彇褰撳墠鏃ユ湡
+        var yesterday = new Date(today); // 澶嶅埗褰撳墠鏃ユ湡
+        yesterday.setDate(today.getDate() - 1); // 璁剧疆涓哄墠涓�澶�
+        var timestamp = new Date(yesterday.getTime());
+        this.formData.year = timestamp.getFullYear();
+        this.formData.week = this.getCurrentWeekNumber(timestamp);
+        this.formData.weekDay = this.getWeek(timestamp);
+      }
+    },
+    "formData.amount"(val) {
+      if (val) {
+        if (!isNaN(val)) {
+          if (this.formData.approvedWorkingHour) {
+            this.formData.nonproductiveTime =
+              this.formData.approvedWorkingHour * val;
+          }
+        } else {
+          this.$message.error("璇疯緭鍏ユ暟瀛�");
+          this.formData.amount = "";
+        }
+      }
+    },
+    "formData.approvedWorkingHour"(val) {
+      if (val && this.formData.amount) {
+        this.formData.nonproductiveTime = this.formData.amount * val;
+      }
+    },
+    "formData0.reviewerNumber"(val) {
+      if (val) {
+        if (!isNaN(val)) {
+          if (this.formData0.approvedWorkingHour) {
+            this.formData0.reviewerNonproductiveTime =
+              this.formData0.approvedWorkingHour * val;
+          }
+        } else {
+          this.$message.error("璇疯緭鍏ユ暟瀛�");
+          this.formData0.reviewerNumber = "";
+        }
+      }
+    },
+    "formData0.approvedWorkingHour"(val) {
+      if (val && this.formData0.reviewerNumber) {
+        this.formData0.reviewerNonproductiveTime =
+          this.formData0.reviewerNumber * val;
+      }
+    },
+  },
+  created() {
+    this.setDate();
+    this.getDicts("sys_class_type").then((response) => {
+      this.shifList = response.data;
+    });
+  },
+  mounted() {
+    this.getCurrentWeekNumber();
+    this.collectWorkingHours();
+    this.selectshiftByUser();
+    this.getList();
+    this.getList0();
+  },
+  methods: {
+    checkPermi,
+    getList(entity) {
+      this.tableLoading = true;
+      let param = {};
+      if (entity) {
+        param = { ...entity, ...this.page };
+      } else {
+        param = { ...this.entity, ...this.page };
+      }
+      delete param.total;
+      selectAuxiliaryWorkingHoursDay({ ...param })
+        .then((res) => {
+          this.tableLoading = false;
+          if (res.code === 200) {
+            this.tableData = res.data.records;
+            this.page.total = res.data.total;
+          }
+        })
+        .catch((err) => {
+          this.tableLoading = false;
+        });
+    },
+    getList0(entity) {
+      this.tableLoading = true;
+      let param = {};
+      if (entity) {
+        param = { ...entity, ...this.page0 };
+      } else {
+        param = { ...this.entity, ...this.page0 };
+      }
+      delete param.total;
+      selectAuxiliaryOutputWorkingHours({ ...param })
+        .then((res) => {
+          this.tableLoading = false;
+          if (res.code === 200) {
+            this.tableData0 = res.data.records;
+            this.page0.total = res.data.total;
+          }
+        })
+        .catch((err) => {
+          this.tableLoading = false;
+        });
+    },
+    pagination(current, size) {
+      this.page.current = current;
+      this.getList();
+    },
+    pagination0(current, size) {
+      this.page0.current = current;
+      this.getList();
+    },
+    /** 灏嗘椂闂撮�夋嫨鍣ㄩ粯璁ら�変负褰撳ぉ鐨勬棩鏈� */
+    setDate() {
+      let currentDate = new Date();
+      let year = currentDate.getFullYear();
+      let month = String(currentDate.getMonth() + 1).padStart(2, "0");
+      let day = String(currentDate.getDate()).padStart(2, "0");
+      let formattedDate1 = `${year}-${month}-${day}`;
+      let formattedDate2 = `${year}-${month}-${day}`;
+      this.entity.dateTime.push(formattedDate1);
+      this.entity.dateTime.push(formattedDate2);
+      this.refreshTable();
+    },
+    getYearAndMonthAndDays(date) {
+      return getYearAndMonthAndDays(date);
+    },
+    refreshTable(e) {
+      let entity = {};
+      if (this.entity.week1 && this.entity.week2) {
+        entity.week = JSON.stringify([this.entity.week1, this.entity.week2]);
+      } else {
+        entity.week = "";
+      }
+      if (this.entity.dateTime) {
+        entity.dateTime = JSON.stringify(this.entity.dateTime);
+      } else {
+        entity.dateTime = "";
+      }
+      entity.weekDay = this.entity.weekDay;
+      entity.name = this.entity.name;
+      entity.sample = this.entity.sample;
+      if (this.currentTable == "ValueTable0") {
+        entity.state = this.entity.state;
+        this.page.current = 1;
+        this.getList(entity);
+      } else {
+        this.page0.current = 1;
+        this.getList0(entity);
+      }
+      this.collectWorkingHours();
+    },
+    refresh() {
+      this.entity = {};
+      this.refreshTable();
+    },
+    openAdd() {
+      this.formData = {
+        dateTime: getYearAndMonthAndDays() + " 00:00:00",
+        year: new Date().getFullYear(),
+        week: this.getCurrentWeekNumber(),
+        weekDay: this.getWeek(),
+        shift: "",
+        number: "",
+        amount: "",
+        approvedWorkingHour: "",
+        nonproductiveTime: "",
+        auxiliaryProject: "",
+        remarks: "",
+      };
+      this.addVisible = true;
+    },
+    handleEdit(row) {
+      this.formData = row;
+      this.addVisible = true;
+    },
+    handleDelete(row) {
+      this.$confirm("鏄惁鍒犻櫎璇ユ潯鏁版嵁?", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+      })
+        .then(() => {
+          deleteAuxiliaryWorkingHoursDay({ id: row.id }).then((res) => {
+            if (res.code == 201) return;
+            this.$message.success("鍒犻櫎鎴愬姛");
+            this.refreshTable("page");
+          });
+        })
+        .catch(() => {});
+    },
+    handleClose() {
+      this.addVisible = false;
+    },
+    submitAdd() {
+      if (!this.formData.number) {
+        this.$message.error("璇疯緭鍏ョ紪鍙�");
+        return;
+      }
+      if (!this.formData.amount) {
+        this.$message.error("璇疯緭鍏ユ暟閲�");
+        return;
+      }
+      this.addLoad = true;
+      if (!this.formData.id) {
+        insertAuxiliaryWorkingHoursDay(this.formData).then((res) => {
+          this.addLoad = false;
+          if (res.code == 201) return;
+          this.$message.success("宸叉彁浜�");
+          this.formData.number = "";
+          this.formData.amount = "";
+          this.formData.remarks = "";
+          this.formData.approvedWorkingHour = "";
+          this.formData.nonproductiveTime = "";
+          this.formData.auxiliaryProject = "";
+          this.addVisible = false;
+          this.refreshTable("page");
+          this.collectWorkingHours();
+        });
+      } else {
+        updateAuxiliaryWorkingHoursDay(this.formData).then((res) => {
+          this.addLoad = false;
+          if (res.code == 201) return;
+          this.$message.success("鎿嶄綔鎴愬姛");
+          this.formData.number = "";
+          this.formData.amount = "";
+          this.formData.remarks = "";
+          this.formData.approvedWorkingHour = "";
+          this.formData.nonproductiveTime = "";
+          this.formData.auxiliaryProject = "";
+          this.refreshTable("page");
+          this.collectWorkingHours();
+        });
+      }
+    },
+    handleRatify(row) {
+      this.title = "鎵瑰噯";
+      this.formData0 = row;
+      this.checkVisible = true;
+      this.formData0.reviewerNumber = this.formData0.amount;
+      if (this.formData0.approvedWorkingHour && this.formData0.reviewerNumber) {
+        this.formData0.reviewerNonproductiveTime =
+          this.formData0.approvedWorkingHour * this.formData0.reviewerNumber;
+      }
+    },
+    handleChangeTask(row) {
+      this.ValueTable0Selected = JSON.parse(JSON.stringify(row));
+    },
+    openBatchCheck(e) {
+      if (this.ValueTable0Selected.length > 0) {
+        const isApprove = this.ValueTable0Selected.every(
+          (item) => item.state !== "宸叉壒鍑�"
+        );
+        this.batchCheckTitle = "鎵归噺鎵瑰噯";
+        this.batchCheckDialogMessage = "鏄惁鍏ㄩ儴閫氳繃鎵瑰噯?";
+        if (isApprove) {
+          this.batchCheckDialog = true;
+        } else {
+          this.$message.error("璇烽�夋嫨鏈壒鍑嗙殑鏁版嵁");
+        }
+      } else {
+        this.$message.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+      }
+    },
+    batchCheck(e) {
+      this.$refs.ValueTable0.batchCheck(e);
+    },
+    closeBatchCheckDialog() {
+      this.batchCheckDialog = false;
+    },
+    submitBatchCheckDialog() {
+      this.batchCheckDialog = false;
+      this.refreshTable("page");
+      this.collectWorkingHours();
+    },
+    submitCheck(e) {
+      if (!this.formData0.number) {
+        this.$message.error("璇疯緭鍏ョ紪鍙�");
+        return;
+      }
+      if (!this.formData0.amount) {
+        this.$message.error("璇疯緭鍏ユ暟閲�");
+        return;
+      }
+      if (e == 0) {
+        this.checkLoadN = true;
+      } else {
+        this.checkLoadY = true;
+      }
+      this.formData0.state = e == 0 ? "涓嶆壒鍑�" : "宸叉壒鍑�";
+      approve({
+        auxiliaryWorkingHoursDays: [this.formData0],
+      }).then((res) => {
+        if (e == 0) {
+          this.checkLoadN = false;
+        } else {
+          this.checkLoadY = false;
+        }
+        if (res.code == 201) return;
+        this.$message.success("鎿嶄綔鎴愬姛");
+        this.checkVisible = false;
+        this.refreshTable("page");
+        this.collectWorkingHours();
+      });
+    },
+    getCurrentWeekNumber(now = new Date()) {
+      const startOfWeek = new Date(
+        now.getFullYear(),
+        now.getMonth(),
+        now.getDate() - now.getDay()
+      ); // 鍛ㄥぉ
+      const firstWeekOfYear = new Date(startOfWeek.getFullYear(), 0, 0); // 褰撳勾鐨勭涓�涓懆澶�
+      const firstWeekOfNextYear = new Date(
+        firstWeekOfYear.getFullYear() + 1,
+        0,
+        0
+      ); // 涓嬩竴骞寸殑绗竴涓懆澶�
+      const daysSinceNewYear =
+        (startOfWeek - firstWeekOfYear) / (24 * 60 * 60 * 1000); // 璁$畻鑷柊骞翠互鏉ョ殑澶╂暟
+      const weeksSinceNewYear = Math.floor(daysSinceNewYear / 7); // 澶╂暟闄や互7寰楀埌鍛ㄦ暟
+
+      if (startOfWeek > now) {
+        // 濡傛灉褰撳墠鍛ㄧ殑鍛ㄥぉ杩樻病鍒帮紝鍒欒繑鍥炰笂骞寸殑鏈�鍚庝竴鍛�
+        return weeksSinceNewYear;
+      } else if (firstWeekOfNextYear <= now) {
+        // 濡傛灉褰撳墠鍛ㄧ殑鍛ㄥぉ宸茬粡杩囦簡锛屽垯杩斿洖褰撳勾鐨勫懆鏁�
+        return weeksSinceNewYear + 1;
+      } else {
+        // 鍚﹀垯杩斿洖褰撳勾鐨勬渶鍚庝竴鍛�
+        return weeksSinceNewYear + 2;
+      }
+    },
+    getWeek(e = new Date()) {
+      // let str = '鏃ヤ竴浜屼笁鍥涗簲鍏�'
+      let d = e.getDay();
+      // let c = str.charAt(d)
+      // return `鍛�${c}`
+      return String(d);
+    },
+    // 缁熻浜ч噺宸ユ椂姹囨�诲拰杈呭姪宸ユ椂姹囨��
+    collectWorkingHours() {
+      let entity = {};
+      if (this.entity.week1 && this.entity.week2) {
+        entity.week = JSON.stringify([this.entity.week1, this.entity.week2]);
+      } else {
+        entity.week = "";
+      }
+      if (this.entity.dateTime) {
+        entity.dateTime = JSON.stringify(this.entity.dateTime);
+      } else {
+        entity.dateTime = "";
+      }
+      entity.weekDay = this.entity.weekDay;
+      entity.name = this.entity.name;
+      collectWorkingHours({ entity: entity }).then((res) => {
+        this.totalInfo = res.data;
+      });
+    },
+    selectshiftByUser() {
+      selectshiftByUser().then((res) => {
+        this.formData.shift = res.data;
+      });
+    },
+    getInfoByCode() {
+      if (this.formData.number) {
+        selectAuxiliaryWorkingHoursByNumber(this.formData.number).then(
+          (res) => {
+            this.auxiliaryWorking = res.data;
+            if (this.addVisible) {
+              this.formData.approvedWorkingHour =
+                this.auxiliaryWorking.approvedWorkingHour;
+              this.formData.auxiliaryProject =
+                this.auxiliaryWorking.auxiliaryProject;
+            } else if (this.title == "瀹℃牳" && this.checkVisible) {
+              this.formData0.approvedWorkingHour =
+                this.auxiliaryWorking.approvedWorkingHour;
+              this.formData0.auxiliaryProject =
+                this.auxiliaryWorking.auxiliaryProject;
+            }
+          }
+        );
+      }
+    },
+    handleOut() {
+      let entity = this.HaveJson(this.entity);
+      if (this.entity.dateTime) {
+        entity.dateTime = JSON.stringify(this.entity.dateTime);
+      } else {
+        entity.dateTime = "";
+      }
+      this.outLoading = true;
+      exportAssistantHours({ entity: entity })
+        .then((res) => {
+          this.outLoading = false;
+          this.$message.success("瀵煎嚭鎴愬姛");
+          const blob = new Blob([res]);
+          this.$download.saveAs(blob, "杈呭姪宸ユ椂淇℃伅瀵煎嚭.xlsx");
+        })
+        .catch((err) => {
+          this.outLoading = false;
+        });
+    },
+    handleOut1() {
+      let entity = this.HaveJson(this.entity);
+      if (this.entity.dateTime) {
+        entity.dateTime = JSON.stringify(this.entity.dateTime);
+      } else {
+        entity.dateTime = "";
+      }
+      this.outLoading = true;
+      exportOutputHours({ entity: entity })
+        .then((res) => {
+          this.outLoading = false;
+          this.$message.success("瀵煎嚭鎴愬姛");
+          const blob = new Blob([res]);
+          this.$download.saveAs(blob, "浜ч噺宸ユ椂淇℃伅瀵煎嚭.xlsx");
+        })
+        .catch((err) => {
+          this.outLoading = false;
+        });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.work-time-management {
+  height: 100%;
+  overflow-y: scroll;
+  padding: 20px;
+  padding-top: 0;
+  /* scrollbar-width: none;  */
+}
+/* .work-time-management::-webkit-scrollbar {
+  display: none;
+} */
+.search {
+  background-color: #fff;
+  height: 80px;
+  display: flex;
+  align-items: center;
+}
+
+.search_thing {
+  width: 300px;
+  display: flex;
+  align-items: center;
+}
+
+.search_label {
+  width: 70px;
+  font-size: 14px;
+  text-align: right;
+}
+
+.search_input {
+  width: calc(100% - 70px);
+}
+</style>
diff --git a/src/views/performance/manHour/workTimeStatistics.vue b/src/views/performance/manHour/workTimeStatistics.vue
new file mode 100644
index 0000000..4425caf
--- /dev/null
+++ b/src/views/performance/manHour/workTimeStatistics.vue
@@ -0,0 +1,176 @@
+<template>
+  <div>
+    <div>
+      <div class="search">
+        <div class="search_thing">
+          <div class="search_label">鏃ユ湡锛�</div>
+          <div class="search_input" style="display: flex; align-items: center">
+            <el-date-picker
+              v-model="queryParams.month"
+              :clearable="false"
+              format="yyyy-MM"
+              placeholder="閫夋嫨鏈�"
+              size="small"
+              style="width: 100%"
+              type="month"
+              value-format="yyyy-MM"
+              @change="refreshTable()"
+            >
+            </el-date-picker>
+          </div>
+        </div>
+        <div class="search_thing">
+          <div class="search_label">鍛樺伐锛�</div>
+          <el-input
+            v-model="queryParams.name"
+            clearable
+            placeholder="璇疯緭鍏�"
+            size="small"
+            @keyup.enter.native="refreshTable()"
+          ></el-input>
+        </div>
+        <div class="search_thing" style="padding-left: 30px">
+          <el-button size="small" @click="refresh()">閲� 缃�</el-button>
+          <el-button size="small" type="primary" @click="refreshTable()"
+            >鏌� 璇�</el-button
+          >
+        </div>
+      </div>
+      <div class="table">
+        <TableCard :showForm="false" :showTitle="false">
+          <template v-slot:table>
+            <limsTable
+              :column="tableColumn"
+              :table-data="tableData"
+              :table-loading="tableLoading"
+              :page="page"
+              style="padding: 0 15px"
+            >
+            </limsTable>
+          </template>
+        </TableCard>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getYearAndMonthAndDays } from "@/utils/date";
+import TableCard from "@/components/TableCard/index.vue";
+import limsTable from "@/components/Table/lims-table.vue";
+import { selectAuxiliaryAllByMonth } from "@/api/performance/manHour";
+export default {
+  components: {
+    limsTable,
+    TableCard,
+  },
+  data() {
+    return {
+      queryParams: {
+        month: getYearAndMonthAndDays().slice(0, 7),
+        name: "",
+        departLims: "",
+      },
+      tableColumn: [
+        {
+          label: "濮撳悕",
+          minWidth: "120px",
+          prop: "userName",
+        },
+        {
+          label: "鏈堜唤",
+          minWidth: "120px",
+          prop: "month",
+        },
+        {
+          label: "浜ч噺宸ユ椂",
+          minWidth: "120px",
+          prop: "yieldHour",
+        },
+        {
+          label: "杈呭姪宸ユ椂",
+          minWidth: "120px",
+          prop: "subsidiaryHour",
+        },
+        {
+          label: "鎬诲伐鏃�",
+          minWidth: "120px",
+          prop: "totalHour",
+        },
+      ],
+      tableData: [],
+      tableLoading: false,
+      page: {
+        total: 0,
+        size: 10,
+        current: 0,
+      },
+    };
+  },
+  mounted() {
+    this.refreshTable();
+  },
+  methods: {
+    refreshTable() {
+      this.tableLoading = true;
+      selectAuxiliaryAllByMonth(this.queryParams)
+        .then((res) => {
+          this.tableLoading = false;
+          if (res.code === 201) return;
+          this.tableData = res.data;
+        })
+        .catch(() => {
+          this.tableLoading = false;
+        });
+    },
+    refresh() {
+      this.queryParams = {
+        month: getYearAndMonthAndDays().slice(0, 7),
+        name: "",
+        departLims: "",
+      };
+      this.refreshTable();
+    },
+    // 鍒嗛〉
+    handleCurrent(page) {
+      this.pagination.curent = page;
+      this.refreshTable();
+    },
+    handleSizeChange(size) {
+      this.pagination.pageSize = size;
+      this.refreshTable();
+    },
+  },
+};
+</script>
+
+<style scoped>
+.work-time-statistics {
+  height: 100%;
+}
+.search {
+  background-color: #fff;
+  height: 80px;
+  display: flex;
+  align-items: center;
+}
+
+.search_thing {
+  width: 270px;
+  display: flex;
+  align-items: center;
+}
+
+.search_label {
+  width: 60px;
+  font-size: 14px;
+  text-align: right;
+}
+
+.search_input {
+  width: calc(100% - 60px);
+}
+.table {
+  height: calc(100% - 60px - 80px - 10px - 40px - 25px);
+}
+</style>
diff --git a/src/views/standard/model/index.vue b/src/views/standard/model/index.vue
index 323b197..375cd35 100644
--- a/src/views/standard/model/index.vue
+++ b/src/views/standard/model/index.vue
@@ -21,29 +21,29 @@
       </div>
       <div class="btn">
         <el-button
-          v-if="checkPermi(['system:standard:model:add'])"
+          v-if="checkPermi(['standard:model:add'])"
           size="small"
           type="primary"
           @click="openAdd"
           >鏂板</el-button
         >
-        <el-button
-          v-if="checkPermi(['system:standard:model:copy'])"
+        <!-- <el-button
+          v-if="checkPermi(['standard:model:copy'])"
           size="small"
           @click="copyTemplate"
           >澶嶅埗妯$増</el-button
-        >
+        > -->
       </div>
     </div>
-    <div class="table">
-      <lims-table
-        :tableData="tableData"
-        :column="column"
-        :page="page"
-        :tableLoading="tableLoading"
-        :height="'calc(100% - 200px)'"
-      ></lims-table>
-    </div>
+    <lims-table
+      :tableData="tableData"
+      :column="column"
+      :page="page"
+      :tableLoading="tableLoading"
+      :height="'calc(100vh - 240px)'"
+      style="padding: 20px; padding-top: 0"
+      @pagination="pagination"
+    ></lims-table>
     <el-dialog
       :before-close="isClose"
       :close-on-click-modal="false"
@@ -153,7 +153,7 @@
           dataType: "action",
           fixed: "right",
           label: "鎿嶄綔",
-          width: "180px",
+          width: "320px",
           operation: [
             {
               name: "缂栬緫",
@@ -164,7 +164,7 @@
                 this.isShowCopyTem = true;
               },
               showHide: (row) => {
-                return this.checkPermi(["system:standard:model:edit"]);
+                return this.checkPermi(["standard:model:edit"]);
               },
             },
             {
@@ -174,7 +174,7 @@
                 this.handleDelete(row);
               },
               showHide: (row) => {
-                return this.checkPermi(["system:standard:model:del"]);
+                return this.checkPermi(["standard:model:del"]);
               },
             },
             {
@@ -184,7 +184,7 @@
                 this.copyTemplate(row);
               },
               showHide: (row) => {
-                return this.checkPermi(["system:standard:model:copy"]);
+                return this.checkPermi(["standard:model:copy"]);
               },
             },
             {
@@ -195,8 +195,8 @@
               },
               showHide: (row) => {
                 return this.checkPermi([
-                  "system:standard:model:edit",
-                  "system:standard:model:add",
+                  "standard:model:edit",
+                  "standard:model:add",
                 ]);
               },
             },
@@ -220,23 +220,31 @@
     checkPermi,
     getList() {
       this.tableLoading = true;
-      selectStandardTemplatePageList({ ...this.queryParams, ...this.page })
+      let param = { ...this.queryParams, ...this.page };
+      delete param.total;
+      selectStandardTemplatePageList({ ...param })
         .then((res) => {
           this.tableLoading = false;
           if (res.code === 200) {
-            this.tableData = res.data;
-            this.page.total = res.total;
+            this.tableData = res.data.records;
+            this.page.total = res.data.total;
           }
         })
         .catch((err) => {
           this.tableLoading = false;
         });
     },
+    pagination(current, size) {
+      this.page.current = current;
+      this.getList();
+    },
     refreshTable(e) {
+      this.page.current = 1;
       this.getList();
     },
     refresh() {
       this.queryParams = {};
+      this.page.current = 1;
       this.getList();
     },
     openAdd() {
@@ -278,7 +286,7 @@
                 });
               break;
             case "缂栬緫":
-              params.thing = row.thing;
+              params.thing = this.copyForm.thing ? this.copyForm.thing : "";
               upStandardTemplate(params)
                 .then((res) => {
                   if (res.code == 201) return;
@@ -339,7 +347,7 @@
           return;
         }
         this.row = row;
-        this.row.thing = res.data;
+        this.row.thing = res.msg;
         this.isShow = true;
       });
     },
@@ -439,7 +447,7 @@
 }
 
 .search_label {
-  width: 110px;
+  width: 90px;
   font-size: 14px;
   text-align: right;
 }
@@ -449,13 +457,7 @@
 }
 .btn {
   position: absolute;
-  right: 20px;
+  right: 14px;
   top: 20px;
-}
-
-.table {
-  background-color: #fff;
-  padding: 10px;
-  padding-top: 0;
 }
 </style>
diff --git a/src/views/standard/standardLibrary/index.vue b/src/views/standard/standardLibrary/index.vue
index 2f0e756..d57f377 100644
--- a/src/views/standard/standardLibrary/index.vue
+++ b/src/views/standard/standardLibrary/index.vue
@@ -204,7 +204,7 @@
           ></el-input>
         </el-col>
         <el-col
-          v-if="checkPermi(['system:standard:standardLibrary:add'])"
+          v-if="checkPermi(['standard:standardLibrary:add'])"
           :span="4"
           style="text-align: center; line-height: 30px"
         >
@@ -261,9 +261,7 @@
             </el-col>
             <el-col
               v-if="
-                checkPermi([
-                  'system:standard:standardLibrary:delStandardTree',
-                ]) &&
+                checkPermi(['standard:standardLibrary:delStandardTree']) &&
                 (node.data.children === null ||
                   node.data.children === undefined)
               "
@@ -280,9 +278,7 @@
             </el-col>
             <el-col
               v-if="
-                checkPermi([
-                  'system:standard:standardLibrary:delStandardTree',
-                ]) &&
+                checkPermi(['standard:standardLibrary:delStandardTree']) &&
                 (node.data.children === null ||
                   node.data.children === undefined)
               "
@@ -414,9 +410,7 @@
             <template slot-scope="scope">
               <el-input
                 v-if="
-                  checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 v-model="scope.row.ask"
                 :autosize="{ minRows: 1, maxRows: 3 }"
@@ -433,9 +427,7 @@
             <template slot-scope="scope">
               <el-input
                 v-if="
-                  checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 v-model="scope.row.tell"
                 :autosize="{ minRows: 1, maxRows: 3 }"
@@ -454,9 +446,7 @@
             <template slot-scope="scope">
               <el-select
                 v-if="
-                  checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 v-model="scope.row.methodS"
                 clearable
@@ -486,9 +476,7 @@
             <template slot-scope="scope">
               <el-select
                 v-if="
-                  checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 v-model="scope.row.radius"
                 clearable
@@ -519,9 +507,7 @@
             <template slot-scope="scope">
               <el-input
                 v-if="
-                  checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 v-model="scope.row.price"
                 placeholder="鍗曚环(鍏�)"
@@ -538,9 +524,7 @@
             <template slot-scope="scope">
               <el-input
                 v-if="
-                  checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 v-model="scope.row.manHour"
                 placeholder="鍗曚环(鍏�)"
@@ -564,9 +548,7 @@
               <el-select
                 v-model="scope.row.templateId"
                 :disabled="
-                  !checkPermi([
-                    'system:standard:standardLibrary:upStandardProduct',
-                  ])
+                  !checkPermi(['standard:standardLibrary:upStandardProduct'])
                 "
                 filterable
                 size="small"
diff --git a/vue.config.js b/vue.config.js
index 159f836..1d8e525 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -1,15 +1,15 @@
-'use strict'
-const path = require('path')
+"use strict";
+const path = require("path");
 
 function resolve(dir) {
-  return path.join(__dirname, dir)
+  return path.join(__dirname, dir);
 }
 
-const CompressionPlugin = require('compression-webpack-plugin')
+const CompressionPlugin = require("compression-webpack-plugin");
 
-const name = process.env.VUE_APP_TITLE || '鑻ヤ緷绠$悊绯荤粺' // 缃戦〉鏍囬
+const name = process.env.VUE_APP_TITLE || "鑻ヤ緷绠$悊绯荤粺"; // 缃戦〉鏍囬
 
-const port = process.env.port || process.env.npm_config_port || 80 // 绔彛
+const port = process.env.port || process.env.npm_config_port || 80; // 绔彛
 
 // vue.config.js 閰嶇疆璇存槑
 //瀹樻柟vue.config.js 鍙傝�冩枃妗� https://cli.vuejs.org/zh/config/#css-loaderoptions
@@ -20,112 +20,111 @@
   // 渚嬪 https://www.ruoyi.vip/銆傚鏋滃簲鐢ㄨ閮ㄧ讲鍦ㄤ竴涓瓙璺緞涓婏紝浣犲氨闇�瑕佺敤杩欎釜閫夐」鎸囧畾杩欎釜瀛愯矾寰勩�備緥濡傦紝濡傛灉浣犵殑搴旂敤琚儴缃插湪 https://www.ruoyi.vip/admin/锛屽垯璁剧疆 baseUrl 涓� /admin/銆�
   publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
   // 鍦╪pm run build 鎴� yarn build 鏃� 锛岀敓鎴愭枃浠剁殑鐩綍鍚嶇О锛堣鍜宐aseUrl鐨勭敓浜х幆澧冭矾寰勪竴鑷达級锛堥粯璁ist锛�
-  outputDir: 'dist',
+  outputDir: "dist",
   // 鐢ㄤ簬鏀剧疆鐢熸垚鐨勯潤鎬佽祫婧� (js銆乧ss銆乮mg銆乫onts) 鐨勶紱锛堥」鐩墦鍖呬箣鍚庯紝闈欐�佽祫婧愪細鏀惧湪杩欎釜鏂囦欢澶逛笅锛�
-  assetsDir: 'static',
+  assetsDir: "static",
   // 鏄惁寮�鍚痚slint淇濆瓨妫�娴嬶紝鏈夋晥鍊硷細ture | false | 'error'
-  lintOnSave: process.env.NODE_ENV === 'development',
+  lintOnSave: process.env.NODE_ENV === "development",
   // 濡傛灉浣犱笉闇�瑕佺敓浜х幆澧冪殑 source map锛屽彲浠ュ皢鍏惰缃负 false 浠ュ姞閫熺敓浜х幆澧冩瀯寤恒��
   productionSourceMap: false,
-  transpileDependencies: ['quill'],
+  transpileDependencies: ["quill"],
   // webpack-dev-server 鐩稿叧閰嶇疆
   devServer: {
-    host: '0.0.0.0',
+    host: "0.0.0.0",
     port: port,
     open: true,
     proxy: {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
-        target: `http://192.168.1.36:8002`,
+        target: `http://192.168.0.104:8002`,
         changeOrigin: true,
         pathRewrite: {
-          ['^' + process.env.VUE_APP_BASE_API]: ''
-        }
-      }
+          ["^" + process.env.VUE_APP_BASE_API]: "",
+        },
+      },
     },
-    disableHostCheck: true
+    disableHostCheck: true,
   },
   css: {
     loaderOptions: {
       sass: {
-        sassOptions: { outputStyle: "expanded" }
-      }
-    }
+        sassOptions: { outputStyle: "expanded" },
+      },
+    },
   },
   configureWebpack: {
     name: name,
     resolve: {
       alias: {
-        '@': resolve('src')
-      }
+        "@": resolve("src"),
+      },
     },
     plugins: [
       // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#浣跨敤gzip瑙e帇缂╅潤鎬佹枃浠�
       new CompressionPlugin({
-        cache: false,                                  // 涓嶅惎鐢ㄦ枃浠剁紦瀛�
-        test: /\.(js|css|html|jpe?g|png|gif|svg)?$/i,  // 鍘嬬缉鏂囦欢鏍煎紡
-        filename: '[path][base].gz[query]',            // 鍘嬬缉鍚庣殑鏂囦欢鍚�
-        algorithm: 'gzip',                             // 浣跨敤gzip鍘嬬缉
-        minRatio: 0.8,                                 // 鍘嬬缉姣斾緥锛屽皬浜� 80% 鐨勬枃浠朵笉浼氳鍘嬬缉
-        deleteOriginalAssets: false                    // 鍘嬬缉鍚庡垹闄ゅ師鏂囦欢
-      })
+        cache: false, // 涓嶅惎鐢ㄦ枃浠剁紦瀛�
+        test: /\.(js|css|html|jpe?g|png|gif|svg)?$/i, // 鍘嬬缉鏂囦欢鏍煎紡
+        filename: "[path][base].gz[query]", // 鍘嬬缉鍚庣殑鏂囦欢鍚�
+        algorithm: "gzip", // 浣跨敤gzip鍘嬬缉
+        minRatio: 0.8, // 鍘嬬缉姣斾緥锛屽皬浜� 80% 鐨勬枃浠朵笉浼氳鍘嬬缉
+        deleteOriginalAssets: false, // 鍘嬬缉鍚庡垹闄ゅ師鏂囦欢
+      }),
     ],
   },
   chainWebpack(config) {
-    config.plugins.delete('preload') // TODO: need test
-    config.plugins.delete('prefetch') // TODO: need test
+    config.plugins.delete("preload"); // TODO: need test
+    config.plugins.delete("prefetch"); // TODO: need test
 
     // set svg-sprite-loader
+    config.module.rule("svg").exclude.add(resolve("src/assets/icons")).end();
     config.module
-      .rule('svg')
-      .exclude.add(resolve('src/assets/icons'))
-      .end()
-    config.module
-      .rule('icons')
+      .rule("icons")
       .test(/\.svg$/)
-      .include.add(resolve('src/assets/icons'))
+      .include.add(resolve("src/assets/icons"))
       .end()
-      .use('svg-sprite-loader')
-      .loader('svg-sprite-loader')
+      .use("svg-sprite-loader")
+      .loader("svg-sprite-loader")
       .options({
-        symbolId: 'icon-[name]'
+        symbolId: "icon-[name]",
       })
-      .end()
+      .end();
 
-    config.when(process.env.NODE_ENV !== 'development', config => {
-          config
-            .plugin('ScriptExtHtmlWebpackPlugin')
-            .after('html')
-            .use('script-ext-html-webpack-plugin', [{
+    config.when(process.env.NODE_ENV !== "development", (config) => {
+      config
+        .plugin("ScriptExtHtmlWebpackPlugin")
+        .after("html")
+        .use("script-ext-html-webpack-plugin", [
+          {
             // `runtime` must same as runtimeChunk name. default is `runtime`
-              inline: /runtime\..*\.js$/
-            }])
-            .end()
+            inline: /runtime\..*\.js$/,
+          },
+        ])
+        .end();
 
-          config.optimization.splitChunks({
-            chunks: 'all',
-            cacheGroups: {
-              libs: {
-                name: 'chunk-libs',
-                test: /[\\/]node_modules[\\/]/,
-                priority: 10,
-                chunks: 'initial' // only package third parties that are initially dependent
-              },
-              elementUI: {
-                name: 'chunk-elementUI', // split elementUI into a single package
-                test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
-                priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
-              },
-              commons: {
-                name: 'chunk-commons',
-                test: resolve('src/components'), // can customize your rules
-                minChunks: 3, //  minimum common number
-                priority: 5,
-                reuseExistingChunk: true
-              }
-            }
-          })
-          config.optimization.runtimeChunk('single')
-    })
-  }
-}
+      config.optimization.splitChunks({
+        chunks: "all",
+        cacheGroups: {
+          libs: {
+            name: "chunk-libs",
+            test: /[\\/]node_modules[\\/]/,
+            priority: 10,
+            chunks: "initial", // only package third parties that are initially dependent
+          },
+          elementUI: {
+            name: "chunk-elementUI", // split elementUI into a single package
+            test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
+            priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
+          },
+          commons: {
+            name: "chunk-commons",
+            test: resolve("src/components"), // can customize your rules
+            minChunks: 3, //  minimum common number
+            priority: 5,
+            reuseExistingChunk: true,
+          },
+        },
+      });
+      config.optimization.runtimeChunk("single");
+    });
+  },
+};

--
Gitblit v1.9.3