Newer
Older
xc-business-system / src / views / equipement / standard / book / components / config / thirteenth / templateTable.vue
<script lang="ts" setup name="ThirdTemplateTable">
import type { Ref } from 'vue'
import { ElMessage, ElTable } from 'element-plus'
import { defineExpose, ref } from 'vue'
import type { TableColumn } from '@/components/NormalTable/table_interface'
import { getDictByCode } from '@/api/system/dict'
import type { dictType } from '@/global'
import SelectEquipmentDialog from '@/views/business/fieldTest/approve/dialog/selectEquipmentDialog.vue'

// ------------------定义props、 emit-------------------
const props = defineProps({
  pageType: {
    type: String,
    default: 'detail',
  },
  // 数据
  data: {
    type: Array,
    default() {
      return []
    },
  },
  // 表格高度
  height: {
    type: Number,
    default() {
      return null
    },
  },
  // 数据列配置
  columns: {
    type: Array<TableColumn>,
    default() {
      return []
    },
  },
  // 表格大小
  size: {
    type: String,
    default: 'default',
  }, // 表格大小,默认,small,mini等,与el-table条件相同
  type: String, // 表格类型
})
const emit = defineEmits(['change', 'selectionChange', 'rowClick', 'rowDbClick', 'filterChange', 'confirmSelectedEquipment', 'selectReferencePoint', 'changeSelectTypeValue'])
// ------------------------------------------字典----------------------------------------------
const checkTypeList = ref<dictType[]>([]) // 核查类型
const typeValueList = ref<dictType[]>([]) // 类型
const standardTimeUnitList = ref<dictType[]>([]) // 时间单位
const standardVoltageList = ref<dictType[]>([]) // 电压单位
const standardResistanceList = ref<dictType[]>([]) // 电阻单位公用
const standardFrequencyUnitList = ref<dictType[]>([]) // 频率单位公用
const standardTechnicalIndexSymbolList = ref<dictType[]>([]) // 技术指标规则

/**
 * 获取字典
 */
function getDict() {
  // 核查类型
  // getDictByCode('bizFirstStandardCheckType').then((response) => {
  //   checkTypeList.value = response.data
  // })
  // 技术指标规则
  getDictByCode('standardTechnicalIndexSymbol').then((response) => {
    standardTechnicalIndexSymbolList.value = response.data
  })
  // 类型
  getDictByCode('standard13TypeValue').then((response) => {
    typeValueList.value = response.data
  })
  // 电压单位--公用/垂直偏转系数(/div)单位
  getDictByCode('standardVoltage').then((response) => {
    standardVoltageList.value = response.data
  })
  // 时间单位
  getDictByCode('standardTimeUnit').then((response) => {
    standardTimeUnitList.value = response.data
  })
  // 电阻单位公用
  getDictByCode('standardResistance').then((response) => {
    standardResistanceList.value = response.data
  })
  // 频率单位公用
  getDictByCode('standardFrequencyUnit').then((response) => {
    standardFrequencyUnitList.value = response.data
  })
}

getDict()
// -------定义数据--------------
interface columnsCheckInfo {
  text: string
  show: boolean
}
const columnsChecked: Ref<columnsCheckInfo[]> = ref([])
const table = ref<InstanceType<typeof ElTable>>()
const singleChecked = ref('') // 单选选中id
// 初始化列显示状态
function initColumnsState() {
  columnsChecked.value = []
  for (const column of props.columns) {
    columnsChecked.value.push({ text: column.text, show: !!column.show })
  }
}

// 最终展示列
const columnsFiltered: Ref<TableColumn[]> = ref([])
// 切换列
function changeColumns() {
  columnsFiltered.value = []
  for (const i in props.columns) {
    if (columnsChecked.value[i].show === true) {
      columnsFiltered.value.push(props.columns[i])
    }
  }
}
// 刷新
function refresh() {
  emit('change')
}

