Browse Source

导入数据模版

master
songguoqiang 12 months ago
parent
commit
9eec798af5
  1. 14
      src/api/detection/records/index.ts
  2. 4
      src/api/spc/templateItemDetails/index.ts
  3. 548
      src/components/ImportForm/src/DetForm.vue
  4. 241
      src/components/ImportForm/src/DetecImportForm.vue
  5. 6
      src/views/detection/records/index.vue
  6. 12
      src/views/detection/records/records.data.ts
  7. 65
      src/views/detection/recordsDetails/importRecordsDetails.data.ts
  8. 395
      src/views/detection/recordsDetails/index.vue
  9. 2
      src/views/spc/detectiontemplate/detectionTemplate.data.ts
  10. 1
      src/views/spc/itembasic/itembasic.data.ts

14
src/api/detection/records/index.ts

@ -56,6 +56,16 @@ export const exportRecords = async (params) => {
} }
// 下载导入模板 // 下载导入模板
export const importTemplate = () => { export const importTemplate = (itemType:string) => {
return request.download({ url: '/detection/records/get-import-template' }) return request.download({ url: '/detection/records/get-import-template?itemType='+itemType })
}
// 提交导入记录
export const saveRecords = async (id: number) => {
return await request.get({ url: `/detection/records/saveRecords?id=` + id })
}
//每次导入前会传模版id后端会根据模版id和用户id把草稿状态的数据逻辑删除
export const deleteStatus = async (templateId: number) => {
return await request.delete({ url: `/detection/records/deleteStatus?id=` + templateId })
} }

4
src/api/spc/templateItemDetails/index.ts

