Newer
Older
xc-business-system / src / views / business / measure / item / components / second / templateTable.vue
<script lang="ts" setup name="NonthTemplateTable">
import type { Ref } from 'vue'
import { 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'

// ------------------定义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条件相同
  // 标题
  title: {
    type: String,
    default: '',
  },
  // 排序
  index: {
    type: String,
    default: '',
  },
  // 按钮展示
  showBtn: {
    type: Boolean,
    default: false,
  },
  // 计算机结果按钮
  calcBtn: {
    type: Boolean,
    default: false,
  },
  // 自定义内容
  customContent: {
    type: Boolean,
    default: false,
  },
  // 下拉框内容
  selectAllList: {
    type: Object,
    default: () => ({}),
  },
  // 是否展示多选列
  isMulti: {
    type: Boolean,
    default: true,
  },
  // 标题
  showTitle: {
    type: Boolean,
    default: false,
  },
})
const emit = defineEmits(['change', 'selectionChange', 'rowClick', 'rowDbClick', 'multiSelect', 'filterChange', 'addRow', 'delRow', 'changeLoadSituationa', 'calculateResult', 'disabled'])
// ------------------------------------------字典----------------------------------------------
// -------定义数据--------------
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 selectionChange(selection: []) {
  emit('selectionChange', selection)
}
// 点击行
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<any[]>([])
// 多选
const handleSelectionChange = (val: any) => {
  selectList.value = val
  emit('selectionChange', val)
}
// 清除多选选中
const clearMulti = () => {
  console.log('清理选中')
  table.value!.clearSelection()
  singleChecked.value = ''
}
// 删除行
const delRow = (selectList: any[], list: any[], title: string) => {
  emit('delRow', selectList, list, title)
}
// 添加行
const addRow = (list: any[], title: string, index: string) => {
  emit('addRow', list, title, index)
}
// 下拉框
const getAnySelect = (text: string, title: string) => {
  return props.selectAllList[text]
}
// 下拉框禁用情况
const disabled = (scope: any, column: any) => {
  let result = false
  emit('disabled', { scope, column }, (value: boolean) => {
    result = value
  })
  return result
}
// 下拉框获取焦点 或者 下拉框的值发生变化
const changeLoadSituationa = (value: any, index: number, text: string, type: string, list: any[], title: string) => {
  emit('changeLoadSituationa', value, index, text, type, list, title)
}
// 计算结果
const calculateResult = (title) => {
  emit('calculateResult', title)
}
// 获取字典value
const getDictValue = (value: string) => {
  console.log(value, 'value')
}
defineExpose({
  clearMulti, initColumnsState,
})
onBeforeMount(() => {
  initColumnsState()
  changeColumns()
})
</script>

<template>
  <detail-block title="">
    <div style="display: flex;justify-content: space-between;">
      <span v-if="props.showTitle" style="padding: 0 10px;">{{ props.title }}</span>
      <!-- 是否可选等一些条件 -->
      <slot name="custom-check" />
      <div style="padding: 0 10px;padding-bottom: 10px;display: flex;">
        <!-- 是否可选等一些条件 -->
        <slot name="custom-right" />
        <el-button v-if="props.showBtn" type="primary" @click="addRow(props.data, props.title, props.index)">
          增加行
        </el-button>
        <el-button v-if="props.showBtn" type="info" @click="delRow(selectList, props.data, props.title)">
          删除行
        </el-button>
        <el-button v-if="props.calcBtn" type="primary" @click="calculateResult(props.title)">
          计算结果
        </el-button>
        <!-- 自定义按钮 -->
        <slot name="custom-btn" />
      </div>
    </div>
    <el-table
      id="print"
      ref="table"
      :data="data"
      :height="height"
      border
      stripe
      :size="size"
      style="width: 100%;"
      @selection-change="handleSelectionChange"
      @row-click="rowClick"
      @row-dblclick="rowDbClick"
    >
      <el-table-column v-if="props.isMulti " 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">
          <div style="display: flex;text-align: center;">
            <!-- 输入框/选择器等  前面插槽 -->
            <slot name="pre-content" :scope="scope" :column="item" />
            <!-- 自定义内容 -->
            <slot v-if="props.customContent" name="custom-content" :scope="scope" :column="item" />
            <template v-if="!props.customContent">
              <!-- 文本内容 -->
              <div v-if="item.type === 'text'" style="text-align: center;width: 100%;">
                {{ scope.row[item.value] }}
              </div>
              <!-- 输入框 -->
              <el-input
                v-if="item.type === 'input'" v-model="scope.row[item.value]"
                :placeholder="`${item.text}`" style="width: 100%;"
                :disabled="disabled(scope, item)"
              />
              <!-- 数字输入框 -->
              <el-input-number
                v-if="item.type === 'number'" v-model="scope.row[item.value]"
                :placeholder="`${item.text}`" style="width: 100%;" controls-position="right"
                :disabled="disabled(scope, item)"
              />
              <!-- 下拉框 -->
              <el-select
                v-if="item.type === 'select'" v-model="scope.row[item.value]"
                :placeholder="`${item.text}`" style="width: 100%;"
                :disabled="disabled(scope, item)"
                @change="(value) => changeLoadSituationa(value, scope.$index, item.text, 'change', props.data, props.title)"
                @focus="(value) => changeLoadSituationa(value, scope.$index, item.text, 'focus', props.data, props.title)"
              >
                <el-option
                  v-for="citem in getAnySelect(item.text, title)"
                  :key="citem.id"
                  :label="citem.name"
                  :value="citem.name"
                />
              </el-select>
              <!-- 输入下拉框(与字典联动) -->
              <select-by-dict
                v-if="item.type === 'select-dict'"
                v-model="scope.row[item.value]"
                :placeholder="`${item.text}`"
                style="width: 100%;"
                :disabled="disabled(scope, item)"
                :dict-code="item.code"
                @get-dict-value="getDictValue"
              />
            </template>
            <!-- 输入框/选择器等  后面插槽 -->
            <slot name="next-content" :scope="scope" :column="item" />
          </div>
        </template>
      </el-table-column>
      <!-- <slot name="custom-column" /> -->
    </el-table>
  </detail-block>
</template>

<style lang="scss" scoped>
.single-table {
  width: 100%;

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

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