// 点击行
function rowClick(row: object, column?: any, event?: any) {
  emit('rowClick', row)
}
// 双击行
function rowDbClick(row: object, column?: any, event?: any) {
  emit('rowDbClick', row)
}
// 监听columns
watch(props.columns, (val) => {
  initColumnsState()
  changeColumns()
})
// 多选
const selectList = ref([])
const handleSelectionChange = (val: any) => {
  selectList.value = val
  emit('selectionChange', val)
}
// 清除多选选中
const clearMulti = () => {
  console.log('清理选中')
  table.value!.clearSelection()
  singleChecked.value = ''
}

// --------------------------------选择设备-------------------------------------------
const selectEquipmentDialogRef = ref() // 选择设备组件ref
const selectIndex = ref()
// 添加
const selectEquipment = (index: number) => {
  selectEquipmentDialogRef.value.initDialog()
  selectIndex.value = index
}

// 确定选择设备
const confirmSelectEquipment = (list: any) => {
  if (list && list.length) {
    const equipmentInfo = {
      equipmentId: list[0].equipmentId, //	配套设备id
      equipmentName: list[0].equipmentName, //	探头设备名称
      manufactureNo: list[0].manufactureNo, //	探头出厂编号
      model: list[0].model, //	探头规格型号
    }
    emit('confirmSelectedEquipment', equipmentInfo, selectIndex.value)
  }
}

// -------------------------------------参考点相关--------------------------------------------
const selectReferencePoint = (val: number, row: any, index: number) => {
  emit('selectReferencePoint', val, row, index)
}
const changeSelectTypeValue = (val: string, row: any, index: number) => {
  emit('changeSelectTypeValue', val, row, index)
}
// --------------------------------------------------------------------------------------
defineExpose({
  clearMulti, initColumnsState,
})
onBeforeMount(() => {
  initColumnsState()
  changeColumns()
})
// ---------------------------------表格操作---------------------------------
const randomNum = `${new Date().getTime}${Math.random()}`
// 右击当前行操作
const clickIndex = ref(-1)
const contextmenu = (row: any, column: any, event: any, index: number) => {
  if (props.pageType === 'detail') { return }
  // 阻止默认的右键菜单
  event.preventDefault()
  clickIndex.value = props.data.findIndex(item => item === row)
  // console.log('右击', clickIndex.value)
  // 获取自定义菜单元素
  var menu = document.getElementById(randomNum) as HTMLElement
  // 设置自定义菜单的位置并显示
  let positionX = event.clientX
  let positionY = event.clientY
  if (window.innerHeight - event.clientY < 268) {
    positionY = window.innerHeight - 268
  }
  else {
    positionY = event.clientY
  }
  if (window.innerWidth - event.clientX < 146) {
    positionX = window.innerWidth - 146
  }
  else if (event.clientX - 180 < 146) {
    positionX = 180
  }
  else {
    positionX = event.clientX - 146 / 2
  }
  menu.style.top = `${positionY}px`
  menu.style.left = `${positionX}px`
  menu.style.display = 'block'
}
// 点击其他位置隐藏自定义菜单
document.addEventListener('click', () => {
  if (props.pageType === 'detail') { return }
  if (document.getElementById(randomNum)) {
    (document.getElementById(randomNum) as HTMLElement).style.display = 'none'
  }
})
const mouseoutTable = () => {
  console.log('鼠标移出')
  if (props.pageType === 'detail') { return }
  if (document.getElementById(randomNum)) {
    (document.getElementById(randomNum) as HTMLElement).style.display = 'none'
  }
}
// 添加行
const costomAddRow = (type: string) => {
  if (type === 'current-pre') {
    // 当前行前方插入
    props.data.splice(clickIndex.value, 0, JSON.parse(JSON.stringify({ ...props.data[clickIndex.value], id: `custom-${new Date().getTime()}` })))
  }
  else if (type === 'current-next') {
    // 当前行后方方插入
    props.data.splice(clickIndex.value + 1, 0, JSON.parse(JSON.stringify({ ...props.data[clickIndex.value], id: `custom-${new Date().getTime()}` })))
  }
  else if (type === 'list-head') {
    // 列表头行插入
    props.data.splice(0, 0, JSON.parse(JSON.stringify({ ...props.data[clickIndex.value], id: `custom-${new Date().getTime()}` })))
  }
  else if (type === 'list-tail') {
    // 列表尾行插入
    props.data.splice(props.data.length, 0, JSON.parse(JSON.stringify({ ...props.data[clickIndex.value], id: `custom-${new Date().getTime()}` })))
  }
  else if (type === 'select-pre') {
    // 选中行前方插入
    if (!selectList.value.length) {
      ElMessage.warning('未选择数据')
      return
    }
    selectList.value.forEach((item, index) => {
      const dataIndex = props.data.findIndex(citem => item === citem)
      props.data.splice(dataIndex, 0, JSON.parse(JSON.stringify({ ...item, id: `custom-${new Date().getTime()}` })))
    })
    table.value!.clearSelection()
  }
  else if (type === 'select-next') {
    // 选中行后方插入
    if (!selectList.value.length) {
      ElMessage.warning('未选择数据')
      return
    }
    selectList.value.forEach((item, index) => {
      const dataIndex = props.data.findIndex(citem => item === citem)
      props.data.splice(dataIndex + 1, 0, JSON.parse(JSON.stringify({ ...item, id: `custom-${new Date().getTime()}` })))
    })
    table.value!.clearSelection()
  }
  else if (type === 'del-current') {
    props.data.splice(clickIndex.value, 1)
  }
  else if (type === 'del-select') {
    if (!selectList.value.length) {
      ElMessage.warning('未选择数据')
      return
    }
    selectList.value.forEach((item, index) => {
      const dataIndex = props.data.findIndex(citem => item === citem)
      props.data.splice(dataIndex, 1)
    })
    table.value!.clearSelection()
  }
  clickIndex.value = -1
}
</script>

