<!-- 第15套:小功率标准装置 --> <script lang="ts" setup name="TemplateDetailFifteenth"> import { ElMessage } from 'element-plus' import type { IList } from './templateDetail-interface' import type { dictType } from '@/global' import { getDictByCode } from '@/api/system/dict' import { calc } from '@/utils/useCalc' import { useCheckList } from '@/commonMethods/useCheckList' import { calculate, recalculate } from '@/api/business/measure/caculate' import { useRound } from '@/commonMethods/useRound' const props = defineProps({ pageType: { type: String, default: 'add', }, itemCategoryName: { type: String, require: true, }, // 设备检定项分类名称 belongStandardEquipment: { // 检校标准装置code type: String, require: true, }, list: { type: Array as any, }, form: { // 检定项表单 type: Object as any, }, itemId: { // 检定项id type: String, default: '', }, }) // eslint-disable-next-line vue/no-dupe-keys const list = ref<IList[]>([]) // 表格数据(上面表格) const checkoutList = ref<IList[]>([]) // 表格多选 const tableLoading = ref(false) // eslint-disable-next-line vue/no-dupe-keys const form = ref({ appearanceFunctionCheck: 1, // 外观检查 calibrationFactor: 1, // 校准因子 }) // ----------------------------------------表头------------------------------------------------ const columns = ref([ { text: '检定项目', value: 'params', align: 'center', required: true }, { text: '频率', value: 'frequency', align: 'center', required: true, width: '180' }, { text: '频率单位', value: 'frequencyUnit', align: 'center', required: true, width: '100' }, { text: 'Kc/%', value: 'kc', align: 'center', required: true, width: '180' }, { text: '标准反射系数ГGe', value: 'standardReflectionCoefficient', align: 'center', required: true, width: '180' }, { text: '被检设备反射系数Гu', value: 'deviceReflectionCoefficient', align: 'center', required: true, width: '180' }, { text: 'U(k=2)', value: 'urel', align: 'center', required: true, width: '180' }, ]) // ------------------------------------------字典---------------------------------------------- const standardFrequencyUnitList = ref<dictType[]>([]) // 频率单位-公用 /** * 获取字典 */ function getDict() { // 频率单位公用 getDictByCode('standardFrequencyUnit').then((response) => { standardFrequencyUnitList.value = response.data }) } getDict() // --------------------------------表格操作--------------------------------------------------- // 多选 const handleSelectionChange = (e: any) => { checkoutList.value = e } /** * 增加行公共方法 * @param list 要操作的数组 * @param title 操作的表格 */ const addRow = (list: IList[], title: string) => { if (checkList()) { if (list.length) { // 增加行时默认上一行数据 list.push({ ...list[list.length - 1], id: `custom-${new Date().getTime()}` }) } else { list.push({ id: `custom-${new Date().getTime()}`, // id,更新/删除使用参数 params: title, itemId: props.itemId, // 检定项id dataType: '1', // 检定项数据类型(一个检定项中区分两个表格)(字典code) frequency: '', // 频率 frequencyUnit: 'MHz', // 频率单位 kc: '', // Kc/% standardReflectionCoefficient: '0.10', // 标准反射系数ГGe deviceReflectionCoefficient: '0.10', // 被检设备反射系数Гu urel: '', // U(k=2) }) } } } /** * 删除行公共方法 * @param checkoutList 选中的数组 * @param list 操作的数组 */ const delRow = (checkoutList: IList[], listParam: IList[]) => { if (!checkoutList.length) { ElMessage.warning('请选中要删除的行') } else { list.value = listParam.filter((item: any) => { return !checkoutList.includes(item) }) } } // ---------------------------------------------校验--------------------------------------------------- // 校验表格(点击保存的时候用) function checkList() { return useCheckList(list.value, columns.value, '检定项表格') } const checkListBeforeSave = () => { if (!list.value.length) { ElMessage.warning('校准因子表格不能为空') return false } if (!checkList()) { return false } return true } // ----------------------------------------------------------------------------------------------------- watch(() => props.list, (newVal) => { // 检定项表格 if (newVal && newVal.length) { list.value = [...newVal] list.value = list.value.map((item: IList) => { return { ...item, params: '校准因子', kc: useRound(item.kc, 3), // 处理小数位数保留 standardReflectionCoefficient: useRound(item.standardReflectionCoefficient, 2), deviceReflectionCoefficient: useRound(item.deviceReflectionCoefficient, 2), } }) as any } }) const $route = useRoute() watch(() => props.form, (newValue) => { const updataOld = $route.query.updataOld as string const isFirstConfig = $route.query.isFirstConfig as string if (newValue && Object.keys(newValue).length && updataOld !== 'true' && isFirstConfig !== 'true') { form.value.appearanceFunctionCheck = newValue.appearanceFunctionCheck // 外观及功能性检查 form.value.calibrationFactor = newValue.calibrationFactor // 校准因子 // form.value.calibrationFactor = 1 // 校准因子 } }, { deep: true, immediate: true }) // ------------------------------------表格操作----------------------------------- const table = ref() 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 } console.log(123) // 阻止默认的右键菜单 event.preventDefault() clickIndex.value = list.value.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') { // 当前行前方插入 list.value.splice(clickIndex.value, 0, JSON.parse(JSON.stringify({ ...list.value[clickIndex.value], id: `custom-${new Date().getTime()}` }))) } else if (type === 'current-next') { // 当前行后方方插入 list.value.splice(clickIndex.value + 1, 0, JSON.parse(JSON.stringify({ ...list.value[clickIndex.value], id: `custom-${new Date().getTime()}` }))) } else if (type === 'list-head') { // 列表头行插入 list.value.splice(0, 0, JSON.parse(JSON.stringify({ ...list.value[clickIndex.value], id: `custom-${new Date().getTime()}` }))) } else if (type === 'list-tail') { // 列表尾行插入 list.value.splice(list.value.length, 0, JSON.parse(JSON.stringify({ ...list.value[clickIndex.value], id: `custom-${new Date().getTime()}` }))) } else if (type === 'select-pre') { // 选中行前方插入 if (!checkoutList.value.length) { ElMessage.warning('未选择数据') return } checkoutList.value.forEach((item, index) => { const dataIndex = list.value.findIndex(citem => item === citem) list.value.splice(dataIndex, 0, JSON.parse(JSON.stringify({ ...item, id: `custom-${new Date().getTime()}` }))) }) table.value!.clearSelection() } else if (type === 'select-next') { // 选中行后方插入 if (!checkoutList.value.length) { ElMessage.warning('未选择数据') return } checkoutList.value.forEach((item, index) => { const dataIndex = list.value.findIndex(citem => item === citem) list.value.splice(dataIndex + 1, 0, JSON.parse(JSON.stringify({ ...item, id: `custom-${new Date().getTime()}` }))) }) table.value!.clearSelection() } else if (type === 'del-current') { list.value.splice(clickIndex.value, 1) } else if (type === 'del-select') { if (!checkoutList.value.length) { ElMessage.warning('未选择数据') return } checkoutList.value.forEach((item, index) => { const dataIndex = list.value.findIndex(citem => item === citem) list.value.splice(dataIndex, 1) }) table.value!.clearSelection() } clickIndex.value = -1 } // 清空配置方法 const clearConfig = () => { list.value = [] } defineExpose({ list, checkListBeforeSave, clearConfig, form }) </script> <template> <div style="padding: 0 10px;"> <el-checkbox v-model="form.appearanceFunctionCheck" :true-label="1" :false-label="0" :disabled="pageType === 'detail'"> 外观及功能性检查 </el-checkbox> <el-checkbox v-model="form.calibrationFactor" :true-label="1" :false-label="0" disabled> 校准因子 </el-checkbox> </div> <detail-block title=" " style="margin-top: 0;padding-top: 0;" @mouseleave="mouseoutTable"> <template v-if="pageType !== 'detail'" #btns> <el-button type="primary" @click="addRow(list, '校准因子')"> 增加行 </el-button> <el-button type="info" @click="delRow(checkoutList, list)"> 删除行 </el-button> </template> <el-table ref="table" :data="list" border :height="list.length > 10 ? 500 : null" style="width: 100%;" @selection-change="handleSelectionChange" @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"> <precision-input-number v-if="pageType !== 'detail' && (item.value === 'kc' || item.value === 'standardReflectionCoefficient' || item.value === 'deviceReflectionCoefficient')" v-model="scope.row[item.value]" :placeholder="`${item.text}`" class="full-width-input" :disabled="props.pageType === 'detail'" :precision="item.value === 'kc' ? 3 : 2" /> <precision-input-number v-if="pageType !== 'detail' && (item.value === 'urel' || item.value === 'frequency')" v-model="scope.row[item.value]" :placeholder="`${item.text}`" class="full-width-input" :disabled="props.pageType === 'detail'" /> <!-- 频率单位公用 --> <el-select v-if="pageType !== 'detail' && item.value === 'frequencyUnit'" 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> </template> </el-table-column> </el-table> <!-- 自定义菜单 --> <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> </detail-block> </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; } } } </style>