9 changed files with 2440 additions and 10 deletions
@ -0,0 +1,877 @@ |
|||
<!-- |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-10-17 09:36:08 |
|||
@ 备注: 自定义表单组件 |
|||
--> |
|||
<script lang='ts' setup> |
|||
import { |
|||
inject, |
|||
onMounted, |
|||
computed, |
|||
watch, |
|||
onUnmounted, |
|||
markRaw |
|||
} from 'vue' |
|||
import { Md5 } from 'ts-md5' |
|||
import { ElMessage } from 'element-plus' |
|||
import Tooltips from '@/components/DesignForm/tooltip.vue' |
|||
import TinymceEdit from '@/components/DesignForm/public/form/tinymce.vue' |
|||
import { FormItem, FormList } from '@/api/DesignForm/types' |
|||
import { |
|||
formatNumber, |
|||
objectToArray, |
|||
constControlChange, |
|||
constSetFormOptions, |
|||
constFormProps, |
|||
constGetControlByName |
|||
} from '@/api/DesignForm/utils' |
|||
import validate from '@/api/DesignForm/validate' |
|||
import ExpandUser from '@/components/DesignForm/public/expand/user.vue' |
|||
import OrgCentent from '@/components/DesignForm/public/expand/org.vue' |
|||
import LokOrgCentent from '@/widget/org/cont.vue' |
|||
|
|||
import DigitpagePage from '@/components/DesignForm/public/expand/digitpage.vue' |
|||
import LowcodeImagePage from '@/components/DesignForm/public/expand/lowcodeImage.vue' |
|||
|
|||
// import LowcodeImagePage from '@/widget/lowcodeimage/index.vue' |
|||
|
|||
|
|||
import UploadPage from '@/components/DesignForm/public/expand/uploadPage.vue' |
|||
import UploadPageList from '@/components/DesignForm/public/expand/uploadPageList.vue' |
|||
import OrgCitys from '@/components/DesignForm/public/expand/orgCitys.vue' |
|||
import DatePickerPage from '@/components/DesignForm/public/expand/datePicker.vue' |
|||
import CascaderPage from '@/components/DesignForm/public/expand/cascader.vue' |
|||
|
|||
|
|||
|
|||
import AKSelect from '@/components/DesignForm/public/form/select.vue' |
|||
import { uploadUrl,getRequest } from '@/api/DesignForm' |
|||
import formatResult from '@/utils/DesignForm/formatResult' |
|||
import { debounce } from '@/utils/DesignForm/index' |
|||
import { useRoute } from 'vue-router' |
|||
|
|||
import { json2string,objToStringify,string2json,stringToObj } from '@/utils/DesignForm/form' |
|||
|
|||
|
|||
import TextImg from "@/assets/image/tinymce.png" |
|||
|
|||
import { AnalysisCss,AnalysisInputCss } from '@/components/DesignForm/public/form/calculate/cssInfo.ts' |
|||
|
|||
import request from '@/utils/request'; |
|||
|
|||
import { getgovcont } from '@/api/hr/org/index' |
|||
|
|||
const props = withDefaults( |
|||
defineProps<{ |
|||
data: FormList |
|||
modelValue?: any // 子表和弹性布局时时有传 |
|||
tProp?: string // 子表时的form-item的prop值,用于子表校验用 |
|||
nodeKey?:string |
|||
purview?:any[] |
|||
optionsValue3Get1?:any |
|||
tablekey?:any |
|||
numrun?:any |
|||
}>(), |
|||
{} |
|||
) |
|||
const emits = defineEmits<{ |
|||
(e: 'update:modelValue', val: any): void |
|||
(e: 'optionsValue3Get1', val: any,fieldName: string): void |
|||
(e: 'asfValueChanged', val: any): void |
|||
}>() |
|||
const route = useRoute() |
|||
const formProps = inject(constFormProps, {}) as any |
|||
const type = computed(() => { |
|||
return formProps.value.type |
|||
}) |
|||
const config = computed(() => { |
|||
return props.data.config || {} |
|||
}) |
|||
//组件css部分 |
|||
const configStyle = computed(() => { |
|||
return props.data.styles || {} |
|||
}) |
|||
|
|||
const control = computed(() => { |
|||
if(props.data.type == "upload"){ |
|||
props.data.control.action = uploadUrl |
|||
} |
|||
return props.data.control |
|||
// return props.data |
|||
}) |
|||
const options = ref(props.data.options) |
|||
//console.log("FormItem*********************************************************"+JSON.stringify(props.data)) |
|||
const changeEvent = inject(constControlChange, '') as any |
|||
const updateModel = (val: any) => { |
|||
let controlAttribute = "" |
|||
if(props.data.control){ |
|||
if(props.data.control.type){ |
|||
controlAttribute = props.data.control.type |
|||
} |
|||
} |
|||
changeEvent && |
|||
changeEvent({ |
|||
key: props.data.name, |
|||
value: val, |
|||
data: props.data, |
|||
tProp: props.tProp, |
|||
type: props.data.type, |
|||
attribute: controlAttribute |
|||
}) |
|||
} |
|||
const value = computed({ |
|||
get() { |
|||
if (props.tProp) { |
|||
// 表格和弹性布局 |
|||
return props.modelValue |
|||
} else { |
|||
if(props.data.type == "checkbox"){ |
|||
if (formProps.value.model[props.data.name] == null || formProps.value.model[props.data.name] == ""){ |
|||
// formProps.value.model[props.data.name] = [] |
|||
// return formProps.value.model[props.data.name] |
|||
return [] |
|||
}else{ |
|||
return formProps.value.model[props.data.name] |
|||
} |
|||
}else{ |
|||
return formProps.value.model[props.data.name] |
|||
} |
|||
|
|||
} |
|||
}, |
|||
set(newVal: any) { |
|||
if (props.tProp) { |
|||
emits('update:modelValue', newVal) |
|||
} |
|||
updateModel(newVal) |
|||
} |
|||
}) |
|||
// 选择数据转换,默认尝试转数字 |
|||
const transformOption = (val: string | number, type?: string) => { |
|||
switch (config.value.transformData || type) { |
|||
case 'none': |
|||
return val |
|||
case 'string': |
|||
try { |
|||
return val.toString() |
|||
} catch (e) { |
|||
return val |
|||
} |
|||
} |
|||
return formatNumber(val) |
|||
} |
|||
|
|||
// 当通用修改属性功能添加新字段时,数组更新但toRefs没更新 |
|||
const getControlByName = inject(constGetControlByName) as any |
|||
const sourceFunKey = computed(() => { |
|||
const iReg = new RegExp('(?<=\\${)(.*?)(?=})', 'g') |
|||
//const iReg = new RegExp('\\${.*?}', 'g') // 结果会包含开头和结尾=>${name} |
|||
const apiUrl = config.value.optionsFun |
|||
const replace = apiUrl?.match(iReg) |
|||
return replace && replace[0] |
|||
}) |
|||
const getLabel = (ele: FormItem) => { |
|||
const showColon = formProps.value.showColon ? ':' : '' |
|||
if (ele) { |
|||
return ele.showLabel ? '' : ele.label + showColon |
|||
} else { |
|||
return '' |
|||
} |
|||
} |
|||
const currentComponent = computed(() => { |
|||
if (props.data.type === 'component') { |
|||
// 自定义组件 |
|||
return config.value.componentName |
|||
} |
|||
if (props.data.type === 'expand-user') { |
|||
return markRaw(ExpandUser) |
|||
} |
|||
if (props.data.type === 'orgCentent') { |
|||
return markRaw(OrgCentent) |
|||
} |
|||
if (props.data.type === 'digitpage') { |
|||
return markRaw(DigitpagePage) |
|||
} |
|||
if (props.data.type === 'lowcodeImage') { |
|||
return markRaw(LowcodeImagePage) |
|||
} |
|||
if (props.data.type === 'upload') { |
|||
return markRaw(UploadPage) |
|||
} |
|||
if (props.data.type === 'organization') { |
|||
return markRaw(OrgCitys) |
|||
} |
|||
if (props.data.type === 'datePicker') { |
|||
props.data.control.valueFormat="x" |
|||
// props.data.control.align="right" |
|||
// props.data.control.appendToBody =true |
|||
return markRaw(DatePickerPage) |
|||
} |
|||
if(props.data.type === 'cascader'){ |
|||
return markRaw(CascaderPage) |
|||
} |
|||
if (props.data.type === 'switch') { |
|||
if(typeof props.data.control.activeValue === "number"){ |
|||
props.data.control.activeValue=props.data.control.activeValue.toString() |
|||
} |
|||
if(typeof props.data.control.inactiveValue === "number"){ |
|||
props.data.control.inactiveValue=props.data.control.inactiveValue.toString() |
|||
} |
|||
} |
|||
// if (props.data.type === 'timePicker') { |
|||
// props.data.control.valueFormat="timestamp" |
|||
// } |
|||
// console.log("自定义组件",props.data) |
|||
return `el-${props.data.type}` |
|||
}) |
|||
// 控制编辑模式下是否可用 |
|||
const editDisabled = computed(() => { |
|||
if (type.value === 3) { |
|||
return true // 查看模式,为不可编辑状态 |
|||
} |
|||
if (type.value === 1 && config.value.addDisabled) { |
|||
return true |
|||
} |
|||
if (type.value === 2 && config.value.editDisabled) { |
|||
return true // 编辑模式 |
|||
} |
|||
// return judgeIsDisabled(key) |
|||
return control.value.disabled |
|||
}) |
|||
// 返回当前item项的校验规则 |
|||
const itemRules = computed(() => { |
|||
let temp |
|||
const itemR: any = props.data.item?.rules || [] |
|||
const customR = formatCustomRules() |
|||
// 如果三个都没有设置,则返回undefined |
|||
if (itemR?.length || customR?.length) { |
|||
temp = [...customR, ...itemR] |
|||
} |
|||
return temp |
|||
}) |
|||
// data 根据条件搜索,select远程搜索里data有值 |
|||
const getAxiosOptions = debounce((data?: any) => { |
|||
//console.log(props.data) |
|||
const { |
|||
optionsType, |
|||
optionsFun, |
|||
method = 'post', |
|||
afterResponse, |
|||
beforeRequest, |
|||
label, |
|||
value, |
|||
debug // =true可用于调试,不存sessionStorage |
|||
} = config.value |
|||
if (optionsType !== 0) { |
|||
let sourceFun = optionsFun |
|||
// 接口数据源 |
|||
if (optionsType === 1 && sourceFun) { |
|||
// 当前控件为动态获取数据,防多次加载,先从本地取。data=true时直接请求 |
|||
let md5Object:any = new Md5() |
|||
md5Object.appendAsciiStr(JSON.stringify(sourceFun + data)) |
|||
let md5Str = md5Object.end() |
|||
// const key = 'getOptions_' + props.data.name + md5(sourceFun + data) |
|||
const key = 'getOptions_' + props.data.name + md5Str |
|||
const storage = window.sessionStorage.getItem(key) |
|||
if (storage && !data && !debug) { |
|||
const val = JSON.parse(storage) |
|||
if (props.data.type === 'treeSelect') { |
|||
control.value.data = val |
|||
} else { |
|||
options.value = val |
|||
} |
|||
} else { |
|||
// 从url里提取一个动态值,${name}形式提取name |
|||
if (sourceFunKey.value) { |
|||
const val = formProps.value.model[sourceFunKey.value] |
|||
const string = '${' + sourceFunKey.value + '}' |
|||
sourceFun = sourceFun.replace(string, val) |
|||
} |
|||
// 处理请求前的数据 |
|||
//let newData = Object.assign({}, data || {}, queryParams) |
|||
let newData = data || {} |
|||
if (typeof beforeRequest === 'function') { |
|||
newData = |
|||
beforeRequest(newData, route, formProps.value.model) ?? data |
|||
} |
|||
if (newData === false) { |
|||
return |
|||
} |
|||
if (method === 'get') { |
|||
newData = { params: newData } |
|||
} |
|||
} |
|||
}else if(optionsType === 3){//liwenxuan 20240611 系统表单字段效果实现 |
|||
/* |
|||
在这里请求后台获取字段 |
|||
*/ |
|||
//console.log("formItem---291",props.data.control.optionsValue3Field) |
|||
if(props.data.control.optionsValue3Field && props.data.control.optionsValue3Field != "" && props.data.control.optionsValue3Field != null && props.data.control.optionsValue3Field != "undefined"){ |
|||
getFieldRecord(props.data.control.optionsValue3Field).then(({ data }) => { |
|||
|
|||
let fieldName = props.data.name |
|||
|
|||
emits('optionsValue3Get1',data,fieldName) |
|||
|
|||
}) |
|||
} |
|||
|
|||
} |
|||
setFormDict(formProps.value.dict) // 表格里新增时行时需要重新设一次 |
|||
} |
|||
}) |
|||
watch( |
|||
() => props.data.control.optionsValue3Field, |
|||
(val:any) => { |
|||
console.log("监听--optionsValue3Field-》",val) |
|||
getAxiosOptions() |
|||
} |
|||
) |
|||
watch( |
|||
() => props.data.config.optionsType, |
|||
() => { |
|||
getAxiosOptions() |
|||
} |
|||
) |
|||
|
|||
|
|||
function getFieldRecord(param1: any) { |
|||
return request({ |
|||
url: '/javasys/lowCode/AssociatedForms/getFieldRecord', |
|||
method: 'post', |
|||
data: { |
|||
optionsValue3Field:param1 |
|||
}, |
|||
}); |
|||
} |
|||
watch( |
|||
() => formProps.value.model[sourceFunKey.value], |
|||
() => { |
|||
getAxiosOptions() |
|||
} |
|||
) |
|||
// 处理自定义校验规则,将customRules转换后追加到rules里 |
|||
const formatCustomRules = () => { |
|||
const rulesReg: any = {} |
|||
validate && |
|||
validate.forEach(item => { |
|||
rulesReg[item.type] = item.regExp |
|||
}) |
|||
|
|||
// 获取校验方法 父级使用provide方法注入 |
|||
const temp: any = [] |
|||
props.data.customRules?.forEach((item: any) => { |
|||
if (!item.message && item.type !== 'methods') { |
|||
return // 方法时允许提示信息为空 |
|||
} |
|||
let obj = {} |
|||
if (item.type === 'required') { |
|||
obj = { required: true } |
|||
} else if (item.type === 'rules') { |
|||
// 自定义表达式 |
|||
obj = { pattern: item.rules } |
|||
} else if (item.type === 'methods') { |
|||
// 方法时 |
|||
const methods: any = item.methods |
|||
if (methods) { |
|||
obj = { validator: inject(methods, {}) } |
|||
} |
|||
} else if (item.type) { |
|||
obj = { pattern: rulesReg[item.type as string] } |
|||
} |
|||
// 这里判断下防某些条件下重复push的可能或存重复校验类型 |
|||
let message: any = { message: item.message } |
|||
if (!item.message) { |
|||
// 当使用validator校验时,如果存在message字段则不能使用 callback(new Error('x'));的提示 |
|||
message = {} |
|||
} |
|||
temp.push( |
|||
Object.assign( |
|||
{ |
|||
trigger: item.trigger || 'blur' |
|||
}, |
|||
obj, |
|||
message |
|||
) |
|||
) |
|||
}) |
|||
return temp |
|||
} |
|||
// 从数据接口获取数据设置options,在表单添加或编辑时数据加载完成 |
|||
const setFormDict = (val: any) => { |
|||
// console.log("从数据接口获取数据设置options",val) |
|||
if (val && config.value.optionsType === 2) { |
|||
const opt = val[config.value.optionsFun] || val[props.data.name] // 不填写默认为当前字段名 |
|||
if (opt !== undefined) { |
|||
options.value = objectToArray(opt) |
|||
} |
|||
} |
|||
} |
|||
// 从接口返回的dict会在这里触发 |
|||
watch( |
|||
() => formProps.value.dict, |
|||
(val: any) => { |
|||
setFormDict(val) |
|||
}, |
|||
{ |
|||
/*deep: true*/ |
|||
} |
|||
) |
|||
// 对单选多选select设置options |
|||
const formOptions = inject(constSetFormOptions, {}) as any |
|||
watch( |
|||
() => formOptions.value, |
|||
(val: any) => { |
|||
// console.log("子表内的需要注意下,只有在子表有记录时才生效",val) |
|||
const opt = val[props.data.name] |
|||
// 子表内的需要注意下,只有在子表有记录时才生效 |
|||
if (val && opt !== undefined) { |
|||
if (props.data.type === 'treeSelect') { |
|||
// 树结构的参数为data |
|||
control.value.data = objectToArray(opt) |
|||
} else { |
|||
options.value = objectToArray(opt) |
|||
} |
|||
} |
|||
} |
|||
) |
|||
// ------------图片上传处理----------- |
|||
const fileList = computed<any>(() => { |
|||
const imgVal = formProps.value.model[props.data.name] |
|||
// console.log("图片上传处理-->",imgVal) |
|||
if (imgVal && typeof imgVal === 'string') { |
|||
// console.log("图片上传处理-2->",imgVal) |
|||
const temp: any = [] |
|||
imgVal.split(',').forEach((item: string) => { |
|||
// console.log("图片上传处理-3->",item) |
|||
temp.push({ |
|||
name: item, |
|||
url: item |
|||
}) |
|||
}) |
|||
return temp |
|||
} |
|||
return imgVal || [] // 这样可支持默认值为array([name:'',url:''这种形式]) |
|||
}) |
|||
// 上传成功时 |
|||
const uploadSuccess = (response: any, uploadFile: any, uploadFiles: any) => { |
|||
// console.log("response==>",response) |
|||
// console.log("uploadFile==>",uploadFile) |
|||
// console.log("uploadFiles==>",uploadFiles) |
|||
const oldList = [] |
|||
fileList.value.forEach((item: any) => { |
|||
oldList.push(item.url) |
|||
}) |
|||
// oldList.push(response.path) |
|||
oldList.push(response.data.url) |
|||
updateModel(oldList.join(',')) |
|||
control.value.onSuccess && |
|||
control.value.onSuccess(response, uploadFile, uploadFiles) |
|||
// console.log("uploadSuccess===>",control.value) |
|||
// console.log("uploadSuccess=fileList==>",fileList) |
|||
} |
|||
// 从列表移除 |
|||
const uploadRemove = (uploadFile: any, uploadFiles: any) => { |
|||
const oldList: any = [] |
|||
fileList.value.forEach((item: any) => { |
|||
if (item.url !== uploadFile.url) { |
|||
oldList.push(item.url) |
|||
} |
|||
}) |
|||
updateModel(oldList.join(',')) |
|||
control.value.onRemove && control.value.onRemove(uploadFile, uploadFiles) |
|||
// todo 需从服务端删除已上传图片时,这里需要发删除请求接口 |
|||
} |
|||
// 上传错误 |
|||
const uploadError = (err: any, file: any, fileList: any) => { |
|||
// console.log('uploadError') |
|||
ElMessage.error(file.name + '上传失败') |
|||
control.value.onError && control.value.onError(err, file, fileList) |
|||
} |
|||
// -------------图片上传结束---------------- |
|||
/****input slot处理***/ |
|||
const getInputSlot = (key?: string) => { |
|||
const slot = key === 'p' ? config.value.prepend : config.value.append |
|||
const has = slot.indexOf('key:') === 0 |
|||
if (!has) { |
|||
return false |
|||
} |
|||
const slotKey = slot.replace('key:', '') |
|||
const control = getControlByName(slotKey) |
|||
if (!control || Object.keys(control)?.length === 0) { |
|||
return false |
|||
} |
|||
return control |
|||
} |
|||
const inputSlotChange = (val: string | number, name: string) => { |
|||
changeEvent && |
|||
changeEvent({ |
|||
key: name, |
|||
value: val, |
|||
data: {}, |
|||
tProp: '' |
|||
}) |
|||
} |
|||
|
|||
onMounted(() => { |
|||
getAxiosOptions() |
|||
}) |
|||
onUnmounted(() => {}) |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-03-01 09:07:11 |
|||
@ 功能: 布局处理 |
|||
*/ |
|||
const getFormItemLableStyle = (ele: any) => { |
|||
if(ele?.labelStyle){ |
|||
// console.log("返回栅格宽度3",AnalysisCss(ele?.labelStyle)) |
|||
return AnalysisCss(ele?.labelStyle) |
|||
} |
|||
} |
|||
const getFormItemInputStyle = (ele: any,sty:number) => { |
|||
if(ele?.inputStyle){ |
|||
// console.log("返回栅格宽度4",AnalysisInputCss(ele?.inputStyle,sty)) |
|||
return AnalysisInputCss(ele?.inputStyle,sty) |
|||
} |
|||
} |
|||
const imgUploadApiUrl = import.meta.env.VITE_APP_BASE_API+"/api/upordown" |
|||
|
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-07-27 14:17:16 |
|||
@ 功能: 判断此组件是否可见 |
|||
*/ |
|||
const judgeIsShow = (key:string) => { |
|||
// console.log("判断此组件是否可见---->",key) |
|||
if(props.nodeKey != undefined && props.purview != undefined && props.purview != null && props.purview != null && props.purview != "" && props.purview != "") { |
|||
if(props.purview.length < 1){ |
|||
return true; |
|||
}else{ |
|||
let isShow = false; |
|||
if(Array.isArray(props.purview)){ |
|||
props.purview.forEach((item)=>{ |
|||
if(item.nodeKey == props.nodeKey){ |
|||
|
|||
if(item.powerAry && item.powerAry.length > 0){ |
|||
item.powerAry.forEach((itm)=>{ |
|||
if(itm.id == key){ |
|||
// console.log("判断此组件是否可见",itm,itm.id == key,"--------->",itm.isLook) |
|||
isShow = itm.isLook |
|||
|
|||
} |
|||
}) |
|||
} |
|||
} |
|||
|
|||
}) |
|||
} |
|||
|
|||
return isShow |
|||
} |
|||
}else{ |
|||
return true; |
|||
} |
|||
|
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-07-27 15:11:42 |
|||
@ 功能: 判断是否禁用 |
|||
*/ |
|||
const judgeIsDisabled = (key:string) => { |
|||
if (type.value === 3) { |
|||
return true // 查看模式,为不可编辑状态 |
|||
} |
|||
if (type.value === 1 && config.value.addDisabled) { |
|||
return true |
|||
} |
|||
if (type.value === 2 && config.value.editDisabled) { |
|||
return true // 编辑模式 |
|||
} |
|||
if(props.nodeKey != undefined && props.purview != undefined && props.purview != null && props.purview != null && props.purview != "" && props.purview != "") { |
|||
if(props.purview.length < 1){ |
|||
return false; |
|||
}else{ |
|||
let isShow = true; |
|||
props.purview.forEach((item)=>{ |
|||
if(item.nodeKey == props.nodeKey){ |
|||
|
|||
if(item.powerAry && item.powerAry.length > 0){ |
|||
item.powerAry.forEach((itm)=>{ |
|||
if(itm.id == key){ |
|||
console.log("判断此组件是否禁用",itm,itm.id == key,"--------->",itm.isLook) |
|||
isShow = !itm.isEdit |
|||
|
|||
} |
|||
}) |
|||
} |
|||
} |
|||
|
|||
}) |
|||
return isShow |
|||
} |
|||
}else{ |
|||
return false; |
|||
} |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-02 13:02:49 |
|||
@ 功能: 将时间戳转换成字符串 |
|||
*/ |
|||
const timeToString = (timeVal:any,types:int) => { |
|||
// console.log("将时间戳转换成字符串",timeVal,types) |
|||
let timeStr = "" |
|||
if(Array.isArray(timeVal)){ |
|||
if(timeVal.length >= 2){ |
|||
let startTime = timeToAry(timeVal[0]) |
|||
let endTime = timeToAry(timeVal[1]) |
|||
switch(types){ |
|||
case "year": //年 |
|||
timeStr = `${startTime.year} 至 ${endTime.year}`; |
|||
break; |
|||
case "month": //月 |
|||
timeStr = `${startTime.year}-${startTime.month} 至 ${endTime.year}-${endTime.month}`; |
|||
break; |
|||
case "datetime": //日期+时间 |
|||
timeStr = `${startTime.year}-${startTime.month}-${startTime.day} ${startTime.hours}:${startTime.minutes}:${startTime.seconds} 至 ${endTime.year}-${endTime.month}-${endTime.day} ${endTime.hours}:${endTime.minutes}:${endTime.seconds}`; |
|||
break; |
|||
case "week": //周 |
|||
let startWeek = getYearWeek(startTime) |
|||
let endWeek = getYearWeek(endTime) |
|||
timeStr = `${startWeek} 至 ${endWeek}`; |
|||
break; |
|||
case "timeCalss": //时间 |
|||
timeStr = `${startTime.hours}:${startTime.minutes}:${startTime.seconds} 至 ${endTime.hours}:${endTime.minutes}:${endTime.seconds}`; |
|||
break; |
|||
case "datetimerange": |
|||
timeStr = `${startTime.year}-${startTime.month}-${startTime.day} ${startTime.hours}:${startTime.minutes}:${startTime.seconds} 至 ${endTime.year}-${endTime.month}-${endTime.day} ${endTime.hours}:${endTime.minutes}:${endTime.seconds}`; |
|||
break; |
|||
case "daterange": |
|||
timeStr = `${startTime.year}-${startTime.month}-${startTime.day} 至 ${endTime.year}-${endTime.month}-${endTime.day}`; |
|||
break; |
|||
case "monthrange": |
|||
timeStr = `${startTime.year}-${startTime.month} 至 ${endTime.year}-${endTime.month}`; |
|||
break; |
|||
default: |
|||
timeStr = `${startTime.year}-${startTime.month}-${startTime.day} 至 ${endTime.year}-${endTime.month}-${endTime.day}`; |
|||
break; |
|||
} |
|||
}else if(timeVal.length == 1){ |
|||
let {year,month,day,hours,minutes,seconds} = timeToAry(timeVal[0]) |
|||
switch(types){ |
|||
case "year": //年 |
|||
timeStr = `${year}`; |
|||
break; |
|||
case "month": //月 |
|||
timeStr = `${year}-${month}`; |
|||
break; |
|||
case "datetime": //日期+时间 |
|||
timeStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
|||
break; |
|||
case "week": //周 |
|||
timeStr = getYearWeek(timeVal) |
|||
break; |
|||
case "timeCalss": //时间 |
|||
timeStr = `${hours}:${minutes}:${seconds}`; |
|||
break; |
|||
default: |
|||
timeStr = `${year}-${month}-${day}` |
|||
break; |
|||
} |
|||
}else{ |
|||
timeStr = "未知时间" |
|||
} |
|||
}else{ |
|||
let {year,month,day,hours,minutes,seconds} = timeToAry(timeVal) |
|||
switch(types){ |
|||
case "year": //年 |
|||
timeStr = `${year}`; |
|||
break; |
|||
case "month": //月 |
|||
timeStr = `${year}-${month}`; |
|||
break; |
|||
case "datetime": //日期+时间 |
|||
timeStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
|||
break; |
|||
case "week": //周 |
|||
timeStr = getYearWeek(timeVal) |
|||
break; |
|||
case "timeCalss": //时间 |
|||
timeStr = `${hours}:${minutes}:${seconds}`; |
|||
break; |
|||
default: |
|||
timeStr = `${year}-${month}-${day}` |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return timeStr |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-02 13:22:14 |
|||
@ 功能: 时间戳转换对象 |
|||
*/ |
|||
const timeToAry = (timestamp:number) => { |
|||
const date = new Date(timestamp); |
|||
const year = date.getFullYear(); |
|||
const month = ('0' + (date.getMonth() + 1)).slice(-2); |
|||
const day = ('0' + date.getDate()).slice(-2); |
|||
const hours = ('0' + date.getHours()).slice(-2); |
|||
const minutes = ('0' + date.getMinutes()).slice(-2); |
|||
const seconds = ('0' + date.getSeconds()).slice(-2); |
|||
return { |
|||
year:year, |
|||
month:month, |
|||
day:day, |
|||
hours:hours, |
|||
minutes:minutes, |
|||
seconds |
|||
} |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-02 13:21:05 |
|||
@ 功能: 计算当前时间戳是今年第几周 |
|||
*/ |
|||
const getYearWeek = (timestamp:number) => { |
|||
const date = new Date(timestamp); |
|||
const firstDayOfYear = new Date(date.getFullYear(), 0, 1); |
|||
const pastDaysOfYear = (date - firstDayOfYear) / 86400000; |
|||
const weekNumber = Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7); |
|||
return weekNumber; |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-02 13:42:22 |
|||
@ 功能: 判断单选值 |
|||
*/ |
|||
const judgeRadio = (val:any,list:any) => { |
|||
let valStr = "" |
|||
if(Array.isArray(list)){ |
|||
if(list.length > 0){ |
|||
list.forEach((item) => { |
|||
if(item.value == val){ |
|||
valStr = item.label |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
return valStr |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-02 13:42:22 |
|||
@ 功能: 判断多选值 |
|||
*/ |
|||
const judgeCheckbox = (val:any,list:any) => { |
|||
let valAry = [] |
|||
if(Array.isArray(val)){ |
|||
if(val.length > 0){ |
|||
if(Array.isArray(list)){ |
|||
val.forEach((item) => { |
|||
list.forEach((ltem) => { |
|||
if(item == ltem.value){ |
|||
valAry.push(ltem.label) |
|||
} |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
return valAry |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-05 10:00:31 |
|||
@ 功能: 下拉菜单处理 |
|||
*/ |
|||
const selectValue = (val:any,list:any) => { |
|||
// console.log("下拉菜单处理",val,list) |
|||
let valAry = [] |
|||
if(val && val != "" && val != null ){ |
|||
let pickSelect = val |
|||
if(Array.isArray(val)){ |
|||
pickSelect = val |
|||
}else{ |
|||
pickSelect = JSON.parse(val) |
|||
} |
|||
|
|||
// console.log("下拉菜单处理-----3------->",pickSelect) |
|||
|
|||
|
|||
if(Array.isArray(pickSelect)){ |
|||
if(pickSelect.length > 0){ |
|||
|
|||
if(Array.isArray(list)){ |
|||
pickSelect.forEach((item) => { |
|||
|
|||
list.forEach((ltem) => { |
|||
if(item*1 == ltem.value*1){ |
|||
valAry.push(ltem.label) |
|||
} |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
}else{ |
|||
if(Array.isArray(list)){ |
|||
list.forEach((ltem) => { |
|||
if(val == ltem.value){ |
|||
valAry.push(ltem.label) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
}else{ |
|||
// console.log("下拉菜单处理-4->",val) |
|||
} |
|||
|
|||
// console.log("下拉菜单处理-2->",valAry) |
|||
return valAry |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-08-06 08:34:05 |
|||
@ 功能: 选择用户 |
|||
*/ |
|||
const pickUserVal = (val:any) => { |
|||
// console.log("选择用户-2->",val) |
|||
if(Array.isArray(val)){ |
|||
return val |
|||
}else{ |
|||
// let valAry = string2json(val) |
|||
// console.log("选择用户-2->",valAry) |
|||
return val |
|||
} |
|||
} |
|||
|
|||
|
|||
function asfValueChanged(val:any){ |
|||
//console.log("asfValueChanged",val) |
|||
emits("asfValueChanged",val) |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-09-17 14:30:37 |
|||
@ 功能: 解析下载图片 |
|||
*/ |
|||
const uploadPic = (val:any) => { |
|||
console.log("解析下载图片-->",val) |
|||
if(val != ""){ |
|||
let urlAry = string2json(val) |
|||
// let urlAry = val.toString().split(",") |
|||
console.log("解析下载图片-2->",urlAry) |
|||
return urlAry |
|||
}else{ |
|||
return []; |
|||
} |
|||
} |
|||
</script> |
|||
<template> |
|||
<div></div> |
|||
</template> |
|||
<style lang='scss' scoped> |
|||
|
|||
</style> |
|||
@ -0,0 +1,195 @@ |
|||
<!-- |
|||
@ 作者: 秦东 |
|||
@ 时间: 2023-09-19 13:09:24 |
|||
@ 备注: |
|||
--> |
|||
<script lang='ts' setup> |
|||
import { onMounted, watch, ref, computed, onUnmounted } from 'vue' |
|||
import { ElMessage } from 'element-plus' |
|||
import { newUploadFileApi } from '@/api/file/index' |
|||
|
|||
const props = withDefaults( |
|||
defineProps<{ |
|||
modelValue: string |
|||
placeholder?: string |
|||
width?: string |
|||
height?: string |
|||
blobUrl?: string |
|||
imgUrl?: string |
|||
config?: any |
|||
}>(), |
|||
{ |
|||
modelValue: '', |
|||
placeholder: '请输入内容', |
|||
width: '100%', |
|||
height: '300px', |
|||
blobUrl: '', |
|||
imgUrl: '', |
|||
config: () => { |
|||
return {} |
|||
} |
|||
} |
|||
) |
|||
const emits = defineEmits<{ |
|||
(e: 'update:modelValue', value: string): void |
|||
}>() |
|||
const contentValue = ref(props.modelValue) |
|||
// 参数自定义初始化 |
|||
// eslint-disable-next-line max-len |
|||
const buttonPlugins ='preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media code codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave ' |
|||
// 导入工具栏 |
|||
// eslint-disable-next-line max-len |
|||
const toolbar ='fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor table image | alignleft aligncenter alignright alignjustify outdent indent | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | media charmap emoticons pagebreak insertdatetime print preview | code selectall searchreplace visualblocks | indent2em lineheight formatpainter axupimgs' |
|||
const toolbarSimple ='undo cut copy paste pastetext |forecolor backcolor bold italic underline strikethrough|alignleft aligncenter alignright alignjustify|' |
|||
const commInit = { |
|||
selector: '#myTextarea', |
|||
cleanup: true, |
|||
language: 'zh_CN', // 语言类型 |
|||
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px', // 字体大小 |
|||
lineheight_formats: '0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5', // 行高配置,也可配置成"12px 14px 16px 20px"这种形式 |
|||
branding: false, // tiny技术支持信息是否显示 |
|||
resize: false, // 编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号 |
|||
// statusbar: false, //最下方的元素路径和字数统计那一栏是否显示 |
|||
elementpath: false, // 元素路径是否显示 |
|||
height: props.height, // 允许外界传进来高度和placeholder |
|||
width: props.width, |
|||
placeholder: props.placeholder, |
|||
init_instance_callback: (editor: any) => { |
|||
// editor.setContent('') |
|||
editor.on('NodeChange Change KeyUp SetContent', () => { |
|||
contentValue.value = editor.getContent() |
|||
emits('update:modelValue', editor.getContent()) |
|||
}) |
|||
} |
|||
} |
|||
// 图片上传 |
|||
const imgUploadFn = (blobInfo: any, progress: number) => |
|||
new Promise((resolve, reject) => { |
|||
// https://www.tiny.cloud/docs/tinymce/6/file-image-upload/#images_upload_handler |
|||
// console.log("图片上传",progress) |
|||
const params = new FormData() |
|||
params.append('file', blobInfo.blob()) |
|||
params.append('type',"1") |
|||
let options = {} |
|||
if (props.imgUrl) { |
|||
options = { |
|||
url: props.imgUrl |
|||
} |
|||
} |
|||
newUploadFileApi(params) |
|||
.then(res =>{ |
|||
// console.log("上传图片",res.data) |
|||
resolve(res.data.url) |
|||
}) |
|||
.catch(()=>{ |
|||
reject('上传出错,请查看你上传的文件是否符合要求!') |
|||
}) |
|||
}) |
|||
const fileUpload = (callback: any, value: string, meta: any) => { |
|||
const filetype ='.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4' |
|||
//后端接收上传文件的地址 |
|||
const input = document.createElement('input') //创建文件选择 |
|||
input.setAttribute('type', 'file') |
|||
input.setAttribute('accept', filetype) |
|||
input.click() |
|||
input.onchange = () => { |
|||
const file = input?.files && input.files[0] //获取文件信息 |
|||
let attr = {} |
|||
if (meta.filetype === 'file') { |
|||
attr = { text: file?.name } |
|||
} |
|||
if (meta.filetype === 'image') { |
|||
attr = { alt: file?.name } |
|||
} |
|||
if (meta.filetype === 'media') { |
|||
// attr={source2: 'alt.ogg', poster: 'image.jpg'} |
|||
} |
|||
const params = new FormData() |
|||
params.append('file', file as any) |
|||
let options = {} |
|||
if (props.blobUrl) { |
|||
options = { |
|||
url: props.blobUrl |
|||
} |
|||
} |
|||
newUploadFileApi(params) |
|||
.then(res =>{ |
|||
// console.log("后端接收上传文件的地址",res.data) |
|||
callback(res.data.url, attr) |
|||
}) |
|||
.catch(res => { |
|||
ElMessage.error(res.data?.msg) |
|||
}) |
|||
} |
|||
} |
|||
const defaultInit = { |
|||
plugins: buttonPlugins, // 插件配置 |
|||
toolbar: toolbar, // 工具栏配置,设为false则隐藏 |
|||
menubar: false, // 菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单” |
|||
//emoticons_database_url: './tinymce/emoticons/js/emojis.js', |
|||
// eslint-disable-next-line max-len |
|||
font_formats:'微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;', // 字体样式 微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif, 宋体=simsun,serif,仿宋体=FangSong,黑体=SimHei,Arial=arial, |
|||
// content_style: 'p {margin-block-start: 0; margin-block-end: 0; color: #606D81; font-size: 14px;}; table { border: 1px}', // 直接自定义可编辑区域的css样式 |
|||
content_css: false, // 以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入 |
|||
paste_data_images: true, // 图片是否可粘贴 |
|||
// 允许外界传进来高度和placeholder |
|||
// 粘贴图片 自动处理 base64 |
|||
urlconverter_callback: (url: string, node: string) => { |
|||
if (node === 'img' && url.startsWith('blob:')) { |
|||
// @ts-ignore |
|||
tinymce.activeEditor && tinymce.activeEditor.uploadImages() |
|||
} |
|||
return url |
|||
}, |
|||
// 图片上传 |
|||
images_upload_handler: imgUploadFn, |
|||
file_picker_types: 'file image media', //分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数 |
|||
file_picker_callback: fileUpload |
|||
} |
|||
const simpleInit = { |
|||
plugins: '', // 插件配置 |
|||
toolbar: toolbarSimple, // 工具栏配置,设为false则隐藏 |
|||
menubar: false, // 菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 |
|||
font_formats: '', |
|||
paste_data_images: false // 图片是否可粘贴 |
|||
} |
|||
const myInit = computed(() => { |
|||
const styleType = |
|||
props.config?.style === 'simple' ? simpleInit : defaultInit |
|||
return Object.assign(commInit, styleType) |
|||
}) |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
onMounted(() => { |
|||
// @ts-ignore |
|||
tinymce.init(myInit.value) |
|||
}) |
|||
onUnmounted(() => { |
|||
// @ts-ignore |
|||
tinymce.remove() |
|||
}) |
|||
// 侦听默认值 外界第一次传进来一个 v-model 就赋值给 contentValue |
|||
watch( |
|||
() => props.modelValue, |
|||
(n: any) => { |
|||
if (n && n !== contentValue.value) { |
|||
contentValue.value = n |
|||
} |
|||
} |
|||
) |
|||
</script> |
|||
<template> |
|||
<textarea id="myTextarea" v-model="contentValue"></textarea> |
|||
</template> |
|||
<style lang='scss' scoped> |
|||
.tox-tinymce-aux { |
|||
z-index: 99999 !important; /*el-dialog层为2014,默认时在el弹出层显示不了编辑器里的弹窗*/ |
|||
z-index: 99999; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,900 @@ |
|||
<!-- |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-10-17 09:10:53 |
|||
@ 备注: 手机版页面布局 |
|||
--> |
|||
<script lang='ts' setup> |
|||
import { computed, watch, inject, onUnmounted } from 'vue' |
|||
import Draggable from 'vuedraggable-es' |
|||
// import FormItem from '@/components/DesignForm/public/form/web/formItem.vue' |
|||
import FormItem from './formItem.vue' |
|||
import ChildTable from './childTable.vue' |
|||
import Tooltips from '@/components/DesignForm/tooltip.vue' |
|||
import FlexBox from './flexBox.vue' |
|||
import { useDesignFormStore } from '@/store/DesignForm/designForm' |
|||
import { FormList,formTableInfo } from '@/api/DesignForm/types' |
|||
import { |
|||
constFormBtnEvent, |
|||
constFormProps |
|||
} from '@/api/DesignForm/utils' |
|||
import WebFormGroup from '@/components/DesignForm/public/form/webformGroup.vue' |
|||
import { Md5 } from 'ts-md5'; |
|||
import { jsonParseStringify } from '@/utils/DesignForm' |
|||
import request from '@/utils/request'; |
|||
import { AnalysisCss } from '@/components/DesignForm/public/form/calculate/cssInfo.ts' |
|||
|
|||
const props = withDefaults( |
|||
defineProps<{ |
|||
data: FormList[] |
|||
tableinfo:formTableInfo |
|||
numrun?:number |
|||
nodeKey?:string |
|||
purview?:any[] |
|||
alldata?:any |
|||
}>(), |
|||
{ |
|||
data: () => { |
|||
return [] |
|||
} |
|||
} |
|||
) |
|||
|
|||
let emits = defineEmits(['optionsValue3Get2','asfValueChanged']); |
|||
|
|||
const store = useDesignFormStore() as any //自定义表单存储器 |
|||
const formProps = inject(constFormProps, {}) as any |
|||
const type = computed(() => { //动态计算属性 |
|||
return formProps.value.type |
|||
}) |
|||
const state = reactive({ |
|||
clone: true, // 允许clone |
|||
gridAdd: false |
|||
}) |
|||
const dataList = ref<any>(props.data) |
|||
|
|||
watch( |
|||
() => props.data, |
|||
(v: FormList[]) => { |
|||
dataList.value = v |
|||
// console.log("监听表单变化++++++++++>",v) |
|||
}, |
|||
{ |
|||
deep: true |
|||
} |
|||
) |
|||
const activeKey = computed(() => { |
|||
return store.activeKey |
|||
}) |
|||
// 禁止容器嵌套 |
|||
const notNested = (type: string) => { |
|||
// const controlType = ['grid', 'table', 'tabs', 'div', 'flex', 'card'] |
|||
const controlType = ['grid', 'tabs', 'div', 'card'] |
|||
// let kjkdh = controlType.includes(type) |
|||
// console.log("禁止容器嵌套",kjkdh,controlType) |
|||
return controlType.includes(type) |
|||
// return false |
|||
} |
|||
const notNestedTableFlex = (type: string) => { |
|||
const controlType = ['grid', 'table', 'tabs', 'div', 'flex', 'card'] |
|||
// let kjkdh = controlType.includes(type) |
|||
// console.log("禁止容器嵌套",kjkdh,controlType) |
|||
return controlType.includes(type) |
|||
// return false |
|||
} |
|||
/** |
|||
@ 作者: 秦东 |
|||
@ 时间: 2024-06-22 15:03:31 |
|||
@ 功能: 判断不能重复出现的组件 |
|||
*/ |
|||
const determineDuplicates = (type: string) => { |
|||
const controlType = ["founder","founderTime","editTime","owner","deptOrg"] |
|||
// console.log("判断不能重复出现的组件",dataList); |
|||
if(dataList.value.length > 0){ |
|||
let jibuqi = 0; |
|||
dataList.value.forEach((item:any)=>{ |
|||
// console.log("组件循环",item); |
|||
if(controlType.includes(type)){ |
|||
if(type == item.type){ |
|||
jibuqi++ |
|||
} |
|||
} |
|||
|
|||
}) |
|||
// console.log("组件循环",jibuqi); |
|||
if(jibuqi > 1){ |
|||
ElMessage({ |
|||
showClose: true, |
|||
message: '此类控件在表单中只能出现一次!不可重复添加!', |
|||
type: 'error', |
|||
}) |
|||
return true; |
|||
}else{ |
|||
return false |
|||
} |
|||
}else{ |
|||
return false |
|||
} |
|||
// return controlType.includes(type) |
|||
} |
|||
// 删除或复制 |
|||
const click = (action: string, index: number, item?: any) => { |
|||
if (type.value !== 5) { |
|||
return // 非设计模式 |
|||
} |
|||
if (action === 'clone') { |
|||
const key = item.type + new Date().getTime().toString() |
|||
const newItem = jsonParseStringify(item) |
|||
dataList.value.splice(index, 0, Object.assign(newItem, { name: key })) |
|||
} else if (action === 'del') { |
|||
dataList.value.splice(index, 1) |
|||
// 清空右侧栏信息 |
|||
store.setActiveKey('') |
|||
store.setControlAttr({}) |
|||
} else if (action === 'gridAdd') { |
|||
item.columns.push({ |
|||
list: [], |
|||
attr: { span: 12 } |
|||
}) |
|||
} else if (action === 'delGridChild') { |
|||
item.splice(index, 1) |
|||
} |
|||
} |
|||
const draggableAdd = (evt: any) => { |
|||
if (type.value !== 5) { |
|||
return // 非设计模式 |
|||
} |
|||
const newIndex = evt.newIndex |
|||
const key = new Date().getTime().toString() |
|||
const obj: any = dataList.value[newIndex] |
|||
const isNested = evt.target && evt.target.getAttribute('data-type') // 不能嵌套 |
|||
// console.log("设计拖拽事件-----1------->",newIndex) |
|||
// console.log("设计拖拽事件-----2------->",key) |
|||
// console.log("设计拖拽事件-----3------->",obj) |
|||
// console.log("设计拖拽事件-----4------->",isNested) |
|||
// console.log("设计拖拽事件-----4------->",dataList.value) |
|||
if ((isNested === 'not-nested' && notNested(obj.type)) || ((isNested === 'not-table' || isNested === 'not-flex') && notNestedTableFlex(obj.type)) || determineDuplicates(obj.type)) { |
|||
dataList.value.splice(newIndex, 1) |
|||
return |
|||
} |
|||
if (!obj) { |
|||
return |
|||
} |
|||
const label = obj.label || obj.item.label |
|||
delete obj.label |
|||
delete obj.icon |
|||
let objectItem = {} |
|||
// 不需要添加item的项 |
|||
const notNeedItem = [ |
|||
'txt', |
|||
'title', |
|||
'button', |
|||
'table', |
|||
'grid', |
|||
'tabs', |
|||
'flex', |
|||
'div' |
|||
] |
|||
// console.log("非设计模式-->",obj.type) |
|||
if (!notNeedItem.includes(obj.type)) { |
|||
objectItem = { |
|||
item: { |
|||
label: label |
|||
} |
|||
} |
|||
} |
|||
// 不需要name的组件 |
|||
let nameObj = {} |
|||
const notNeedName = [ |
|||
'txt', |
|||
'title', |
|||
'button', |
|||
'grid', |
|||
'tabs', |
|||
'divider', |
|||
'div', |
|||
'card' |
|||
] |
|||
switch(obj.type){ |
|||
case "founder": |
|||
nameObj = { |
|||
name: "creater" |
|||
} |
|||
// console.log("founder--->creater",nameObj) |
|||
break |
|||
case "founderTime": |
|||
nameObj = { |
|||
name: "creater_time" |
|||
} |
|||
// console.log("founderTime-->creater_time",nameObj) |
|||
break |
|||
case "editTime": |
|||
nameObj = { |
|||
name: "edit_time" |
|||
} |
|||
// console.log("editTime--->edit_time",nameObj) |
|||
break |
|||
case "owner": |
|||
nameObj = { |
|||
name: "owner" |
|||
} |
|||
// console.log("owner------>owner",nameObj) |
|||
break |
|||
case "deptOrg": |
|||
nameObj = { |
|||
name:"org" |
|||
} |
|||
// console.log("deptOrg---->org",nameObj) |
|||
break |
|||
default: |
|||
if (!notNeedName.includes(obj.type) && !obj.name) { |
|||
nameObj = { |
|||
name: obj.type + key |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
// console.log("设计拖拽事件-----5------->",obj) |
|||
// console.log("设计拖拽事件-----6------->",nameObj) |
|||
// console.log("设计拖拽事件-----7------->",objectItem) |
|||
|
|||
Object.assign(obj, nameObj, objectItem) |
|||
// console.log("设计拖拽事件-----8------->",obj) |
|||
groupClick(obj) |
|||
} |
|||
const getGroupName = (item: any) => { |
|||
if (item.name) { |
|||
return item.name |
|||
} else { |
|||
let md5Object:any = new Md5() |
|||
md5Object.appendAsciiStr(JSON.stringify(item)) |
|||
let md5Str = md5Object.end() |
|||
return md5Str |
|||
} |
|||
} |
|||
// 点击激活当前 |
|||
/** |
|||
* styles:{ |
|||
divStyle:{}, |
|||
labelStyle:{}, |
|||
inputStyle:{} |
|||
} |
|||
*/ |
|||
const groupClick = (item: any, ele?: string) => { |
|||
// 设计模式下才执行 |
|||
if (type.value !== 5) { |
|||
return |
|||
} |
|||
if (ele) { |
|||
item.type = ele |
|||
} |
|||
if(!item.styles){ |
|||
item.styles={ |
|||
divStyle:{}, |
|||
labelStyle:{}, |
|||
inputStyle:{} |
|||
} |
|||
} |
|||
// console.log("点击激活当前--->",getGroupName(item)) |
|||
store.setActiveKey(getGroupName(item)) |
|||
store.setControlAttr(item) |
|||
// grid时显示添加列按钮 |
|||
state.gridAdd = item.type === 'grid' |
|||
// state.clone = !notNested(item.type) |
|||
state.clone = !notNestedTableFlex(item.type) |
|||
} |
|||
// 返回栅格宽度 |
|||
const getFormItemStyle = (ele: FormList) => { |
|||
let styleClass = {} |
|||
// console.log("返回栅格宽度311---->",ele) |
|||
if (ele.config?.span === 0) { |
|||
styleClass['width'] = "auto" |
|||
styleClass['margin'] = "0 5px" |
|||
// return { width: 'auto', margin: '0 5px' } |
|||
} |
|||
if (ele.config && ele.config.span) { |
|||
// return { width: (ele.config.span / 24) * 100 + '%' } |
|||
styleClass['width'] = "100%" |
|||
// return "100%" |
|||
} |
|||
if(ele.styles?.divStyle){ |
|||
// console.log("返回栅格宽度3",AnalysisCss(ele.styles.divStyle)) |
|||
let styleObject = AnalysisCss(ele.styles.divStyle) |
|||
if(Object.keys(styleObject).length > 0){ |
|||
Object.keys(styleObject).forEach((key:string)=>{ |
|||
// console.log("返回栅格宽度110-"+key+"--->",styleObject[key]) |
|||
styleClass[key] = styleObject[key] |
|||
}) |
|||
} |
|||
return AnalysisCss(ele.styles.divStyle) |
|||
} |
|||
return styleClass |
|||
} |
|||
// 根据关联条件显示隐藏当前项 |
|||
const linksShow = (el: FormList, index: number) => { |
|||
|
|||
/* |
|||
|
|||
*/ |
|||
// 当前项设置了关联条件,当关联主体的值等于当前组件设定的值时 |
|||
if (!el.config) { |
|||
return true |
|||
} |
|||
const key = el.config.linkKey |
|||
//liwenxuan 关联选项设置效果实现 |
|||
//console.log("linksShow--------"+index+"--------"+JSON.stringify(el)) |
|||
//仅第一次加载会触发,须将出现在配置条件中的表单项隐藏。 |
|||
|
|||
const value = el.config.linkValue |
|||
const linkResult = el.config.linkResult |
|||
if (key && value && type.value !== 5) { |
|||
const Fn = new Function('$', `return (${value})`) |
|||
// console.log(Fn) |
|||
const pass = Fn(formProps.value.model) |
|||
if (linkResult === 'disabled') { |
|||
// 设置为disabled后返回显示状态 |
|||
dataList.value[index].control.disabled = pass |
|||
return true |
|||
} else { |
|||
return pass |
|||
} |
|||
} |
|||
return true |
|||
} |
|||
// 根据表单设置不显示指定字段 |
|||
const linksIf = (obj: FormList) => { |
|||
const { type } = formProps.value |
|||
const { config: { disabledAdd, disabledEdit, disabledDetail } = {} } = obj |
|||
if (type === 1) { |
|||
if (disabledAdd) { |
|||
// 编辑页 || 新增页 |
|||
return false // 不显示 |
|||
} |
|||
} else if (type === 2) { |
|||
// 编辑 |
|||
if (disabledEdit) { |
|||
return false |
|||
} |
|||
} else if (type === 4 || type === 3) { |
|||
// 查看 |
|||
if (disabledDetail) { |
|||
return false |
|||
} |
|||
} |
|||
// 如果当前字段的name值存在于表单数据的vIf中,则不显示 |
|||
const vIf: string | string[] = formProps.value.hideField |
|||
if (vIf?.length > 0 && obj.name) { |
|||
return vIf.indexOf(obj.name) === -1 // 存在时返回false隐藏 |
|||
} |
|||
return true |
|||
} |
|||
//按钮点击事件 |
|||
const injectBtnEvent:any = inject(constFormBtnEvent) |
|||
const clickBtn = (control: any) => { |
|||
// console.log(control) |
|||
// 0: '提交表单', |
|||
// 1: '重置表单', |
|||
// 2: '取消返回', |
|||
// 3: '无动作(自定义)' |
|||
if (type.value !== 5) { |
|||
// 非设计模式才触发事件 |
|||
injectBtnEvent && injectBtnEvent(control) |
|||
} |
|||
} |
|||
onUnmounted(() => { |
|||
|
|||
dataList.value = {} |
|||
store.setActiveKey('') |
|||
store.setControlAttr({}) |
|||
}) |
|||
const asfs: any[] = [] |
|||
const tables: any[] = [] |
|||
onMounted(()=>{ |
|||
// console.log('非设计模式才触发事件',props.nodeKey,"---------------->",props.purview) |
|||
// console.log('formGroup onMounted',props.data,dataList.value,props.tableinfo) |
|||
|
|||
|
|||
|
|||
setTimeout(()=>{ |
|||
if(dataList&&Array.isArray(dataList.value)&&dataList.value.length>0){ |
|||
for(let i = 0;i<dataList.value.length;i++){ |
|||
if(dataList.value[i].type=="associatedForms"){ |
|||
asfs.push(dataList.value[i]) |
|||
}else if(dataList.value[i].type=="card"||dataList.value[i].type=="flex"||dataList.value[i].type=="div"||dataList.value[i].type=="table"){ |
|||
|
|||
if(dataList.value[i].type=="table"){ |
|||
tables.push(dataList.value[i]) |
|||
} |
|||
|
|||
dataList.value[i].list.forEach((element:any) => { |
|||
if(element.type=="associatedForms"){ |
|||
asfs.push(element) |
|||
} |
|||
}); |
|||
}else if(dataList.value[i].type=="grid"){ |
|||
let columns = JSON.parse(JSON.stringify(dataList.value[i].columns)); |
|||
//console.log(columns) |
|||
if(columns.length>0){ |
|||
for(let z = 0;z<columns.length;z++){ |
|||
for(let x = 0; x<columns[z].list.length;x++){ |
|||
let a = JSON.parse(JSON.stringify(columns[z].list[x])); |
|||
//console.log(a) |
|||
if(a.type=="associatedForms"){ |
|||
asfs.push(a) |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
}else if(dataList.value[i].type=="tabs"){//tabs标签页有可能再嵌套一层flex或者table |
|||
let columns = JSON.parse(JSON.stringify(dataList.value[i].columns)); |
|||
if(columns.length>0){ |
|||
for(let z = 0;z<columns.length;z++){ |
|||
for(let x = 0; x<columns[z].list.length;x++){ |
|||
let a = JSON.parse(JSON.stringify(columns[z].list[x])); |
|||
//console.log(a) |
|||
if(a.type=="associatedForms"){ |
|||
asfs.push(a) |
|||
}else if(a.type=="flex"||a.type=="table"){ |
|||
|
|||
if(a.type=="table"){ |
|||
tables.push(dataList.value[i]) |
|||
} |
|||
|
|||
if(a.list.length>0){ |
|||
for(let m = 0;m<a.list.length;m++){ |
|||
let q = JSON.parse(JSON.stringify(a.list[m])) |
|||
//console.log(q) |
|||
if(q.type=="associatedForms"){ |
|||
asfs.push(q) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
/* if(asfs.length>0){ |
|||
//console.log(asfs) |
|||
} */ |
|||
/* if(tables.length>0){ |
|||
console.log(tables) |
|||
} */ |
|||
} |
|||
},500) |
|||
}) |
|||
function getNewObject(obj:any, arr:any) { |
|||
//console.log(obj) |
|||
//console.log(arr) |
|||
let key = arr[0]; |
|||
let newKey = arr[1]; |
|||
if (obj[key]) { |
|||
return { [newKey]: obj[key] }; |
|||
} |
|||
return {}; |
|||
} |
|||
function asfValueChanged(val:any){ |
|||
|
|||
/* console.log("asfValueChanged",val) |
|||
console.log(val.currentVal) |
|||
console.log(val.fillFieldsMaster) |
|||
console.log(val.fillFieldsChild) */ |
|||
let fillFieldsMaster = "" |
|||
let masterFillRoleFieldsArray1: any[] = []; |
|||
|
|||
if(val.fillFieldsMaster.length>0){ |
|||
fillFieldsMaster = val.fillFieldsMaster.substring(0, val.fillFieldsMaster.length - 1); |
|||
let masterFillRoleFieldsArray = fillFieldsMaster.split(";"); |
|||
//console.log(masterFillRoleFieldsArray) |
|||
masterFillRoleFieldsArray.forEach((item:any)=>{ |
|||
let itemArray = item.split("_"); |
|||
itemArray.splice(0, 1); |
|||
|
|||
itemArray = itemArray.map((item1:any) => item1.split(':').pop()); |
|||
//console.log(itemArray) |
|||
masterFillRoleFieldsArray1.push(itemArray) |
|||
|
|||
}) |
|||
|
|||
} |
|||
|
|||
if(val.fillFieldsChild.length>0){ |
|||
/* console.log(val.asfFormId) |
|||
console.log(val.masterOnField) */ |
|||
let fillFieldsChild = JSON.parse(val.fillFieldsChild); |
|||
if (fillFieldsChild && fillFieldsChild.length > 0) { |
|||
fillFieldsChild = fillFieldsChild.filter((element:any)=>{ |
|||
if(containsDangerousWords(element.filterCondition.gongShi.mathsFormula)){ |
|||
//alert("筛选条件非法") |
|||
console.log("筛选条件非法===>"+element.filterCondition.conditionHtml) |
|||
}else{ |
|||
return element |
|||
} |
|||
}) |
|||
} |
|||
//console.log(fillFieldsChild) |
|||
getAsfTableFill(val.asfFormId,val.glbbddbd,val.currentVal,fillFieldsChild).then(({ data }) => { |
|||
//console.log(data) |
|||
if(data&&data.length>0){ |
|||
data.forEach((dataElement:any) => { |
|||
tables.forEach((tableItem: any) => { |
|||
if(dataElement.tableName==tableItem.name){ |
|||
//console.log(formProps.value.model) |
|||
//console.log(tableItem) |
|||
//console.log(dataElement) |
|||
let tableName = dataElement.tableName |
|||
//console.log(tableName) |
|||
if(tableItem.list.length>0){ |
|||
let tableRowArray: { type: any; name: any }[] = [] |
|||
tableItem.list.forEach((listItem:any) => { |
|||
//console.log(listItem) |
|||
tableRowArray.push({ |
|||
type:listItem.type, |
|||
name:listItem.name |
|||
}) |
|||
}); |
|||
//console.log(tableRowArray) |
|||
const result = generateXResult(dataElement, tableRowArray); |
|||
//console.log(result); |
|||
formProps.value.model[tableName] = result |
|||
} |
|||
|
|||
} |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
}); |
|||
} |
|||
|
|||
|
|||
//emits("asfValueChanged",val) |
|||
if(val.options.length>0){ |
|||
//console.log(val.options) |
|||
if(val.options[0].fillRolesFieldsMap){ |
|||
val.options.forEach((item:any)=>{ |
|||
if(item.fillRolesFieldsMap.value == val.currentVal){ |
|||
|
|||
if(masterFillRoleFieldsArray1.length>0){ |
|||
masterFillRoleFieldsArray1.forEach((item1:any)=>{ |
|||
//console.log(item.fillRolesFieldsMap) |
|||
//console.log(item1) |
|||
let x = convertObjectToArray(getNewObject(item.fillRolesFieldsMap,item1)) |
|||
//console.log(x) |
|||
let strOrNumber = convertToStringOrNumber(x[1]) |
|||
let strOrNumberOrArray |
|||
if(isString(strOrNumber)&&strOrNumber.includes("[")){ |
|||
strOrNumberOrArray = convertIfValidNumberArray(strOrNumber) |
|||
} |
|||
|
|||
/* console.log(x[1]) |
|||
console.log(strOrNumberOrArray) |
|||
console.log(formProps.value.model[x[0]]) */ |
|||
if(strOrNumberOrArray){ |
|||
formProps.value.model[x[0]] = strOrNumberOrArray |
|||
}else{ |
|||
formProps.value.model[x[0]] = strOrNumber |
|||
} |
|||
|
|||
//console.log(formProps.value.model[x[0]]) |
|||
|
|||
}) |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
}) |
|||
} |
|||
} |
|||
} |
|||
|
|||
interface DetailObject { |
|||
[key: string]: any |
|||
} |
|||
|
|||
interface TableRow { |
|||
type: string; |
|||
name: string; |
|||
} |
|||
|
|||
function generateXResult(dataElement: { tableDetail: DetailObject[] }, tableRowArray: TableRow[]): DetailObject[] { |
|||
const xResult: DetailObject[] = []; |
|||
const propertyNames = tableRowArray.map(item => item.name); |
|||
for (const detail of dataElement.tableDetail) { |
|||
const obj: DetailObject = {}; |
|||
propertyNames.forEach(name => { |
|||
let strOrNumber = convertToStringOrNumber(detail[name]) |
|||
let strOrNumberOrArray |
|||
if(isString(strOrNumber)&&strOrNumber.includes("[")){ |
|||
strOrNumberOrArray = convertIfValidNumberArray(strOrNumber) |
|||
} |
|||
if(strOrNumberOrArray){ |
|||
obj[name] = strOrNumberOrArray |
|||
}else{ |
|||
obj[name] = strOrNumber |
|||
} |
|||
}); |
|||
xResult.push(obj); |
|||
} |
|||
return xResult; |
|||
} |
|||
function getAsfTableFill(asfFormId:any,glbbddbd:any,currentVal:any,fillFieldsChild:any){ |
|||
/* console.log(asfFormId) |
|||
console.log(glbbddbd) |
|||
console.log(fillFieldsChild) */ |
|||
/* asfFormId = JSON.stringify(asfFormId) |
|||
glbbddbd = JSON.stringify(glbbddbd) |
|||
currentVal = JSON.stringify(currentVal) */ |
|||
fillFieldsChild = JSON.stringify(fillFieldsChild) |
|||
return request({ |
|||
url: '/javasys/lowCode/AssociatedForms/getAsfTableFill', |
|||
method: 'post', |
|||
data: { |
|||
asfFormId:asfFormId, |
|||
glbbddbd:glbbddbd, |
|||
currentVal:currentVal, |
|||
fillFieldsChild:fillFieldsChild, |
|||
}, |
|||
}); |
|||
} |
|||
function containsDangerousWords(str: string | undefined): boolean { |
|||
if (str === undefined) { |
|||
return false; |
|||
} |
|||
const dangerousWords = new Set<string>([ |
|||
"drop", |
|||
"table", |
|||
"where", |
|||
"select", |
|||
"insert", |
|||
"update", |
|||
"delete", |
|||
"and", |
|||
"or", |
|||
"union", |
|||
"order by", |
|||
"group by", |
|||
"having", |
|||
"exec", |
|||
"execute", |
|||
]); |
|||
const words = str.split(" "); |
|||
for (const word of words) { |
|||
if (dangerousWords.has(word.toLowerCase())) { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
function isString(value: any): value is string { |
|||
return typeof value === 'string'; |
|||
} |
|||
function convertIfValidNumberArray(str: string): number[] | null { |
|||
const regex = /^\[(\d+(,\d+)*)?\]$/; |
|||
if (regex.test(str)) { |
|||
const numbersStr = str.slice(1, -1); |
|||
if (numbersStr.length === 0) { |
|||
return []; |
|||
} |
|||
return numbersStr.split(',').map(item => Number(item)); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
function convertToStringOrNumber(str: string): number | string { |
|||
const isOnlyNumbers = /^\d+$/.test(str); |
|||
return isOnlyNumbers? Number(str) : str; |
|||
} |
|||
function convertObjectToArray(obj:any) { |
|||
for (let key in obj) { |
|||
return [key, obj[key]]; |
|||
} |
|||
return []; |
|||
} |
|||
const getFormItemLableStyle = (ele: any) => { |
|||
if(ele?.labelStyle){ |
|||
// console.log("返回栅格宽度3",AnalysisCss(ele)) |
|||
return AnalysisCss(ele?.labelStyle) |
|||
} |
|||
} |
|||
|
|||
function optionsValue3Get1(data: any,fieldName: string){ |
|||
emits('optionsValue3Get2',data,fieldName) |
|||
} |
|||
/* |
|||
|
|||
*/ |
|||
</script> |
|||
<template> |
|||
<draggable |
|||
itemKey="id" |
|||
:list="dataList" |
|||
name="fade" |
|||
class="drag" |
|||
v-bind="{ |
|||
group: 'form', |
|||
ghostClass: 'ghost', |
|||
animation: 200, |
|||
handle: '.drag-move', |
|||
disabled: type !== 5 |
|||
}" |
|||
@add="draggableAdd" |
|||
> |
|||
<template #item="{ element, index }"> |
|||
<div |
|||
class="group" |
|||
:class="{ |
|||
['group-' + element.type]: true, |
|||
active: activeKey === getGroupName(element) |
|||
}" |
|||
:style="getFormItemStyle(element)" |
|||
@click.stop="groupClick(element)" |
|||
v-show="linksShow(element, index)" |
|||
v-if="linksIf(element)" |
|||
> |
|||
<!--选项卡组件--> |
|||
<template v-if="element.type === 'tabs'"> |
|||
<div class="form-tabs"> |
|||
<el-tabs |
|||
v-bind="element.control" |
|||
:class="[element.config?.className]" |
|||
> |
|||
<el-tab-pane |
|||
v-for="(item, tIndex) in element.columns" |
|||
:label="item.label" |
|||
:key="tIndex" |
|||
> |
|||
<WebFormGroup :data="item.list" data-type="not-nested" /> |
|||
</el-tab-pane> |
|||
</el-tabs> |
|||
</div> |
|||
</template> |
|||
<!--标题组件--> |
|||
<template v-else-if="element.type === 'title'"> |
|||
<div |
|||
class="title" |
|||
:class="[element.config.className]" |
|||
v-bind="element.control" |
|||
:style="getFormItemLableStyle(element.styles)" |
|||
> |
|||
<span v-html="element.control.modelValue"></span> |
|||
<Tooltips |
|||
:content="element.config.help" |
|||
v-if="element.config.help" |
|||
/> |
|||
</div> |
|||
</template> |
|||
<!--文字组件--> |
|||
<template v-else-if="element.type === 'txt'"> |
|||
<div |
|||
v-bind="element.control" |
|||
:class="[element.config.className]" |
|||
v-html="element.control.modelValue" |
|||
> |
|||
</div> |
|||
</template> |
|||
<!--表格组件--> |
|||
<template v-else-if="element.type === 'table'"> |
|||
</template> |
|||
<!--格栅布局--> |
|||
<template v-else-if="element.type === 'grid'"> |
|||
<el-row class="form-row" :style="type === 5?'padding: 0 0 20px 0;':''" :class="[element.className]"> |
|||
|
|||
<el-col |
|||
class="form-col" |
|||
:class="{ |
|||
'active-col': activeKey === getGroupName(col), |
|||
[col.className]: col.className |
|||
}" |
|||
|
|||
v-for="(col, i) in element.columns" |
|||
:key="i" |
|||
@click.stop="groupClick(col, 'gridChild')" |
|||
> |
|||
<WebFormGroup :data="col.list" data-type="not-nested" /> |
|||
<div class="drag-control" v-if="type === 5"> |
|||
<div class="item-control"> |
|||
<i |
|||
class="icon-del" |
|||
@click.stop="click('delGridChild', i as number, element.columns)" |
|||
> |
|||
</i> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
</template> |
|||
<!--卡片布局--> |
|||
<template v-else-if="element.type === 'card'"> |
|||
<el-collapse model-value="1"> |
|||
<el-collapse-item :title="element.item.label" name="1"> |
|||
<template #title v-if="element.help"> |
|||
{{ element.item.label }} |
|||
<Tooltips :content="element.help" /> |
|||
</template> |
|||
<WebFormGroup :data="element.list" data-type="not-nested" /> |
|||
</el-collapse-item> |
|||
</el-collapse> |
|||
</template> |
|||
<!--div容器--> |
|||
<template v-else-if="element.type === 'div'"> |
|||
<div |
|||
class="div-layout" |
|||
v-bind="element.control" |
|||
|
|||
> |
|||
<WebFormGroup :data="element.list" data-type="not-nested" /> |
|||
</div> |
|||
</template> |
|||
<!--弹性布局--> |
|||
<template v-else-if="element.type === 'flex'"> |
|||
|
|||
<WebFormGroup |
|||
:data="element.list" |
|||
data-type="not-flex" |
|||
v-if="type === 5" |
|||
/> |
|||
<flex-box :data="element" v-else /> |
|||
<el-button |
|||
style="position: relative; top: -28px; left: 10px" |
|||
v-if="element.config.addBtnText && type === 5" |
|||
size="small" |
|||
> |
|||
{{ element.config.addBtnText }} |
|||
</el-button> |
|||
</template> |
|||
<!--按钮--> |
|||
<template v-else-if="element.type === 'button'"> |
|||
<div |
|||
:class="[element.config?.className]" |
|||
:style="{ 'text-align': element.config?.textAlign }" |
|||
> |
|||
<el-button |
|||
v-bind="element.control" |
|||
@click="clickBtn(element.control)" |
|||
color="#626aef" |
|||
> |
|||
<td :style="getFormItemLableStyle(element.styles)">{{ element.control?.label }}</td> |
|||
</el-button> |
|||
</div> |
|||
</template> |
|||
<!--分割线--> |
|||
<template v-else-if="element.type === 'divider'"> |
|||
<el-divider v-bind="element.control">{{ element.item && element.item.label }}</el-divider> |
|||
</template> |
|||
<!--其他组件--> |
|||
<FormItem v-else :data="element" @optionsValue3Get1="optionsValue3Get1" :purview="props.purview" :node-key="props.nodeKey" :tablekey="props.tableinfo" :numrun="props.numrun" @asf-value-changed="asfValueChanged" /> |
|||
|
|||
<!--组件设计外功能框架--> |
|||
<template v-if="type === 5"> |
|||
<div class="drag-control"> |
|||
<div class="item-control"> |
|||
<i |
|||
class="icon-plus" |
|||
@click.stop="click('gridAdd', index, element)" |
|||
v-if="state.gridAdd" |
|||
title="添加列" |
|||
></i> |
|||
<i |
|||
class="icon-clone" |
|||
@click.stop="click('clone', index, element)" |
|||
v-if="state.clone" |
|||
title="克隆" |
|||
></i> |
|||
<i class="icon-del" @click.stop="click('del', index)"></i> |
|||
</div> |
|||
<div class="drag-move icon-move"></div> |
|||
</div> |
|||
<!-- <div class="tooltip" style="display: black;">{{ element.name }}</div> --> |
|||
<div class="tooltip" style="display: black;"></div> |
|||
</template> |
|||
</div> |
|||
</template> |
|||
</draggable> |
|||
</template> |
|||
<style lang='scss' scoped> |
|||
|
|||
</style> |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue