<template>
|
<div>
|
<div class="formitem" >
|
<div v-if="dataChildItem.type === 'input'">
|
<el-input
|
v-model.trim="parentDatas[_dataIndex].content"
|
:placeholder="dataChildItem.description"
|
clearable
|
:disabled="_disabled"
|
></el-input>
|
</div>
|
<div v-if="dataChildItem.type === 'textarea'">
|
<el-input
|
v-model.trim="parentDatas[_dataIndex].content"
|
style="width: 100%"
|
:rows="3"
|
type="textarea"
|
:placeholder="dataChildItem.description"
|
clearable
|
:disabled="_disabled"
|
></el-input>
|
</div>
|
<div v-if="dataChildItem.type === 'singleSelect'">
|
<el-select
|
style="width:100%"
|
clearable
|
v-model="parentDatas[_dataIndex].content"
|
:disabled="_disabled"
|
:placeholder="dataChildItem.description"
|
>
|
<el-option
|
v-for="option in dictionaryObj[dataChildItem.dictCode]"
|
:key="option.id"
|
:label="option.name"
|
:value="option.id"
|
/>
|
</el-select>
|
</div>
|
<div v-if="dataChildItem.type === 'multipleSelect'">
|
<el-select
|
style="width:100%"
|
clearable
|
v-model="parentDatas[_dataIndex].content"
|
:disabled="_disabled"
|
:placeholder="dataChildItem.description"
|
multiple
|
>
|
<el-option
|
v-for="option in dictionaryObj[dataChildItem.dictCode]"
|
:key="option.id"
|
:label="option.name"
|
:value="option.id"
|
/>
|
</el-select>
|
</div>
|
<div v-if="dataChildItem.type=='singleTree'">
|
<el-tree-select
|
:disabled="_disabled"
|
v-model="parentDatas[_dataIndex].content"
|
:data="dictionaryObj[dataChildItem.dictCode]"
|
:placeholder="parentDatas[_dataIndex].description||'请选择'"
|
clearable
|
:default-expand-all="true"
|
:render-after-expand="false"
|
style="width: 100%"
|
/>
|
</div>
|
<div v-if="dataChildItem.type=='multipleTree'">
|
<el-tree-select
|
:disabled="_disabled"
|
v-model="parentDatas[_dataIndex].content"
|
:data="dictionaryObj[dataChildItem.dictCode]"
|
:placeholder="parentDatas[_dataIndex].description||'请选择'"
|
clearable
|
:default-expand-all="true"
|
:render-after-expand="false"
|
style="width: 100%"
|
multiple
|
show-checkbox
|
/>
|
</div>
|
<div v-if="dataChildItem.type=='table'">
|
<el-table class="table" :data="dataChildItem.tableData" border>
|
<el-table-column
|
v-for="(header, tableIndex) in dataChildItem.tableHead"
|
:key="tableIndex"
|
:prop="header.prop"
|
:label="header.name"
|
:min-width="returnTdMinWidth(header)"
|
:width="returnTdWidth(header)"
|
>
|
<template #header="scope" v-if="header.required=='1'" >
|
<div class="customTh"><span class="xing-tb">*</span>
|
<span>{{ header.name }}</span></div>
|
</template>
|
<template #default="scope" v-if="header.type=='text'" >
|
<div>{{ scope.row[header.prop] }}</div>
|
</template>
|
<template #default="scope" v-if="header.type=='input'" >
|
<div>
|
<el-input
|
v-model.trim="scope.row[header.prop]"
|
:placeholder="header?.description||'请输入'"
|
clearable
|
:disabled="_disabled"
|
style="width: 100%"
|
/>
|
</div>
|
</template>
|
<template #default="scope" v-if="header.type=='textarea'" >
|
<div>
|
<el-input
|
v-model.trim="scope.row[header.prop]"
|
style="width: 100%"
|
:rows="3"
|
type="textarea"
|
:disabled="_disabled"
|
:placeholder="header?.description||'请输入'"
|
clearable
|
/>
|
</div>
|
</template>
|
<template #default="scope" v-if="header.type=='singleTree'" >
|
<div>
|
<el-tree-select
|
:disabled="_disabled"
|
v-model="scope.row[header.prop]"
|
:data="dictionaryObj[header.dictCode]"
|
:placeholder="header.description||'请选择'"
|
clearable
|
:default-expand-all="true"
|
:render-after-expand="false"
|
style="width: 100%"
|
/>
|
</div>
|
</template>
|
<template #default="scope" v-if="header.type=='multipleTree'" >
|
<div>
|
<el-tree-select
|
:disabled="_disabled"
|
v-model="scope.row[header.prop]"
|
:data="dictionaryObj[header.dictCode]"
|
:placeholder="header.description||'请选择'"
|
clearable
|
:default-expand-all="true"
|
:render-after-expand="false"
|
multiple
|
show-checkbox
|
style="width: 100%"
|
/>
|
</div>
|
</template>
|
<template #default="scope" v-if="header.type=='singleSelect' && header.dictCode!=''">
|
<div>
|
<el-select
|
style="width:100%"
|
clearable
|
v-model="scope.row[header.prop]"
|
:placeholder="header?.description||'请选择'"
|
:disabled="_disabled"
|
>
|
<el-option
|
v-for="item in dictionaryObj[header.dictCode]"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
</div>
|
</template>
|
<template #default="scope" v-if="header.type=='multipleSelect' && header.dictCode!=''">
|
<div>
|
<el-select
|
style="width:100%"
|
clearable
|
v-model="scope.row[header.prop]"
|
:placeholder="header?.description||'请选择'"
|
:disabled="_disabled"
|
multiple
|
>
|
<el-option
|
v-for="item in dictionaryObj[header.dictCode]"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
</div>
|
</template>
|
<template #default="{row}" v-if="header.type=='upload'" >
|
<div class="uploadbox">
|
<template v-if="!header.multiple">
|
<template v-if="_disabled">
|
<!-- 编辑预览 -->
|
<div v-if="row?.fileList && row.fileList.length>0">
|
<div v-for="item in row.fileList" :key="item.fileId">
|
<template v-if="item.suffix.toLowerCase()=='.pdf'">
|
<span @click="previewQuotationSystem(item)" class="filename">{{ item.name }}</span>
|
</template>
|
<template v-else>
|
<el-image
|
style="
|
position: relative;
|
width: 100px;
|
height: 100px;
|
cursor: pointer;
|
"
|
:src="item.fileUrl"
|
:preview-teleported="true"
|
:preview-src-list="[item.fileUrl]"
|
>
|
</el-image>
|
</template>
|
</div>
|
</div>
|
</template>
|
<template v-else>
|
<el-upload
|
:ref="'uploadSingleRef'+header.sort"
|
:file-list="row.fileList"
|
:accept="header.acceptType"
|
action="#"
|
:multiple="header.multiple"
|
:on-remove="(file, fileList) => {handleRemoveFile(file, fileList,row,header.prop)}"
|
:limit="1"
|
:on-exceed="(files, fileList) => {handleExceedFile(files, fileList,row)}"
|
:http-request="(file) => {handleUploadFile(file, row)}"
|
:disabled="_disabled"
|
>
|
<slot>
|
<el-button type="primary" :disabled="_disabled">选择文件</el-button>
|
</slot>
|
<template #tip v-if="!_disabled">
|
<div class="el-upload__tip">{{ header.description }}</div>
|
</template>
|
</el-upload>
|
</template>
|
</template>
|
</div>
|
</template>
|
</el-table-column>
|
<el-table-column v-if="dataChildItem.operate && !_disabled" align="center" label="操作" width="120">
|
<template #default="scope">
|
<div class="rowBtnDiv">
|
<el-icon size="20" @click="handleRowCopy(dataChildItem.tableData,scope.row)"><DocumentCopy class="btnicon"/></el-icon>
|
<el-icon size="20" v-if="dataChildItem.tableData.length>1" @click="handleRowDelete(dataChildItem.tableData,scope.row,scope.$index)"><Remove class="btnicon" /></el-icon>
|
</div>
|
</template>
|
</el-table-column>
|
</el-table>
|
<div v-if="dataChildItem.operate&& !_disabled" class="addbtn"><el-button icon="Plus" @click="addTableRow(dataChildItem.tableData,dataChildItem.tableHead)">增加</el-button></div>
|
</div>
|
|
<div v-if="dataChildItem.type === 'richText'">
|
<template v-if="_disabled">
|
<div class="richTextbox" v-html="parentDatas[_dataIndex].content"></div>
|
</template>
|
<template v-else>
|
<richText
|
:ref="'richTextRef' + _dataIndex"
|
:indexData="_dataIndex"
|
:modelData="parentDatas[_dataIndex].content"
|
:currentData="parentDatas"
|
:currentIndex="_dataIndex"
|
@updateDataFun="updateDataFun"
|
:placeholder="parentDatas[_dataIndex].description|| null"
|
@getCurrentData="handleGetCurrentRichData"
|
></richText>
|
</template>
|
</div>
|
<div v-if="dataChildItem.type === 'upload'" class="uploadbox">
|
<template v-if="_disabled">
|
<!-- 编辑预览 -->
|
<div v-if="dataChildItem?.fileList && dataChildItem.fileList.length>0">
|
<div v-for="item in dataChildItem.fileList" :key="item.fileId">
|
<template v-if="item.suffix.toLowerCase()=='.pdf'">
|
<span @click="previewQuotationSystem(item)" class="filename">{{ item.name }}</span>
|
</template>
|
<template v-else>
|
<el-image
|
style="
|
position: relative;
|
width: 100px;
|
height: 100px;
|
cursor: pointer;
|
"
|
:src="item.fileUrl"
|
:preview-teleported="true"
|
:preview-src-list="[item.fileUrl]"
|
>
|
</el-image>
|
</template>
|
</div>
|
</div>
|
</template>
|
<template v-else>
|
<el-upload
|
:ref="'uploadItemRef'+ dataChildItem.sort"
|
:file-list="dataChildItem.fileList"
|
:accept="dataChildItem.acceptType"
|
action="#"
|
:multiple="dataChildItem.multiple"
|
:on-remove="(file, fileList) => {handleRemoveFile(file, fileList,dataChildItem,'content')}"
|
:limit="1"
|
:on-exceed="(files, fileList) => {handleExceedFile(files, fileList,dataChildItem)}"
|
:http-request="(file) => {handleUploadFile(file, dataChildItem)}"
|
>
|
<slot>
|
<el-button type="primary" >选择文件</el-button>
|
</slot>
|
<template #tip>
|
<div class="el-upload__tip">{{ dataChildItem.description }}</div>
|
</template>
|
</el-upload>
|
</template>
|
</div>
|
</div>
|
<el-dialog
|
width="80vw"
|
height="90vh"
|
class="resetDialog"
|
v-model="showfilePreviewDiv"
|
title="文件预览"
|
>
|
<fileInfoPreview ref="fileInfoPreviewRef"></fileInfoPreview>
|
</el-dialog>
|
</div>
|
</template>
|
<script setup lang="ts">
|
import { useVModel } from '@vueuse/core'
|
import createAxios from '@/utils/axios'
|
import type {UploadProps} from 'element-plus'
|
import {genFileId, UploadRawFile} from 'element-plus'
|
|
interface Props {
|
dataItem: any
|
dataIndex:number
|
twoIndex?:number
|
parentData:any
|
dictObj:any
|
disabled?: boolean
|
size?: 'default' | 'small' | 'large'
|
}
|
const props = withDefaults(defineProps<Props>(), {
|
dataItem: [],
|
dictObj:{},
|
disabled: false,
|
size: 'default',
|
})
|
const emit = defineEmits(['getJonData','returnItemData'])
|
const parentDatas= useVModel(props, 'parentData', emit)
|
const dataChildItem = useVModel(props, 'dataItem', emit)
|
const _dataIndex = useVModel(props, 'dataIndex', emit)
|
const _twoIndex = useVModel(props, 'twoIndex', emit)
|
const dictionaryObj = useVModel(props, 'dictObj', emit)
|
const _disabled = useVModel(props, 'disabled', emit)
|
const _size = useVModel(props, 'size', emit)
|
const state= reactive<any>({
|
currentRichData:''
|
})
|
const showfilePreviewDiv = ref<boolean>(false)
|
const fileInfoPreviewRef = ref()
|
const previewQuotationSystem = (item:any) => {
|
showfilePreviewDiv.value = true
|
nextTick(() => {
|
fileInfoPreviewRef.value.visibleShow({
|
fileId:item.fileId,
|
fileSuffix: item.suffix,
|
})
|
})
|
}
|
const returnTdWidth=computed(()=>{
|
return function(item:any){
|
if(item.prop=='sort'){
|
return '80px'
|
}
|
}
|
})
|
const returnTdMinWidth=computed(()=>{
|
return function(item:any){
|
if(item.type=='input' || item.type=='singleSelect'){
|
return '200px'
|
}
|
else if(item.type=='textarea' || item.type=='upload'){
|
return '400px'
|
}
|
}
|
})
|
// 上传文件
|
const handleRemoveFile=(file:any, fileList:any,row:any,key:'')=>{
|
row.fileList = []
|
row[key]=''
|
}
|
const handleExceedFile= (files:any, uploadFiles:any,row:any) => {
|
ElMessage.warning(`只能上传1个文件`)
|
}
|
const handleUploadFile=(option: any,row:any) => {
|
console.log(option)
|
const maxSize = 20 * 1024 * 1024; // 20MB
|
const isLt20M = option.file.size <= maxSize;
|
if (!isLt20M) {
|
ElMessage({
|
type: "error",
|
message: "文件大小不能超过10MB",
|
});
|
row.fileList = [];
|
return false; // 阻止文件上传
|
}
|
let param = new FormData()
|
param.append('file', option.file)
|
createAxios({
|
url: '/admin/common/fileUploadAnswerDetail',
|
headers: {
|
'Content-Type': 'multipart/form-data'
|
},
|
data: param,
|
}).then((res:any) => {
|
if (res.code == 200) {
|
row.fileList = [res.data]
|
ElMessage.success('文件上传成功!')
|
row.accessory=res.data.fileId
|
}
|
})
|
.finally(() => {
|
})
|
}
|
const handleRowCopy=(tableData:any,row:any)=>{
|
console.log('tableData',tableData)
|
console.log('row',row)
|
tableData.push({...row})
|
tableData.forEach((item:any,index:number)=>{
|
item.sort=index+1
|
})
|
}
|
const handleRowDelete=(tableData:any,row:any,rowIndex:number)=>{
|
tableData.splice(rowIndex,1)
|
tableData.forEach((item:any,index:number)=>{
|
item.sort=index+1
|
})
|
}
|
const addTableRow=(tableData:any,tableHead:any)=>{
|
let obj:any={}
|
tableHead.forEach((item:any)=>{
|
obj[item.prop]=''
|
})
|
obj.sort=tableData.length+1
|
tableData.push(obj)
|
tableData.forEach((item:any,index:number)=>{
|
item.sort=index+1
|
})
|
}
|
const updateDataFun = (val: any, indexData?: any) => {
|
state.currentRichData=val
|
}
|
const handleGetCurrentRichData=(currentList:any,index:any)=>{
|
if(currentList){
|
currentList[index].content=state.currentRichData
|
}
|
}
|
|
</script>
|
<style scoped lang="scss">
|
.formitem{
|
display: flex;
|
flex-direction: column;
|
width: 100%;
|
.item-desc{
|
display: flex;
|
margin-top: 10px;
|
font-weight: 600;
|
align-items: center;
|
.xing{
|
font-size: 24px;
|
color: rgb(247, 23, 23);
|
padding-right:5px;
|
padding-top: 0px;
|
}
|
.xing-tb{
|
font-size: 24px;
|
color: rgb(247, 23, 23);
|
padding-right:5px;
|
}
|
}
|
}
|
|
.borderbox{
|
border: 1px solid #dddddd;
|
padding: 0px 10px;
|
width: 100%;
|
border-radius: 4px;
|
}
|
.uploadbox{margin-top: 10px;}
|
.customTh{
|
display: flex;
|
// justify-content: center;
|
// align-items: center;
|
.xing-tb{
|
display: inline-block;
|
font-size: 18px;
|
color: rgb(247, 23, 23);
|
padding-top: 5px;
|
padding-right: 5px;
|
}
|
}
|
:deep(.el-tag.el-tag--info){
|
border: 1px solid #e4e4e4;
|
border-radius: 3px;
|
background-color: #f8f8f8;
|
}
|
:deep(.el-form-item){
|
margin-bottom: 0px;
|
}
|
.table{
|
width: 100%;
|
margin-top: 5px;
|
}
|
.btnicon{
|
cursor: pointer;
|
&:hover{
|
color:#5b6ad8
|
}
|
}
|
.rowBtnDiv{
|
display: flex;
|
justify-content: center;
|
}
|
.addbtn{
|
margin-top: 10px;
|
}
|
.footerbtns{
|
display: flex;
|
justify-content: center;
|
}
|
:deep(.el-upload-list){
|
max-width: 600px;
|
}
|
.richTextbox{
|
border: 1px solid #e4e7ed;
|
border-radius: 4px;
|
padding: 8px;
|
background-color: #fafafa;
|
}
|
.filename{
|
color: #5b6ad8;
|
cursor: pointer;
|
font-weight: 600;
|
}
|
:deep(.el-table){
|
z-index:0
|
}
|
</style>
|