spring
2025-02-15 74da5f0d434681ca8e9090e242e7fd29c144ebcb
工时管理30%
已修改7个文件
已添加7个文件
2752 ■■■■ 文件已修改
src/api/performance/manHour.js 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/standard/model.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Excel/luckysheet.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/lims-table.vue 629 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/TableCard/index.vue 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/AppMain.vue 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/performance/class/index.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/performance/manHour/index.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/performance/manHour/workTimeConfig.vue 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/performance/manHour/workTimeManagement.vue 1143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/performance/manHour/workTimeStatistics.vue 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/standard/model/index.vue 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/standard/standardLibrary/index.vue 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 149 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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,
  });
}
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,
  });
}
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 = {};
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、width、prop、dataType、slot
  // label ï¼šåˆ—名,就是表头上的标签叫什么些什么,类型 string
  // width:该列宽度, string
  // prop:  table绑定数据字段 string,这一列要展示哪个tableData里面的字段就写哪个字段
  // dataType:  å†…置多个基本的element组件可供直接使用 string
  // slot  å½“`dataType`为`slot`时必带参数,参数值为插槽的 `slot` å€¼ string,具体使用方法请看下面的第4点slot插槽的使用
  // fixed:列是否固定在左侧或者右侧,true è¡¨ç¤ºå›ºå®šåœ¨å·¦ä¾§ string, boolean
  // sortable å¯¹åº”列是否可以排序 boolean, string
  // filters æ•°æ®è¿‡æ»¤çš„选项,数组格式,数组中的元素需要有 text å’Œ value å±žæ€§ã€‚Array
  // columnKey ï¼šcolumn çš„ key,如果需要使用 filter-change äº‹ä»¶ï¼Œåˆ™éœ€è¦æ­¤å±žæ€§æ ‡è¯†æ˜¯å“ªä¸ª column çš„筛选条件
  // filteredValue  é€‰ä¸­çš„æ•°æ®è¿‡æ»¤é¡¹ï¼Œå¦‚果需要自定义表头过滤的渲染方式,可能会需要此属性。
  // filterMultiple  æ•°æ®è¿‡æ»¤çš„选项是否多选
  // minWidth å¯¹åº”列的最小宽度,与 width çš„区别是 width æ˜¯å›ºå®šçš„,min-width ä¼šæŠŠå‰©ä½™å®½åº¦æŒ‰æ¯”例分配给设置了 min-width çš„列 string
  // formatData  å¯¹æ•°æ®è¿›è¡Œæ•°æ®å¤„理,接受一个回调函数 (params?: {prop}) => {}
  // formatType  å½“ `dataType`为 `tag`时,对标签颜色设置 (params?: {prop}) => { return 'danger'| 'success'... }`
  // operation å½“ `dataType` ä¸º `option`时,对按钮的 é…ç½®ï¼Œå…·ä½“配置项以下图为准object
  // tagGroup å½“ `dataType`为 `tag`时,绑定数据集字段显示名称 object
  /**
   * æ’槽的使用方法:
   */
  /* <div
<script>
// æ³¨ï¼šä»¥ä¸‹æ˜¯æ‰€æœ‰é…ç½®é¡¹ï¼Œå…¶ä¸­æœ€å¸¸ä½¿ç”¨çš„就是label、width、prop、dataType、slot
// label ï¼šåˆ—名,就是表头上的标签叫什么些什么,类型 string
// width:该列宽度, string
// prop:  table绑定数据字段 string,这一列要展示哪个tableData里面的字段就写哪个字段
// dataType:  å†…置多个基本的element组件可供直接使用 string
// slot  å½“`dataType`为`slot`时必带参数,参数值为插槽的 `slot` å€¼ string,具体使用方法请看下面的第4点slot插槽的使用
// fixed:列是否固定在左侧或者右侧,true è¡¨ç¤ºå›ºå®šåœ¨å·¦ä¾§ string, boolean
// sortable å¯¹åº”列是否可以排序 boolean, string
// filters æ•°æ®è¿‡æ»¤çš„选项,数组格式,数组中的元素需要有 text å’Œ value å±žæ€§ã€‚Array
// columnKey ï¼šcolumn çš„ key,如果需要使用 filter-change äº‹ä»¶ï¼Œåˆ™éœ€è¦æ­¤å±žæ€§æ ‡è¯†æ˜¯å“ªä¸ª column çš„筛选条件
// filteredValue  é€‰ä¸­çš„æ•°æ®è¿‡æ»¤é¡¹ï¼Œå¦‚果需要自定义表头过滤的渲染方式,可能会需要此属性。
// filterMultiple  æ•°æ®è¿‡æ»¤çš„选项是否多选
// minWidth å¯¹åº”列的最小宽度,与 width çš„区别是 width æ˜¯å›ºå®šçš„,min-width ä¼šæŠŠå‰©ä½™å®½åº¦æŒ‰æ¯”例分配给设置了 min-width çš„列 string
// formatData  å¯¹æ•°æ®è¿›è¡Œæ•°æ®å¤„理,接受一个回调函数 (params?: {prop}) => {}
// formatType  å½“ `dataType`为 `tag`时,对标签颜色设置 (params?: {prop}) => { return 'danger'| 'success'... }`
// operation å½“ `dataType` ä¸º `option`时,对按钮的 é…ç½®ï¼Œå…·ä½“配置项以下图为准object
// 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:按钮大小,以elementUi å‚数为准
  // icon:按钮上的icon,以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:按钮大小,以elementUi å‚数为准
// icon:按钮上的icon,以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>
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>
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 {
src/views/performance/class/index.vue
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>
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>
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>
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>
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>
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"
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" ? "/" : "/",
  // åœ¨npm run build æˆ– yarn build æ—¶ ï¼Œç”Ÿæˆæ–‡ä»¶çš„目录名称(要和baseUrl的生产环境路径一致)(默认dist)
  outputDir: 'dist',
  outputDir: "dist",
  // ç”¨äºŽæ”¾ç½®ç”Ÿæˆçš„静态资源 (js、css、img、fonts) çš„;(项目打包之后,静态资源会放在这个文件夹下)
  assetsDir: 'static',
  assetsDir: "static",
  // æ˜¯å¦å¼€å¯eslint保存检测,有效值: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解压缩静态文件
      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");
    });
  },
};