@ -19,7 +19,9 @@ export interface TemplateItemDetailsVO {
deleterId: string deleterId: string
extraProperties: string extraProperties: string
concurrencyStamp: string concurrencyStamp: string
siteId: string siteId: string,
recodeColumns?:number,
recodeLines?:number,
} }
// 查询检测记录明细列表 // 查询检测记录明细列表
export const getTemplateItemDetailsPage = async (params) => { export const getTemplateItemDetailsPage = async (params) => {

548
src/components/ImportForm/src/DetForm.vue

@ -0,0 +1,548 @@
<template>
<Dialog v-model="dialogVisible" title="导入" width="1200">
<el-form
:inline="true"
:model="queryParams"
class="demo-form-inline"
style="margin-bottom: 10px"
label-width="100px"
>
<el-form-item label="项目" style="width: calc(22%)">
<el-select
v-model="queryParams.proCode"
placeholder="请选择项目"
clearable
style="width: 100%"
@change="detectionProjectChange"
>
<el-option v-for=" (item) in projectList" :key="item" :label="item.name" :value="item.code" />
</el-select>
</el-form-item>
<el-form-item label="物料" style="width: calc(22%)">
<el-select
v-model="queryParams.itemCode"
placeholder="请选择物料"
clearable
style="width: 100%"
@change="detectionItemChange"
>
<el-option v-for=" (item) in itemList" :key="item" :label="item.name" :value="item.code" />
</el-select>
</el-form-item>
<el-form-item label="检测类型" style="width: calc(22%)">
<el-select
v-model="queryParams.detectionType"
placeholder="请选择检测类型"
clearable
style="width: 100%"
@change="detectionTypeChange"
>
<el-option v-for="dict in dictTypeList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item style="width: calc(22%)">
<el-button :disabled="formLoading" type="primary" @click="submitForm">解析校验</el-button>
<el-button @click="dialogVisible = false"> </el-button>
</el-form-item>
</el-form>
<el-upload v-if="false" ref="uploadRef" v-model:file-list="fileList" :action="importUrl + '?mode=' + mode + '&file=' + file + '&updatePart=' + updatePart + '&outFile=' + outFile"
:auto-upload="false" :disabled="formLoading" :headers="uploadHeaders" :limit="1" :on-error="submitFormError"
:on-exceed="handleExceed" :on-success="submitFormSuccess" :accept="accept" drag
style="width:300px;margin:0 auto">
<Icon icon="ep:upload-filled" color="#c0c4cc" size="60" />
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<!-- 列表头部 -->
<TableHead
:HeadButttondata="HeadButttondata"
@button-base-click="buttonBaseClick"
:routeName="routeName"
@updataTableColumns="updataTableColumns"
@searchFormClick="searchFormClick"
:allSchemas="RecordsDetails.allSchemas"
/>
<!-- 列表 -->
<ContentWrap>
<Table
:columns="tableColumns"
:data="tableObject.tableList"
:loading="tableObject.loading"
:pagination="{
total: tableObject.total
}"
v-model:pageSize="tableObject.pageSize"
v-model:currentPage="tableObject.currentPage"
v-model:sort="tableObject.sort"
>
<template #code="{row}">
<el-button type="primary" link @click="openDetail(row, '代码', row.code)">
<span>{{ row.code }}</span>
</el-button>
</template>
<template #action="{ row }">
<ButtonBase :Butttondata="butttondata" @button-base-click="buttonTableClick($event,row)" />
</template>
</Table>
</ContentWrap>
</el-upload>
<template #footer>
<div class="flex items-center">
<div class="flex-1 text-left">
<el-button type="primary" plain @click="importTemplate">
<Icon icon="ep:download" />
下载模板
</el-button>
</div>
<!-- <el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button> -->
</div>
</template>
</Dialog>
</template>
<script setup lang="ts">
import download from '@/utils/download'
import { RecordsDetails,RecordsDetailsRules } from '@/views/detection/recordsDetails/importRecordsDetails.data'
import * as RecordsDetailsApi from '@/api/detection/recordsDetails'
import * as defaultButtons from '@/utils/disposition/defaultButtons'
import * as ProjecAPI from '@/api/spc/project'
import * as ItembasicApi from '@/api/spc/itembasic'
import * as TemplateItemDetailsApi from '@/api/spc/templateItemDetails'
import {formatDate} from '@/utils/formatTime'
defineOptions({ name: 'RecordsDetails' })
const { t } = useI18n() //
const route = useRoute() //
const routeName = ref()
routeName.value = route.name
const tableColumns = ref(RecordsDetails.allSchemas.tableColumns)
//
const updataTableColumns = (val) => {
tableColumns.value = val
}
//
const searchTableParams = ref([
//{
// formField: 'productItemCode',
// searchTableTitle: '',
// searchTableAllSchemas: Itembasic.allSchemas,
// searchTablePage: ItembasicApi.getItembasicPage
//}
])
const { tableObject, tableMethods } = useTable({
getListApi: RecordsDetailsApi.getRecordsDetailsPage //
})
//
const { getList, setSearchParams } = tableMethods
const message = useMessage() //
const dialogVisible = ref(false) //
const formLoading = ref(false) //
const uploadRef = ref()
const uploadHeaders = ref() // Header
const fileList = ref([]) //
const file = ref('')
//
const HeadButttondata = [
defaultButtons.defaultAddBtn({hasPermi:'wms:recordsDetails:create'}), //
defaultButtons.defaultImportBtn({hasPermi:'wms:recordsDetails:import'}), //
defaultButtons.defaultExportBtn({hasPermi:'wms:recordsDetails:export'}), //
defaultButtons.defaultFreshBtn(null), //
defaultButtons.defaultFilterBtn(null), //
defaultButtons.defaultSetBtn(null), //
]
//
const buttonBaseClick = (val, item) => {
if (val == 'add') { //
openForm('create')
} else if (val == 'import') { //
handleImport()
} else if (val == 'export') { //
handleExport()
} else if (val == 'refresh') { //
getList()
} else if (val == 'filtrate') { //
} else { //
console.log('其他按钮', item)
}
}
// -
const butttondata = [
defaultButtons.mainListEditBtn({hasPermi:'wms:recordsDetails:update'}), //
defaultButtons.mainListDeleteBtn({hasPermi:'wms:recordsDetails:delete'}), //
]
// -
const buttonTableClick = async (val, row) => {
if (val == 'edit') { //
openForm('update', row)
} else if (val == 'delete') { //
handleDelete(row.id)
}
}
/** 添加/修改操作 */
const basicFormRef = ref()
const openForm = (type: string, row?: any) => {
basicFormRef.value.open(type, row)
}
//
const searchTableSuccess = (formField, searchField, val, formRef) => {
nextTick(() => {
const setV = {}
setV[formField] = val[0][searchField]
formRef.setValues(setV)
})
}
/** 详情操作 */
const detailRef = ref()
const openDetail = (row: any, titleName: any, titleValue: any) => {
detailRef.value.openDetail(row, titleName, titleValue, 'basicRecordsDetails')
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await RecordsDetailsApi.deleteRecordsDetails(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const exportLoading = ref(false) //
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await RecordsDetailsApi.exportRecordsDetails(setSearchParams)
download.excel(data, '检测记录详细.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 导入 */
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
//
// const importTemplateData = reactive({
// templateUrl: '',
// templateTitle: '.xls'
// })
//
const importSuccess = () => {
getList()
}
//
const searchFormClick = (searchData) => {
tableObject.params = {
isSearch: true,
filters: searchData.filters
}
getList() //
}
/** 初始化 **/
onMounted(async () => {
getList()
})
const queryParams = reactive({
proCode: '',
itemCode: '',
detectionType: '',
detectionItemContentId: null,
ecTab: '1'
})
const uploadOpen=ref(false)
const props = defineProps({
importTemplateData: {
type: Object,
required: true
},
//
accept: {
type: String,
required: false,
default:'.xlsx,.xls'
},
// .1
mode: {
type: Number,
required: false,
default: 1
},
// ,
updateIsDisable: {
type: Boolean,
required: false,
default: false
},
// ,
appendIsDisable: {
type: Boolean,
required: false,
default: false
},
// ,
coverIsDisable: {
type: Boolean,
required: false,
default: false
},
// ,
updatePart: {
type: Boolean,
required: false,
default: false
},
url:{
type: String,
required: false,
},
//
isShowOut: {
type: Boolean,
required: false,
default: false
},
outFile: {
type: Boolean,
required: false,
default: false
},
})
const importTemplateData= ref(props.importTemplateData)
const accept= ref(props.accept)
const mode = ref(props.mode)//.1
const updateIsDisable = ref(props.updateIsDisable)//,
const appendIsDisable = ref(props.appendIsDisable)//,
const coverIsDisable = ref(props.coverIsDisable)//,
const updatePart = ref(props.updatePart)//
const outFile = ref(props.outFile)//
//
const projectList = ref()
//
const itemList = ref()
//
const dictTypeList = ref()
const getProject = async () => {//
const _projectList = await ProjecAPI.selectAllPros()
if (_projectList != null && _projectList.length != 0) {
projectList.value = _projectList
let code = projectList.value[0].code;
queryParams.proCode = code;
await _itemList(code);
}
}
//code
const _itemList =async (projectCode)=>{
itemList.value = []
const _itemList = await ItembasicApi.selectItemsByProjectCode(projectCode);
if (_itemList != null && _itemList.length != 0) {
itemList.value = _itemList
queryParams.itemCode = itemList.value[0].code
dictOptions();
}
}
const dictOptions = async () => {//
dictTypeList.value = []
const dictOptions = await getIntDictOptions(DICT_TYPE.ITEMBASIC_TYPE);
if (dictOptions != null && dictOptions.length != 0) {
dictTypeList.value = dictOptions;
queryParams.detectionType = dictOptions[0].value + ''
uploadOpen.value = true;
}
}
const detectionProjectChange =async ()=>{//
if(queryParams.proCode==''){
queryParams.itemCode=''
queryParams.detectionType=''
itemList.value = [];
dictTypeList.value = [];
uploadOpen.value = false;
}else{
_itemList(queryParams.proCode);
}
}
const detectionTypeChange=async()=>{
if(queryParams.detectionType==''){
uploadOpen.value = false;
}else{
uploadOpen.value = true;
}
}
const detectionItemChange = async ()=>{//
if(queryParams.itemCode==''){
queryParams.detectionType=''
dictTypeList.value = [];
uploadOpen.value = false;
}else{
dictOptions();
uploadOpen.value =true;
}
}
onMounted(()=>{
getProject()
})
const importUrl =
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + props.url
/** 打开弹窗 */
const open = () => {
dialogVisible.value = true
getList() //
setSearchParams({
decRecId:55,
saveStatus:1,
result:"Warning",
});
resetForm()
}
defineExpose({ open }) // open
/** 提交表单 */
const submitForm = async () => {
if (fileList.value.length == 0) {
message.error('请上传文件')
return
}
file.value = fileList.value[0].name
//
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId(),
}
formLoading.value = true
uploadRef.value!.submit()
}
/** 文件上传成功 */
const emits = defineEmits(['success'])
const submitFormSuccess = (response: any) => {
formLoading.value = true
if(response){
if(response.code == 500){
message.error('导入失败')
return;
} else if (response.data.errorCount > 0) {
message.confirm('文件中有部分数据导入失败,是否下载失败数据?').then(() => {
// download.excel(file, 'file_' + new Date().getTime())
// url
// const downloadElement = document.createElement('a')
// console.log(172, import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/' + response.data.errorFile)
// console.log(172, import.meta.env.VITE_BASE_URL + '/admin-api/opt/profile/' + response.data.errorFile)
window.open(import.meta.env.VITE_BASE_URL + '/admin-api/profile/' + response.data.errorFile ,'222')
// downloadElement.setAttribute('href', import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + response.data.errorFile )
//
// downloadElement.click()
})
}
}else{
console.info("response",response);
message.success('导入成功')
}
//
formLoading.value = false
emits('success')
const decRecId = response.data.decRecId;//id
const role = response.data.decRecId;//admin
const waring = response.data.decRecId;//
//dialogVisible.value = false
//
setSearchParams({
decRecId:decRecId,
saveStatus:1,
result:"Warning",
});
uploadOpen.value = false;
}
/** 上传错误提示 */
const submitFormError = (): void => {
message.error('上传失败,请您重新上传!')
formLoading.value = false
}
/** 重置表单 */
const resetForm = () => {
//
formLoading.value = false
uploadRef.value?.clearFiles()
fileList.value = []
}
/** 文件数超出提示 */
const handleExceed = (): void => {
message.error('最多只能上传一个文件!')
}
/** 下载模板操作 */
const importTemplate = () => {
const res = importTemplateData.value.templateUrl
download.excel(res, importTemplateData.value.templateTitle)
}
</script>
<style scoped lang="scss">
.tips {
div {
position: relative;
padding-left: 22px;
&::before {
width: 4px;
height: 4px;
border-radius: 50%;
content: '';
background: #c2c2c2;
position: absolute;
top: 50%;
margin-top: -2px;
left: 4px;
}
}
}
</style>

241
src/components/ImportForm/src/DetecImportForm.vue

@ -1,6 +1,6 @@
<!-- 导入组件 --> <!-- 导入组件 -->
<template> <template>
<Dialog v-model="dialogVisible" title="导入" width="800"> <Dialog v-model="dialogVisible" title="导入" width="1200">
<el-form <el-form
:inline="true" :inline="true"
:model="queryParams" :model="queryParams"
@ -8,7 +8,7 @@
style="margin-bottom: 10px" style="margin-bottom: 10px"
label-width="100px" label-width="100px"
> >
<el-form-item label="项目" style="width: calc(26%)"> <el-form-item label="项目" style="width: calc(22%)">
<el-select <el-select
v-model="queryParams.proCode" v-model="queryParams.proCode"
placeholder="请选择项目" placeholder="请选择项目"
@ -16,10 +16,10 @@
style="width: 100%" style="width: 100%"
@change="detectionProjectChange" @change="detectionProjectChange"
> >
<el-option v-for=" (item) in projectList" :key="item" :label="item.name" :value="item.code" /> <el-option v-for=" (item) in projectList" :key="item" :label="item.code" :value="item.code" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="物料" style="width: calc(26%)"> <el-form-item label="物料" style="width: calc(22%)">
<el-select <el-select
v-model="queryParams.itemCode" v-model="queryParams.itemCode"
placeholder="请选择物料" placeholder="请选择物料"
@ -27,10 +27,10 @@
style="width: 100%" style="width: 100%"
@change="detectionItemChange" @change="detectionItemChange"
> >
<el-option v-for=" (item) in itemList" :key="item" :label="item.name" :value="item.code" /> <el-option v-for=" (item) in itemList" :key="item" :label="item.code" :value="item.code" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="检测类型" style="width: calc(26%)"> <el-form-item label="检测类型" style="width: calc(22%)">
<el-select <el-select
v-model="queryParams.detectionType" v-model="queryParams.detectionType"
placeholder="请选择检测类型" placeholder="请选择检测类型"
@ -41,56 +41,51 @@
<el-option v-for="dict in dictTypeList" :key="dict.value" :label="dict.label" :value="dict.value" /> <el-option v-for="dict in dictTypeList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item style="width: calc(22%)">
<el-button :disabled="formLoading" type="primary" @click="submitForm">解析校验</el-button>
<el-button v-if="!uploadOpen&&isButton" type="primary" @click="saveSubmit"> </el-button>
</el-form-item>
</el-form> </el-form>
<el-upload v-if="uploadOpen" ref="uploadRef" v-model:file-list="fileList" :action="importUrl + '?mode=' + mode + '&file=' + file + '&updatePart=' + updatePart + '&outFile=' + outFile" <el-upload v-if="uploadOpen" ref="uploadRef" v-model:file-list="fileList" :action="importUrl + '?mode=' + mode + '&file=' + file + '&itemCode=' + queryParams.itemCode + '&itemType=' + queryParams.detectionType"
:auto-upload="false" :disabled="formLoading" :headers="uploadHeaders" :limit="1" :on-error="submitFormError" :auto-upload="false" :disabled="formLoading" :headers="uploadHeaders" :limit="1" :on-error="submitFormError"
:on-exceed="handleExceed" :on-success="submitFormSuccess" :accept="accept" drag :on-exceed="handleExceed" :on-success="submitFormSuccess" :accept="accept" drag
style="width:300px;margin:0 auto"> style="width:300px;margin:0 auto">
<Icon icon="ep:upload-filled" color="#c0c4cc" size="60" /> <Icon icon="ep:upload-filled" color="#c0c4cc" size="60" />
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<template #tip> </el-upload>
<div class="el-upload__tip ml--126px mr--80px"> <template v-if="!uploadOpen">
<div class="flex"> <!-- 列表头部 -->
<div class="label h-32px mr-26px color-#acaeb3 font-size-14px w-100px text-right" style="line-height:32px">导入模式</div> <TableHead
<div class=""> @updataTableColumns="updataTableColumns"
<div class="radio"> @searchFormClick="searchFormClick"
<el-radio-group v-model="mode"> :allSchemas="RecordsDetails.allSchemas"
<el-radio :label="1" :disabled="updateIsDisable">更新</el-radio> />
<el-radio :label="2" :disabled="appendIsDisable">追加</el-radio> <!-- 列表 -->
<el-radio :label="3" :disabled="coverIsDisable">覆盖</el-radio> <ContentWrap>
</el-radio-group> <Table
</div> :columns="tableColumns"
:data="tableObject.tableList"
<div class="tips color-#acaeb3 font-size-14px"> :loading="tableObject.loading"
<div class="mt-2">更新新增并修改</div> :pagination="{
<div class="mt-2">追加只新增不修改</div> total: tableObject.total
<div class="mt-2">覆盖只修改不新增</div> }"
</div> v-model:pageSize="tableObject.pageSize"
</div> v-model:currentPage="tableObject.currentPage"
</div> v-model:sort="tableObject.sort"
<div class="flex mt-16px"> >
<div class="label h-32px mr-26px color-#acaeb3 font-size-14px w-100px text-right" style="line-height:32px">部分保存</div> <template #code="{row}">
<div class=""> <el-button type="primary" link @click="openDetail(row, '代码', row.code)">
<div class="switch"> <span>{{ row.code }}</span>
<el-switch v-model="updatePart" /> </el-button>
</div> </template>
<div class="tips color-#acaeb3 font-size-14px"> <template #action="{ row }">
<div class="mt-2">部分保存如存在错误数据正确数据正常导入</div> <ButtonBase :Butttondata="butttondata" @button-base-click="buttonTableClick($event,row)" />
<div class="mt-2">全部保存全部数据正确才能导入</div>
</div>
</div>
</div>
<div class="flex mt-16px" v-if="isShowOut">
<div class="label h-32px mr-26px color-#acaeb3 font-size-14px w-100px text-right" style="line-height:32px">是否外部资源</div>
<div class="">
<div class="switch">
<el-switch v-model="outFile" />
</div>
</div>
</div>
</div>
</template> </template>
</el-upload> </Table>
</ContentWrap>
</template>
<template #footer> <template #footer>
<div class="flex items-center"> <div class="flex items-center">
<div class="flex-1 text-left"> <div class="flex-1 text-left">
@ -99,8 +94,8 @@
下载模板 下载模板
</el-button> </el-button>
</div> </div>
<el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button> <!-- <el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button> -->
</div> </div>
</template> </template>
</Dialog> </Dialog>
@ -108,7 +103,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getAccessToken, getTenantId } from '@/utils/auth' import { getAccessToken, getTenantId } from '@/utils/auth'
import download from '@/utils/download' import download from '@/utils/download'
defineOptions({ name: 'ImportForm' }) defineOptions({ name: 'ImportForm' })
import * as ZlnalysisAPI from '@/api/tjanalysis/zlanalysis' import * as ZlnalysisAPI from '@/api/tjanalysis/zlanalysis'
import * as ProjecAPI from '@/api/spc/project' import * as ProjecAPI from '@/api/spc/project'
@ -116,7 +110,32 @@ import * as ItembasicApi from '@/api/spc/itembasic'
import * as TemplateItemDetailsApi from '@/api/spc/templateItemDetails' import * as TemplateItemDetailsApi from '@/api/spc/templateItemDetails'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import {formatDate} from '@/utils/formatTime' import {formatDate} from '@/utils/formatTime'
import { RecordsDetails } from '@/views/detection/recordsDetails/importRecordsDetails.data'
import * as RecordsDetailsApi from '@/api/detection/recordsDetails'
import * as RecordsApi from '@/api/detection/records'
import * as defaultButtons from '@/utils/disposition/defaultButtons'
const tableColumns = ref(RecordsDetails.allSchemas.tableColumns)
//
const updataTableColumns = (val) => {
tableColumns.value = val
}
//
const searchTableParams = ref([
//{
// formField: 'productItemCode',
// searchTableTitle: '',
// searchTableAllSchemas: Itembasic.allSchemas,
// searchTablePage: ItembasicApi.getItembasicPage
//}
])
const { tableObject, tableMethods } = useTable({
getListApi: RecordsDetailsApi.getRecordsDetailsPage //
})
//
const { getList, setSearchParams } = tableMethods
const message = useMessage() // const message = useMessage() //
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
@ -242,7 +261,6 @@ const dictOptions = async () => {//获取物料类型
if (dictOptions != null && dictOptions.length != 0) { if (dictOptions != null && dictOptions.length != 0) {
dictTypeList.value = dictOptions; dictTypeList.value = dictOptions;
queryParams.detectionType = dictOptions[0].value + '' queryParams.detectionType = dictOptions[0].value + ''
uploadOpen.value = true;
} }
} }
@ -252,8 +270,9 @@ const dictOptions = async () => {//获取物料类型
queryParams.itemCode='' queryParams.itemCode=''
queryParams.detectionType='' queryParams.detectionType=''
itemList.value = []; itemList.value = [];
_itemList("");
dictTypeList.value = []; dictTypeList.value = [];
uploadOpen.value = false; //uploadOpen.value = false;
}else{ }else{
_itemList(queryParams.proCode); _itemList(queryParams.proCode);
} }
@ -261,9 +280,18 @@ const dictOptions = async () => {//获取物料类型
const detectionTypeChange=async()=>{ const detectionTypeChange=async()=>{
if(queryParams.detectionType==''){ if(queryParams.detectionType==''){
uploadOpen.value = false; //uploadOpen.value = false;
}else{ }else{
uploadOpen.value = true; if(queryParams.detectionType=='GLOSS'){//
importUrl.value = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + "/detection/records/importGZAndXN"
}else if(queryParams.detectionType=='PROPERTY'){//
importUrl.value = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + "/detection/records/importGZAndXN"
}else if(queryParams.detectionType=='DIMENSION'){//
importUrl.value = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + "/detection/records/importCC"
}else{
importUrl.value=import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + "/detection/records/importColor"
}
} }
} }
@ -274,27 +302,56 @@ const dictOptions = async () => {//获取物料类型
uploadOpen.value = false; uploadOpen.value = false;
}else{ }else{
dictOptions(); dictOptions();
uploadOpen.value =true;
} }
} }
onMounted(()=>{ onMounted(()=>{
getProject() getProject()
}) })
const importUrl = //
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + props.url const importUrl = ref(import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + "/detection/records/importColor");
//
const searchFormClick = (searchData) => {
tableObject.params = {
isSearch: true,
filters: searchData.filters
}
getList() //
}
/** 打开弹窗 */ /** 打开弹窗 */
const open = () => { const open = () => {
console.log(111) uploadOpen.value = true;
dialogVisible.value = true dialogVisible.value = true
//getList() //
// setSearchParams({
// decRecId:55,
// saveStatus:1,
// result:"Warning",
// });
resetForm() resetForm()
} }
defineExpose({ open }) // open defineExpose({ open }) // open
const decRecId = ref();//id
const isButton = ref(true);//
const problem = ref(false);//
/** 提交表单 */ /** 提交表单 */
const submitForm = async () => { const submitForm = async () => {
console.info("queryParams",queryParams);
if(queryParams.itemCode==''){
message.warning("请选择物料编码");
return;
}
if(queryParams.detectionType==''){
message.warning("请选择物料类型");
return;
}
//await RecordsApi.deleteRecords(1221);
if (fileList.value.length == 0) { if (fileList.value.length == 0) {
message.error('请上传文件') message.error('请上传文件')
return return
@ -331,44 +388,45 @@ const submitFormSuccess = (response: any) => {
}) })
} }
}else{ }else{
console.info("response",response);
message.success('导入成功') message.success('导入成功')
}
// if (response.code !== 0) {
// message.error(response.msg)
// formLoading.value = false
// return
// }
// //
// const data = response.data
// const create = response.data.importResult[0]
// const update = response.data.importResult[1]
// const failure = response.data.importResult[2]
// let text = '' + data[create].length + ';'
// for (let name of data[create]) {
// text += '< ' + name + ' >'
// }
// text += '' + data[update].length + ';'
// for (const name of data[update]) {
// text += '< ' + name + ' >'
// }
// text += '' + Object.keys(data[failure]).length + ';'
// for (const name in data[failure]) {
// text += '< ' + name + ': ' + data[failure][name] + ' >'
// }
// message.alert(text)
}
resetForm();
// //
formLoading.value = false formLoading.value = false
emits('success') emits('success')
dialogVisible.value = false problem.value = response.data.problem
let messages = response.data.message
if(problem.value){//0
message.warning(messages);
return;
}
decRecId.value= response.data.decRecId;//id
isButton.value = response.data.button;//
isButton.value=true;
//dialogVisible.value = false
//
setSearchParams({
decRecId:decRecId,
saveStatus:1,
result:"NG",
});
uploadOpen.value = false;
} }
/** 上传错误提示 */ /** 上传错误提示 */
const submitFormError = (): void => { const submitFormError = (): void => {
message.error('上传失败,请您重新上传!') message.error('上传失败,请您重新上传!')
formLoading.value = false formLoading.value = false
} }
//
const saveSubmit = async () => {
await RecordsApi.saveRecords(decRecId.value);
dialogVisible.value =false
emits('success')
}
/** 重置表单 */ /** 重置表单 */
const resetForm = () => { const resetForm = () => {
@ -384,10 +442,11 @@ const handleExceed = (): void => {
} }
/** 下载模板操作 */ /** 下载模板操作 */
const importTemplate = () => { const importTemplate =async() => {
const res = importTemplateData.value.templateUrl const res = await RecordsApi.importTemplate(queryParams.detectionType);
download.excel(res, importTemplateData.value.templateTitle) download.excel(res,"模版下载")
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

6
src/views/detection/records/index.vue

@ -63,7 +63,7 @@
/> />
<!-- 导入 --> <!-- 导入 -->
<DetecImportForm ref="importFormRef" url="/detection/records/import" :importTemplateData="importTemplateData" @success="importSuccess" /> <detec-import-form ref="importFormRef" url="/detection/records/import" :importTemplateData="importTemplateData" @success="importSuccess" />
</template> </template>
@ -257,8 +257,8 @@ const searchFormClick = (searchData) => {
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
getList() getList();
importTemplateData.templateUrl = await RecordsApi.importTemplate() //importTemplateData.templateUrl = await RecordsApi.importTemplate()
}) })
</script> </script>

