| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700 |
- <template>
- <div class="qualityControl">
- <div v-if="!readonly && shiFouGuoShen" class="btn">
- <el-button icon="ibps-icon-edit" @click="onCopy">复制</el-button>
- <el-button type="success" icon="ibps-icon-plus" @click="onAddClick"
- >添加</el-button
- >
- <el-button type="danger" icon="ibps-icon-close" @click="onRemoveClick"
- >删除</el-button
- >
- <el-button icon="ibps-icon-import" @click="onImportClick">导入</el-button>
- <el-button icon="ibps-icon-export" @click="onExportClick">导出</el-button>
- </div>
- <div class="table">
- <el-table
- :data="showPaperList"
- border
- @selection-change="handleSelectionChange"
- >
- <el-table-column type="selection" />
- <el-table-column label="序号" width="50">
- <template slot-scope="{ row, $index }">
- {{ (currentPage - 1) * pageSize + $index + 1 }}</template
- >
- </el-table-column>
- <el-table-column label="选择项目" prop="xuanZeXiangMu" width="200">
- <template slot-scope="{ row }">
- <ibps-custom-dialog
- v-model="row.xuanZeXiangMu"
- template-key="snzkyfxzjbgxzjyxm"
- placeholder="请选择"
- store="id"
- icon="ibps-icon-search-plus"
- type="dialog"
- :disabled="readonly"
- />
- </template>
- </el-table-column>
- <el-table-column label="项目" prop="xiangMu" width="160">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.xiangMu }}</div>
- <el-input
- v-else
- type="textarea"
- autosize
- v-model="row.xiangMu"
- ></el-input>
- </template>
- </el-table-column>
- <!-- <el-table-column label="设备名称" prop="sheBeiMingCheng" width="160">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.sheBeiMingCheng }}</div>
- <el-input v-else v-model="row.sheBeiMingCheng"></el-input
- ></template>
- </el-table-column> -->
- <el-table-column label="质控品厂家" prop="zhiKongChangJia" width="160">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongChangJia }}</div>
- <el-input v-else v-model="row.zhiKongChangJia"></el-input
- ></template>
- </el-table-column>
- <el-table-column label="质控批号" prop="zhiKongPinPiHao" width="100">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongPinPiHao }}</div>
- <el-input v-else v-model="row.zhiKongPinPiHao"></el-input
- ></template>
- </el-table-column>
- <el-table-column
- label="批号开始时间"
- prop="piHaoKaiShiShiJia"
- width="100"
- >
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.piHaoKaiShiShiJia }}</div>
- <el-input v-else v-model="row.piHaoKaiShiShiJia"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="失控规则" prop="shiKongGuiZe" width="100">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.shiKongGuiZe }}</div>
- <el-input v-else v-model="row.shiKongGuiZe"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="单位" prop="zhiKongTuDanWei">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongTuDanWei }}</div>
- <el-input v-else v-model="row.zhiKongTuDanWei"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="设定质控图数据">
- <el-table-column label="水平" prop="zhiKongTuShuiPing">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongTuShuiPing }}</div>
- <el-input v-else v-model="row.zhiKongTuShuiPing"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="均值" prop="zhiKongTuJunZhi">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongTuJunZhi }}</div>
- <el-input v-else v-model="row.zhiKongTuJunZhi"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="SD" prop="zhiKongTuSd">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongTuSd }}</div>
- <el-input v-else v-model="row.zhiKongTuSd"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="CV%" prop="zhiKongTuCv">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zhiKongTuCv }}</div>
- <el-input v-else v-model="row.zhiKongTuCv"></el-input>
- </template>
- </el-table-column>
- </el-table-column>
- <el-table-column label="当月原始测定数据统计">
- <el-table-column label="均值" prop="yuanShiJunZhi">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.yuanShiJunZhi }}</div>
- <el-input v-else v-model="row.yuanShiJunZhi"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="SD" prop="yuanShiSd">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.yuanShiSd }}</div>
- <el-input v-else v-model="row.yuanShiSd"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="CV%" prop="yuanShiCv">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.yuanShiCv }}</div>
- <el-input v-else v-model="row.yuanShiCv"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="测定数" prop="yuanShiN">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.yuanShiN }}</div>
- <el-input v-else v-model="row.yuanShiN"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="失控数" prop="shiKongShu">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.shiKongShu }}</div>
- <el-input v-else v-model="row.shiKongShu"></el-input>
- </template>
- </el-table-column>
- </el-table-column>
- <el-table-column label="当月在控数据统计">
- <el-table-column label="均值" prop="chuJunZhi">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.chuJunZhi }}</div>
- <el-input v-else v-model="row.chuJunZhi"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="SD" prop="chuSd">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.chuSd }}</div>
- <el-input v-else v-model="row.chuSd"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="CV%" prop="chuCv">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.chuCv }}</div>
- <el-input v-else v-model="row.chuCv"></el-input>
- </template>
- </el-table-column>
- </el-table-column>
- <el-table-column label="累积质控数据统计">
- <el-table-column label="均值" prop="leiJunZhi">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.leiJunZhi }}</div>
- <el-input v-else v-model="row.leiJunZhi"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="SD" prop="leiSd">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.leiSd }}</div>
- <el-input v-else v-model="row.leiSd"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="CV%" prop="leiCv">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.leiCv }}</div>
- <el-input v-else v-model="row.leiCv"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="测定数" prop="leiN">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.leiN }}</div>
- <el-input v-else v-model="row.leiN"></el-input>
- </template>
- </el-table-column>
- <el-table-column label="在控率%" prop="zaiKongLv">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.zaiKongLv }}</div>
- <el-input v-else v-model="row.zaiKongLv"></el-input>
- </template>
- </el-table-column>
- </el-table-column>
- <el-table-column label="CV%控制范围">
- <el-table-column label="%" prop="cvKongZhiFanWei">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.cvKongZhiFanWei }}</div>
- <el-input v-else v-model="row.cvKongZhiFanWei"></el-input>
- </template>
- </el-table-column>
- </el-table-column>
- <el-table-column label="是否合格" prop="shiFouHeGe" width="120">
- <template slot-scope="{ row }">
- <div v-if="isReadonly">{{ row.shiFouHeGe }}</div>
- <el-select v-else v-model="row.shiFouHeGe">
- <el-option
- v-for="item in shiFouHeGeOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- >
- </el-option>
- </el-select>
- </template>
- </el-table-column>
- <el-table-column
- v-if="!readonly && shiFouGuoShen"
- label="操作栏位"
- fixed="right"
- >
- <template slot-scope="{ row, $index }">
- <el-button
- type="text"
- icon="ibps-icon-edit"
- @click="onEditClick(row, $index)"
- >编辑</el-button
- >
- </template>
- </el-table-column>
- </el-table>
- <el-pagination
- style="margin-top: 5px; padding-bottom: 10px"
- :current-page="currentPage"
- :page-sizes="[10, 15, 20, 30, 50, 100]"
- :page-size="pageSize"
- layout="total,sizes,prev,pager,next"
- :total="tableData.length"
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- />
- </div>
- <input
- id=""
- ref="file1"
- style="display: none"
- type="file"
- name=""
- accept=".xlsx,.xls"
- @change="handleUploadChange1"
- />
- </div>
- </template>
- <script>
- import IbpsCustomDialog from '@/business/platform/data/templaterender/custom-dialog'
- import { cloneDeep } from 'lodash'
- import xlsx from 'xlsx'
- import fs from 'file-saver'
- import dayjs from 'dayjs'
- export default {
- components: {
- 'ibps-custom-dialog': IbpsCustomDialog
- },
- props: {
- formData: {
- type: Object,
- default: () => {}
- },
- params: {
- type: Object,
- default: () => {}
- },
- readonly: {
- type: Boolean,
- default: false
- }
- },
- data() {
- return {
- tableData: [],
- multipleSelection: [],
- pageSize: 10,
- currentPage: 1,
- isReadonly:
- this.readOnly ||
- this.params.nodeId == 'Activity_1riq0sr' ||
- this.params.nodeId == 'Activity_0q5i1ex',
- columns: {
- xuanZeXiangMu: '选择项目',
- xiangMu: '项目',
- // sheBeiMingCheng: '设备名称',
- zhiKongPinPiHao: '质控批号',
- piHaoKaiShiShiJia: '批号开始时间',
- zhiKongChangJia: '质控品厂家',
- shiKongGuiZe: '失控规则',
- zhiKongTuDanWei: '单位',
- zhiKongTuShuiPing: '设定质控图数据水平',
- zhiKongTuJunZhi: '设定质控图数据均值',
- zhiKongTuSd: '设定质控图数据SD',
- zhiKongTuCv: '设定质控图数据CV%',
- yuanShiJunZhi: '当月原始测定数据统计均值',
- yuanShiSd: '当月原始测定数据统计SD',
- yuanShiCv: '当月原始测定数据统计CV%',
- yuanShiN: '当月原始测定数据统计测定数',
- shiKongShu: '当月原始测定数据统计失控数',
- chuJunZhi: '当月在控数据统计均值',
- chuSd: '当月在控数据统计SD',
- chuCv: '当月在控数据统计CV%',
- leiJunZhi: '累积质控数据统计均值',
- leiSd: '累积质控数据统计SD',
- leiCv: '累积质控数据统计CV%',
- leiN: '累积质控数据统计测定数',
- zaiKongLv: '累积质控数据统计在控率%',
- cvKongZhiFanWei: 'CV%控制范围',
- shiFouHeGe: '是否合格'
- },
- shiFouHeGeOptions: [
- {
- value: '合格',
- label: '合格'
- },
- {
- value: '不合格',
- label: '不合格'
- }
- ]
- }
- },
- computed: {
- // 分页结果
- showPaperList() {
- const start = (this.currentPage - 1) * this.pageSize
- const end = start + this.pageSize
- return this.tableData.slice(start, end)
- },
- shiFouGuoShen() {
- if (
- !this.formData.shiFouGuoShen ||
- this.formData.shiFouGuoShen === '已退回' ||
- this.formData.shiFouGuoShen === '已暂存' ||
- this.formData.shiFouGuoShen === '待编制'
- ) {
- return true
- }
- return false
- }
- },
- watch: {
- 'formData.dlxmsnzkyfxzb': {
- handler(val) {
- if (
- (val && val.length) ||
- (Array.prototype.isPrototypeOf(val) && val.length === 0)
- ) {
- // console.log(this.formData)
- this.tableData = val
- }
- },
- immediate: true
- },
- tableData: {
- handler(val) {
- this.$emit('change-data', 'dlxmsnzkyfxzb', val)
- },
- deep: true
- }
- },
- methods: {
- onCopy() {
- if (this.multipleSelection.length > 0) {
- this.tableData = this.tableData.concat(
- cloneDeep(this.multipleSelection)
- )
- } else {
- this.$message.warning('请选择数据')
- }
- },
- xlsx(json, fields, filename = '.xlsx') {
- // 导出xlsx
- json.forEach((item) => {
- for (const i in item) {
- if (fields.hasOwnProperty(i)) {
- item[fields[i]] = item[i]
- }
- delete item[i] // 删除原先的对象属性
- }
- })
- const sheetName = filename // excel的文件名称
- const wb = xlsx.utils.book_new() // 工作簿对象包含一SheetNames数组,以及一个表对象映射表名称到表对象。XLSX.utils.book_new实用函数创建一个新的工作簿对象。
- const ws = xlsx.utils.json_to_sheet(json, {
- header: Object.values(fields)
- }) // 将JS对象数组转换为工作表。
- wb.SheetNames.push(sheetName)
- wb.Sheets[sheetName] = ws
- const defaultCellStyle = {
- font: { name: 'Verdana', sz: 13, color: 'FF00FF88' },
- fill: { fgColor: { rgb: 'FFFFAA00' } }
- } // 设置表格的样式
- const wopts = {
- bookType: 'xlsx',
- bookSST: false,
- type: 'binary',
- cellStyles: true,
- defaultCellStyle: defaultCellStyle,
- showGridLines: false
- } // 写入的样式
- const wbout = xlsx.write(wb, wopts)
- const blob = new Blob([this.s2ab(wbout)], {
- type: 'application/octet-stream'
- })
- fs.saveAs(blob, filename + '.xlsx')
- },
- s2ab(s) {
- let buf
- if (typeof ArrayBuffer !== 'undefined') {
- buf = new ArrayBuffer(s.length)
- const view = new Uint8Array(buf)
- for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
- return buf
- } else {
- buf = new Array(s.length)
- for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff
- return buf
- }
- },
- handleSelectionChange(val) {
- this.multipleSelection = val
- },
- onAddClick() {
- this.tableData.push({
- xuanZeXiangMu: '',
- oldXiangMu: '',
- xiangMu: '',
- // sheBeiMingCheng: '',
- zhiKongPinPiHao: '',
- piHaoKaiShiShiJia: '',
- zhiKongChangJia: '',
- shiKongGuiZe: '',
- zhiKongTuDanWei: '',
- zhiKongTuShuiPing: '',
- zhiKongTuJunZhi: '',
- zhiKongTuSd: '',
- zhiKongTuCv: '',
- yuanShiJunZhi: '',
- yuanShiSd: '',
- yuanShiCv: '',
- yuanShiN: '',
- shiKongShu: '',
- chuJunZhi: '',
- chuSd: '',
- chuCv: '',
- leiJunZhi: '',
- leiSd: '',
- leiCv: '',
- leiN: '',
- zaiKongLv: '',
- cvKongZhiFanWei: '',
- shiFouHeGe: ''
- })
- },
- onImportClick() {
- // const btn = document.querySelector('.dynamic-form-table .ibps-icon-import')
- // btn.click()
- this.$refs.file1.click()
- console.log('导入')
- },
- /* 读取文件 将文件转换为二进制 */
- readFile(file) {
- return new Promise((resolve) => {
- const reader = new FileReader()
- reader.readAsBinaryString(file)
- reader.onload = (ev) => {
- resolve(ev.target.result)
- }
- })
- },
- // 转换对象的key
- switchDeviceObj(data, originalObj) {
- const result = []
- data.forEach((item) => {
- const obj = {}
- for (const key in originalObj) {
- // 对日期格式的数据做兼容处理
- if (item[originalObj[key]] instanceof Date) {
- obj[key] =
- dayjs(item[originalObj[key]])
- .add(8, 'hour')
- .format('YYYY-MM-DD') || ''
- } else {
- obj[key] = String(item[originalObj[key]] || '')
- }
- }
- result.push(obj)
- })
- return result
- },
- async switchXmToId(list) {
- // const sql = `select id_, jian_yan_xiang_mu from t_nlfwb`
- const { variables: { data = {} } = {} } = await this.$common.request(
- 'query',
- {
- key: 'getNlfwbProject',
- params: [null]
- }
- )
- for (let i = 0; i < list.length; i++) {
- const row = list[i]
- const t = data.find(
- (item) => item.jian_yan_xiang_mu.trim() === row.xiangMu.trim()
- )
- row.xuanZeXiangMu = t?.id_ || ''
- }
- },
- checkDate(data) {
- // 校验日期字段是否符合要求
- const dateRegex = /^(\d{4})[-/](0[1-9]|1[0-2])[-/](0[1-9]|[12]\d|3[01])$/
- for (let i = 0; i < data.length; i++) {
- const row = data[i]
- if (row.piHaoKaiShiShiJia && !dateRegex.test(row.piHaoKaiShiShiJia)) {
- throw new Error(`第${i + 1}行时间格式错误!`)
- }
- }
- },
- async handleUploadChange1(file) {
- try {
- const dataBinary = await this.readFile(file.target.files[0])
- file.target.value = null // 注意上传后要将input的值设为空
- const workBook = xlsx.read(dataBinary, {
- type: 'binary',
- cellDates: true
- })
- const workSheet = workBook.Sheets[workBook.SheetNames[0]]
- const data = xlsx.utils.sheet_to_json(workSheet)
- const importData = this.switchDeviceObj(data, this.columns)
- // console.log(JSON.parse(JSON.stringify(importData)))
- // this.checkDate(importData)
- await this.switchXmToId(importData)
- this.tableData.push(...importData)
- // console.log(JSON.parse(JSON.stringify(this.tableData)))
- } catch (error) {
- this.$message.warning(error?.message || '导入失败')
- }
- },
- getTimeStamp() {
- return dayjs().format('YYYYMMDDHHmmss')
- },
- onExportClick() {
- // const btn = document.querySelector('.dynamic-form-table .ibps-icon-export')
- // btn.click()
- const copyData = JSON.parse(JSON.stringify(this.tableData))
- this.xlsx(
- copyData,
- this.columns,
- '定量项目室内质控月分析表' + this.getTimeStamp()
- )
- this.$message.success('导出成功!')
- },
- onRemoveClick() {
- if (this.multipleSelection.length === 0) {
- return this.$message.warning('请先选择需要删除的数据!')
- }
- this.$confirm('是否确认删除所选项?', '提示', {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning'
- })
- .then(() => {
- this.tableData = this.tableData.filter(
- (item) => !this.multipleSelection.includes(item)
- )
- this.currentPage = 1
- })
- .catch(() => {})
- },
- onEditClick(row, $index) {
- const btns = document.querySelectorAll(
- '.dynamic-form-table .ibps-icon-edit'
- )
- btns[Math.floor(btns.length / 2) + $index].click()
- },
- onPageClick(number) {
- const btns = document.querySelectorAll(
- '.dynamic-form-table .el-pager .number'
- )
- if (btns[0].innerText == this.currentPage) {
- btns[0].click()
- }
- if (btns[1].innerText == this.currentPage) {
- btns[1].click()
- }
- if (btns[2].innerText == this.currentPage) {
- btns[2].click()
- }
- if (btns[3].innerText == this.currentPage) {
- btns[3].click()
- }
- if (btns[4].innerText == this.currentPage) {
- btns[4].click()
- }
- if (btns[5].innerText == this.currentPage) {
- btns[5].click()
- }
- if (btns[6].innerText == this.currentPage) {
- btns[6].click()
- }
- const butprev = document.querySelectorAll(
- '.dynamic-form-table .el-pager .btn-quickprev'
- )
- if (
- this.currentPage < Number(btns[1].innerText) &&
- this.currentPage !== Number(btns[0].innerText)
- ) {
- butprev[0].click()
- }
- const butnext = document.querySelectorAll(
- '.dynamic-form-table .el-pager .btn-quicknext'
- )
- if (
- this.currentPage > Number(btns[5].innerText) &&
- this.currentPage !== Number(btns[6].innerText)
- ) {
- butnext[0].click()
- }
- },
- onSizeClick() {
- const names = document.querySelectorAll(
- '.dynamic-form-table .el-popper .el-select-dropdown__item'
- )
- if (names[0].innerText == this.pageSize + '条/页') {
- names[0].click()
- }
- if (names[1].innerText == this.pageSize + '条/页') {
- names[1].click()
- }
- if (names[2].innerText == this.pageSize + '条/页') {
- names[2].click()
- }
- if (names[3].innerText == this.pageSize + '条/页') {
- names[3].click()
- }
- if (names[4].innerText == this.pageSize + '条/页') {
- names[4].click()
- }
- if (names[5].innerText == this.pageSize + '条/页') {
- names[5].click()
- }
- },
- // 当前页码改变
- handleCurrentChange(val) {
- this.currentPage = val
- this.onPageClick()
- },
- // 页码选择器改变
- handleSizeChange(val) {
- this.pageSize = val
- this.currentPage = 1
- this.onSizeClick()
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .qualityControl {
- margin-top: 20px;
- .btn {
- padding: 0;
- margin-bottom: 4px;
- display: flex;
- justify-content: flex-end;
- .el-button + .el-button {
- margin-left: 6px;
- }
- }
- }
- </style>
|