<template>
  <div @mouseleave="mouseoutTable">
    <el-table
      id="print"
      ref="table"
      :data="data"
      :height="data.length > 10 ? 500 : null"
      border
      stripe
      :size="size"
      style="width: 100%;"
      @selection-change="handleSelectionChange"
      @row-click="rowClick"
      @row-dblclick="rowDbClick"
      @row-contextmenu="contextmenu"
    >
      <el-table-column v-if="pageType !== 'detail'" type="selection" width="38" />
      <el-table-column align="center" label="序号" width="80" type="index" />
      <el-table-column
        v-for="item in columns"
        :key="item.value"
        :prop="item.value"
        :label="item.text"
        :width="item.width"
        align="center"
      >
        <template #header>
          <span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span>
        </template>
        <template #default="scope">
          <!-- 循环次数 -->
          <!-- <el-input-number
          v-if="item.value === 'cycleNumber' && pageType !== 'detail'"
          v-model="scope.row[item.value]"
          :placeholder="`${item.text}`"
          :step="1"
          :precision="0"
          disabled
          class="full-width-input"
        /> -->
          <!-- 核查类型 -->
          <!-- <el-select v-if="props.pageType !== 'detail' && item.value === 'checkType'" v-model="scope.row[item.value]" disabled clearable multiple placeholder="请选择">
          <el-option
            v-for="item in checkTypeList"
            :key="item.value"
            :label="item.name"
            :value="item.value"
          />
        </el-select> -->
          <!-- 最大允许误差的绝对值 -->
          <div v-if="item.value === 'maximumErrorAbsolute'" style="display: flex;align-items: center;justify-content: center;">
            <precision-input-number
              v-if="props.pageType !== 'detail'"
              v-model="scope.row[item.value]"
              :placeholder="`${item.text}`"
              class="full-width-input"
              controls-position="right"
              :disabled="props.pageType === 'detail'"
            />
            <span v-if="props.pageType === 'detail'">{{ scope.row[item.value] }}</span>
            <!-- 时间单位  -->
            <el-select
              v-if="props.pageType !== 'detail' && props.type === '时标'"
              v-model="scope.row.maximumErrorAbsoluteUnit"
              :disabled="props.pageType === 'detail'"
              style="margin-left: 10px;width: 100px;"
            >
              <el-option v-for="item of standardTimeUnitList" :key="item.value" :label="item.name" :value="item.name" />
            </el-select>
            <!-- 电压公用单位 -->
            <el-select
              v-if="props.pageType !== 'detail' && (props.type !== '时标' && props.type !== '输入阻抗' && props.type !== '稳幅正弦信号电压平坦度')"
              v-model="scope.row.maximumErrorAbsoluteUnit"
              :placeholder="`${item.text}`"
              :disabled="props.pageType === 'detail'"
              style="margin-left: 10px;width: 100px;"
            >
              <el-option v-for="item of standardVoltageList" :key="item.value" :label="item.name" :value="item.name" />
            </el-select>

            <!-- 电阻单位公用 -->
            <el-select
              v-if="props.pageType !== 'detail' && props.type === '输入阻抗'"
              v-model="scope.row.maximumErrorAbsoluteUnit"
              :placeholder="`${item.text}`"
              :disabled="props.pageType === 'detail'"
              style="margin-left: 10px;width: 100px;"
            >
              <el-option v-for="item of standardResistanceList" :key="item.value" :label="item.name" :value="item.name" />
            </el-select>

            <div v-if="props.type === '稳幅正弦信号电压平坦度'" :class="pageType === 'detail' ? 'unit-class' : 'unit-class-margin-left'">
              {{ scope.row.maximumErrorAbsoluteUnit }}
            </div>
            <div v-if="props.pageType === 'detail' && props.type !== '稳幅正弦信号电压平坦度'">
              {{ scope.row.maximumErrorAbsoluteUnit }}
            </div>
          </div>

          <!-- 技术指标  -->
          <div v-if="item.value === 'technicalIndex'" style="display: flex;align-items: center;justify-content: center;">
            <el-select
              v-if="props.pageType !== 'detail'"
              v-model="scope.row.technicalIndexSymbol"
              :disabled="props.pageType === 'detail'"
              style="margin-right: 10px;width: 100px;"
            >
              <el-option v-for="item of standardTechnicalIndexSymbolList" :key="item.value" :label="item.name" :value="item.name" />
            </el-select>
            <span v-if="props.pageType === 'detail'">{{ scope.row.technicalIndexSymbol }}</span>
            <precision-input-number
              v-if="props.pageType !== 'detail'"
              v-model="scope.row[item.value]"
              :placeholder="`${item.text}`"
              class="full-width-input"
              controls-position="right"
              :disabled="props.pageType === 'detail'"
            />
            <span v-if="props.pageType === 'detail'">{{ scope.row[item.value] }}</span>
            <!-- 时间 单位  -->
            <el-select
              v-if="props.type === '上升时间' && props.pageType !== 'detail'"
              v-model="scope.row.technicalIndexUnit"
              :disabled="props.pageType === 'detail'"
              style="margin-left: 10px;width: 130px;"
            >
              <el-option v-for="item of standardTimeUnitList" :key="item.value" :label="item.name" :value="item.name" />
            </el-select>
            <span v-if="props.pageType === 'detail'">{{ scope.row.technicalIndexUnit }}</span>
          </div>

          <!-- 时标--核查点 -->
          <select-by-dict
            v-if="props.type === '时标' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model:model-value="scope.row[item.value]"
            placeholder="核查点"
            dict-code="standard13TimeMarkCheckPoint"
          />
          <!-- 方波电压(50Ω)--核查点 -->
          <select-by-dict
            v-if="props.type === '方波电压(50Ω)' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model:model-value="scope.row[item.value]"
            placeholder="核查点"
            dict-code="standard13Voltage50CheckPoint"
          />
          <!-- 方波电压(1MΩ)--核查点 -->
          <select-by-dict
            v-if="props.type === '方波电压(1MΩ)' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model:model-value="scope.row[item.value]"
            placeholder="核查点"
            dict-code="standard13Voltage1MCheckPoint"
          />
          <!-- 直流电压(50Ω)--核查点 -->
          <select-by-dict
            v-if="props.type === '直流电压(50Ω)' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model:model-value="scope.row[item.value]"
            placeholder="核查点"
            dict-code="standard13DirectVoltage50CheckPoint"
          />
          <!-- 直流电压(1MΩ)--核查点 -->
          <select-by-dict
            v-if="props.type === '直流电压(1MΩ)' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model:model-value="scope.row[item.value]"
            placeholder="核查点"
            dict-code="standard13DirectVoltage1MCheckPoint"
          />

          <!-- 输入阻抗--核查点 -->
          <select-by-dict
            v-if="props.type === '输入阻抗' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model:model-value="scope.row[item.value]"
            placeholder="核查点"
            dict-code="standard13InputImpedance"
          />

          <!-- 稳幅正弦信号电压平坦度类型 -->
          <el-select v-if="props.pageType !== 'detail' && item.value === 'typeValue'" v-model="scope.row[item.value]" :disabled="props.pageType === 'detail'" clearable placeholder="请选择" @change="(val: any) => changeSelectTypeValue(val, scope.row, scope.$index)">
            <el-option
              v-for="item in typeValueList"
              :key="item.value"
              :label="item.name"
              :value="item.name"
            />
          </el-select>

          <!-- 电压公用单位 -->
          <el-select
            v-if="props.pageType !== 'detail' && (item.value === 'unit' && props.type !== '时标' && props.type !== '输入阻抗' && props.type !== '稳幅正弦信号电压平坦度')"
            v-model="scope.row[item.value]"
            :placeholder="`${item.text}`"
            :disabled="props.pageType === 'detail'"
            class="full-width-input"
          >
            <el-option v-for="item of standardVoltageList" :key="item.value" :label="item.name" :value="item.name" />
          </el-select>

          <!-- 时间单位--公用 -->
          <el-select
            v-if="props.pageType !== 'detail' && (item.value === 'unit' && props.type === '时标')"
            v-model="scope.row[item.value]"
            :placeholder="`${item.text}`"
            :disabled="props.pageType === 'detail'"
            class="full-width-input"
          >
            <el-option v-for="item of standardTimeUnitList" :key="item.value" :label="item.name" :value="item.name" />
          </el-select>

          <!-- 电阻单位公用 -->
          <el-select
            v-if="props.pageType !== 'detail' && (item.value === 'unit' && props.type === '输入阻抗')"
            v-model="scope.row[item.value]"
            :placeholder="`${item.text}`"
            :disabled="props.pageType === 'detail'"
            class="full-width-input"
          >
            <el-option v-for="item of standardResistanceList" :key="item.value" :label="item.name" :value="item.name" />
          </el-select>

          <!-- 频率单位公用 -->
          <el-select
            v-if="props.pageType !== 'detail' && (item.value === 'unit' && props.type === '稳幅正弦信号电压平坦度')"
            v-model="scope.row[item.value]"
            :placeholder="`${item.text}`"
            :disabled="props.pageType === 'detail'"
            class="full-width-input"
          >
            <el-option v-for="item of standardFrequencyUnitList" :key="item.value" :label="item.name" :value="item.name" />
          </el-select>

          <!-- 核查点--稳幅正弦信号电压平坦度 -->
          <precision-input-number
            v-if="props.type === '稳幅正弦信号电压平坦度' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model="scope.row[item.value]"
            clearable
            :placeholder="item.text"
            class="full-width-input"
            :disabled="props.pageType === 'detail'"
          />

          <!-- 是否为参考点--稳幅正弦信号电压平坦度 -->
          <el-radio-group v-if="props.type === '稳幅正弦信号电压平坦度' && props.pageType !== 'detail' && item.value === 'referencePoint'" v-model="scope.row[item.value]" :disabled="pageType === 'detail'" @change="(val: any) => selectReferencePoint(val, scope.row, scope.$index)">
            <el-radio :label="1">
              是
            </el-radio>
            <el-radio :label="0">
              否
            </el-radio>
          </el-radio-group>
          <span v-if="props.type === '稳幅正弦信号电压平坦度' && props.pageType === 'detail' && item.value === 'referencePoint'">{{ scope.row.referencePoint === 1 ? '是' : '否' }}</span>
          <!-- 快沿 -->
          <precision-input-number
            v-if="props.type === '上升时间' && props.pageType !== 'detail' && item.value === 'checkPoint'"
            v-model="scope.row[item.value]"
            clearable
            :placeholder="item.text"
            class="full-width-input"
            :disabled="props.pageType === 'detail'"
          />
          <!-- 探头出厂编号 -->
          <el-input
            v-if="props.pageType !== 'detail' && item.value === 'manufactureNo'"
            v-model="scope.row[item.value]"
            placeholder="请选择"
            disabled
          >
            <template v-if="props.pageType !== 'detail'" #append>
              <el-button size="small" @click="selectEquipment(scope.$index)">
                选择
              </el-button>
            </template>
          </el-input>
        </template>
      </el-table-column>
    </el-table>
    <!-- 选择设备台账 -->
    <select-equipment-dialog ref="selectEquipmentDialogRef" @confirm="confirmSelectEquipment" />
    <!-- 自定义菜单 -->
    <div :id="randomNum" class="custom-menu">
      <p class="menu-item" @click="costomAddRow('current-pre')">
        当前行前方插入
      </p>
      <p class="menu-item" @click="costomAddRow('current-next')">
        当前行后方插入
      </p>
      <p class="menu-item" @click="costomAddRow('list-head')">
        列表头行插入
      </p>
      <p class="menu-item" @click="costomAddRow('list-tail')">
        列表尾行插入
      </p>
      <p v-if="pageType !== 'detail'" class="menu-item" @click="costomAddRow('select-pre')">
        选中行前方插入
      </p>
      <!--  -->
      <p v-if="pageType !== 'detail'" class="menu-item" @click="costomAddRow('select-next')">
        选中行后方插入
      </p>
      <p class="menu-item" @click="costomAddRow('del-current')">
        删除当前行
      </p>
      <p v-if="pageType !== 'detail'" class="menu-item" @click="costomAddRow('del-select')">
        删除选中行
      </p>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.custom-menu {
  display: none;
  position: fixed;
  background-color: #fff;
  border-radius: 5px;
  padding: 5px 0;
  z-index: 1000;
  border: 1px solid #c8c9cc;
  box-shadow: 0 0 12px rgb(0 0 0 / 12%);

  .menu-item {
    display: flex;
    align-items: center;
    white-space: nowrap;
    list-style: none;
    line-height: 22px;
    padding: 5px 16px;
    margin: 0;
    // font-size: var(--el-font-size-base);
    color: #606266;
    cursor: pointer;
    outline: none;

    &:hover {
      background-color: #ecf5ff;
      color: #409eff;
    }
  }
}

.single-table {
  width: 100%;

  :deep(.el-table th.el-table__cell:nth-child(1) .cell) {
    visibility: hidden;
  }
}

.unit-class {
  margin-left: 0;
  white-space: nowrap;
}

.unit-class-margin-left {
  margin-left: 10px;
  white-space: nowrap;
}
</style>

<style lang="scss">
.normal-table {
  .el-radio__label {
    display: none !important;
  }
}
</style>