12
src/views/detection/records/records.data.ts

@ -82,12 +82,12 @@ export const Records = useCrudSchemas(reactive<CrudSchema[]>([
} }
}, },
}, },
{ // {
label: '检测结果', // label: '检测结果',
field: 'result', // field: 'result',
sort: 'custom', // sort: 'custom',
isSearch: false, // isSearch: false,
}, // },
// { // {
// label: '备注', // label: '备注',
// field: 'remark', // field: 'remark',

65
src/views/detection/recordsDetails/importRecordsDetails.data.ts

@ -0,0 +1,65 @@
import type { CrudSchema } from '@/hooks/web/useCrudSchemas'
import { dateFormatter } from '@/utils/formatTime'
export const RecordsDetails = useCrudSchemas(reactive<CrudSchema[]>([
{
label: '检测内容',
field: 'contents',
isSearch: true,
isTable:true,
},
{
label: '检测值',
field: 'detectValue',
isSearch: false,
isTable:true,
},
{
label: '检测结果',
field: 'result',
isSearch: false,
isTable:true,
},
{
label: '上限',
field: 'upLimit',
isSearch: false,
isTable:false,
},
{
label: '下限',
field: 'downLimit',
isSearch: false,
isTable:false,
},
{
label: '行号',
field: 'recodeLines',
isSearch: false,
isTable:true,
},
{
label: '列号',
field: 'recodeColumns',
isSearch: false,
isTable:true,
},
{
label: '创建时间',
field: 'createTime',
formatter: dateFormatter,
isSearch: true,
isTable:true,
search: {
component: 'DatePicker',
componentProps: {
valueFormat: 'YYYY-MM-DD HH:mm:ss',
type: 'daterange',
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
}
},
isForm: false
}
]))

395
src/views/detection/recordsDetails/index.vue

@ -1,10 +1,59 @@
<template> <template>
<ContentWrap> <Dialog v-model="dialogVisible" title="导入" width="1200">
<!-- 搜索工作栏 --> <el-form
<Search :schema="RecordsDetails.allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" /> :inline="true"
</ContentWrap> :model="queryParams"
class="demo-form-inline"
style="margin-bottom: 10px"
label-width="100px"
>
<el-form-item label="项目" style="width: calc(22%)">
<el-select
v-model="queryParams.proCode"
placeholder="请选择项目"
clearable
style="width: 100%"
@change="detectionProjectChange"
>
<el-option v-for=" (item) in projectList" :key="item" :label="item.name" :value="item.code" />
</el-select>
</el-form-item>
<el-form-item label="物料" style="width: calc(22%)">
<el-select
v-model="queryParams.itemCode"
placeholder="请选择物料"
clearable
style="width: 100%"
@change="detectionItemChange"
>
<el-option v-for=" (item) in itemList" :key="item" :label="item.name" :value="item.code" />
</el-select>
</el-form-item>
<el-form-item label="检测类型" style="width: calc(22%)">
<el-select
v-model="queryParams.detectionType"
placeholder="请选择检测类型"
clearable
style="width: 100%"
@change="detectionTypeChange"
>
<el-option v-for="dict in dictTypeList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<!-- 列表头部 --> <el-form-item style="width: calc(22%)">
<el-button :disabled="formLoading" type="primary" @click="submitForm">解析校验</el-button>
<el-button @click="dialogVisible = false"> </el-button>
</el-form-item>
</el-form>
<el-upload v-if="false" ref="uploadRef" v-model:file-list="fileList" :action="importUrl + '?mode=' + mode + '&file=' + file + '&updatePart=' + updatePart + '&outFile=' + outFile"
:auto-upload="false" :disabled="formLoading" :headers="uploadHeaders" :limit="1" :on-error="submitFormError"
:on-exceed="handleExceed" :on-success="submitFormSuccess" :accept="accept" drag
style="width:300px;margin:0 auto">
<Icon icon="ep:upload-filled" color="#c0c4cc" size="60" />
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<!-- 列表头部 -->
<TableHead <TableHead
:HeadButttondata="HeadButttondata" :HeadButttondata="HeadButttondata"
@button-base-click="buttonBaseClick" @button-base-click="buttonBaseClick"
@ -13,8 +62,7 @@
@searchFormClick="searchFormClick" @searchFormClick="searchFormClick"
:allSchemas="RecordsDetails.allSchemas" :allSchemas="RecordsDetails.allSchemas"
/> />
<!-- 列表 -->
<!-- 列表 -->
<ContentWrap> <ContentWrap>
<Table <Table
:columns="tableColumns" :columns="tableColumns"
@ -38,34 +86,30 @@
</Table> </Table>
</ContentWrap> </ContentWrap>
<!-- 表单弹窗添加/修改 --> </el-upload>
<BasicForm <template #footer>
ref="basicFormRef" <div class="flex items-center">
@success="getList" <div class="flex-1 text-left">
:rules="RecordsDetailsRules" <el-button type="primary" plain @click="importTemplate">
:formAllSchemas="RecordsDetails.allSchemas" <Icon icon="ep:download" />
:searchTableParams="searchTableParams" 下载模板
:apiUpdate="RecordsDetailsApi.updateRecordsDetails" </el-button>
:apiCreate="RecordsDetailsApi.createRecordsDetails" </div>
@searchTableSuccess="searchTableSuccess" <!-- <el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
:isBusiness="false" <el-button @click="dialogVisible = false"> </el-button> -->
/> </div>
</template>
<!-- 详情 --> </Dialog>
<Detail ref="detailRef" :isBasic="true" :allSchemas="RecordsDetails.allSchemas" />
<!-- 导入 -->
<ImportForm ref="importFormRef" url="/detection/records-details/import" :importTemplateData="importTemplateData" @success="importSuccess" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import download from '@/utils/download' import download from '@/utils/download'
import { RecordsDetails,RecordsDetailsRules } from './recordsDetails.data' import { RecordsDetails,RecordsDetailsRules } from '@/views/detection/recordsDetails/importRecordsDetails.data'
import * as RecordsDetailsApi from '@/api/detection/recordsDetails' import * as RecordsDetailsApi from '@/api/detection/recordsDetails'
import * as defaultButtons from '@/utils/disposition/defaultButtons' import * as defaultButtons from '@/utils/disposition/defaultButtons'
import TableHead from '@/components/TableHead/src/TableHead.vue' import * as ProjecAPI from '@/api/spc/project'
import ImportForm from '@/components/ImportForm/src/ImportForm.vue' import * as ItembasicApi from '@/api/spc/itembasic'
import Detail from '@/components/Detail/src/Detail.vue' import * as TemplateItemDetailsApi from '@/api/spc/templateItemDetails'
import {formatDate} from '@/utils/formatTime'
defineOptions({ name: 'RecordsDetails' }) defineOptions({ name: 'RecordsDetails' })
@ -98,6 +142,14 @@ const { tableObject, tableMethods } = useTable({
// //
const { getList, setSearchParams } = tableMethods const { getList, setSearchParams } = tableMethods
const message = useMessage() //
const dialogVisible = ref(false) //
const formLoading = ref(false) //
const uploadRef = ref()
const uploadHeaders = ref() // Header
const fileList = ref([]) //
const file = ref('')
// //
const HeadButttondata = [ const HeadButttondata = [
@ -107,14 +159,6 @@ const HeadButttondata = [
defaultButtons.defaultFreshBtn(null), // defaultButtons.defaultFreshBtn(null), //
defaultButtons.defaultFilterBtn(null), // defaultButtons.defaultFilterBtn(null), //
defaultButtons.defaultSetBtn(null), // defaultButtons.defaultSetBtn(null), //
// {
// label: '',
// name: 'zdy',
// hide: false,
// type: 'primary',
// icon: 'Select',
// color: ''
// },
] ]
// //
@ -228,4 +272,279 @@ onMounted(async () => {
importTemplateData.templateUrl = await RecordsDetailsApi.importTemplate() importTemplateData.templateUrl = await RecordsDetailsApi.importTemplate()
}) })
const queryParams = reactive({
proCode: '',
itemCode: '',
detectionType: '',
detectionItemContentId: null,
ecTab: '1'
})
const uploadOpen=ref(false)
const props = defineProps({
importTemplateData: {
type: Object,
required: true
},
//
accept: {
type: String,
required: false,
default:'.xlsx,.xls'
},
// .1
mode: {
type: Number,
required: false,
default: 1
},
// ,
updateIsDisable: {
type: Boolean,
required: false,
default: false
},
// ,
appendIsDisable: {
type: Boolean,
required: false,
default: false
},
// ,
coverIsDisable: {
type: Boolean,
required: false,
default: false
},
// ,
updatePart: {
type: Boolean,
required: false,
default: false
},
url:{
type: String,
required: false,
},
//
isShowOut: {
type: Boolean,
required: false,
default: false
},
outFile: {
type: Boolean,
required: false,
default: false
},
})
const importTemplateData= ref(props.importTemplateData)
const accept= ref(props.accept)
const mode = ref(props.mode)//.1
const updateIsDisable = ref(props.updateIsDisable)//,
const appendIsDisable = ref(props.appendIsDisable)//,
const coverIsDisable = ref(props.coverIsDisable)//,
const updatePart = ref(props.updatePart)//
const outFile = ref(props.outFile)//
//
const projectList = ref()
//
const itemList = ref()
//
const dictTypeList = ref()
const getProject = async () => {//
const _projectList = await ProjecAPI.selectAllPros()
if (_projectList != null && _projectList.length != 0) {
projectList.value = _projectList
let code = projectList.value[0].code;
queryParams.proCode = code;
await _itemList(code);
}
}
//code
const _itemList =async (projectCode)=>{
itemList.value = []
const _itemList = await ItembasicApi.selectItemsByProjectCode(projectCode);
if (_itemList != null && _itemList.length != 0) {
itemList.value = _itemList
queryParams.itemCode = itemList.value[0].code
dictOptions();
}
}
const dictOptions = async () => {//
dictTypeList.value = []
const dictOptions = await getIntDictOptions(DICT_TYPE.ITEMBASIC_TYPE);
if (dictOptions != null && dictOptions.length != 0) {
dictTypeList.value = dictOptions;
queryParams.detectionType = dictOptions[0].value + ''
uploadOpen.value = true;
}
}
const detectionProjectChange =async ()=>{//
if(queryParams.proCode==''){
queryParams.itemCode=''
queryParams.detectionType=''
itemList.value = [];
dictTypeList.value = [];
uploadOpen.value = false;
}else{
_itemList(queryParams.proCode);
}
}
const detectionTypeChange=async()=>{
if(queryParams.detectionType==''){
uploadOpen.value = false;
}else{
uploadOpen.value = true;
}
}
const detectionItemChange = async ()=>{//
if(queryParams.itemCode==''){
queryParams.detectionType=''
dictTypeList.value = [];
uploadOpen.value = false;
}else{
dictOptions();
uploadOpen.value =true;
}
}
onMounted(()=>{
getProject()
})
const importUrl =
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + props.url
/** 打开弹窗 */
const open = () => {
dialogVisible.value = true
getList() //
setSearchParams({
decRecId:55,
saveStatus:1,
result:"Warning",
});
resetForm()
}
defineExpose({ open }) // open
/** 提交表单 */
const submitForm = async () => {
if (fileList.value.length == 0) {
message.error('请上传文件')
return
}
file.value = fileList.value[0].name
//
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId(),
}
formLoading.value = true
uploadRef.value!.submit()
}
/** 文件上传成功 */
const emits = defineEmits(['success'])
const submitFormSuccess = (response: any) => {
formLoading.value = true
if(response){
if(response.code == 500){
message.error('导入失败')
return;
} else if (response.data.errorCount > 0) {
message.confirm('文件中有部分数据导入失败,是否下载失败数据?').then(() => {
// download.excel(file, 'file_' + new Date().getTime())
// url
// const downloadElement = document.createElement('a')
// console.log(172, import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/' + response.data.errorFile)
// console.log(172, import.meta.env.VITE_BASE_URL + '/admin-api/opt/profile/' + response.data.errorFile)
window.open(import.meta.env.VITE_BASE_URL + '/admin-api/profile/' + response.data.errorFile ,'222')
// downloadElement.setAttribute('href', import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + response.data.errorFile )
//
// downloadElement.click()
})
}
}else{
console.info("response",response);
message.success('导入成功')
}
//
formLoading.value = false
emits('success')
const decRecId = response.data.decRecId;//id
const role = response.data.decRecId;//admin
const waring = response.data.decRecId;//
//dialogVisible.value = false
//
setSearchParams({
decRecId:decRecId,
saveStatus:1,
result:"Warning",
});
uploadOpen.value = false;
}
/** 上传错误提示 */
const submitFormError = (): void => {
message.error('上传失败,请您重新上传!')
formLoading.value = false
}
/** 重置表单 */
const resetForm = () => {
//
formLoading.value = false
uploadRef.value?.clearFiles()
fileList.value = []
}
/** 文件数超出提示 */
const handleExceed = (): void => {
message.error('最多只能上传一个文件!')
}
/** 下载模板操作 */
const importTemplate = () => {
const res = importTemplateData.value.templateUrl
download.excel(res, importTemplateData.value.templateTitle)
}
</script> </script>
<style scoped lang="scss">
.tips {
div {
position: relative;
padding-left: 22px;
&::before {
width: 4px;
height: 4px;
border-radius: 50%;
content: '';
background: #c2c2c2;
position: absolute;
top: 50%;
margin-top: -2px;
left: 4px;
}
}
}
</style>

2
src/views/spc/detectiontemplate/detectionTemplate.data.ts

@ -85,7 +85,7 @@ export const DetectionTemplate = useCrudSchemas(reactive<CrudSchema[]>([
form:{ form:{
component: 'InputNumber', component: 'InputNumber',
componentProps: { componentProps: {
min: 1, min: 3,
} }
} }
}, },

1
src/views/spc/itembasic/itembasic.data.ts

@ -36,7 +36,6 @@ export const Itembasic = useCrudSchemas(reactive<CrudSchema[]>([
{ {
label: '项目名称', label: '项目名称',
field: 'projectName', field: 'projectName',
sort: 'custom',
isSearch: false, isSearch: false,
isForm:false, isForm:false,
isTable:true, isTable:true,

Loading…
Cancel
Save