|
|
import formBuilderMap from "./formBuilderMap";
|
|
|
import { CreateElement, VNode } from "vue";
|
|
|
import moment from "moment";
|
|
|
import { getToken } from "@/utils/auth";
|
|
|
import {deepCopy, formatFileSize, formatTime} from "@/utils/index";
|
|
|
import { uploadSize } from "@/settings";
|
|
|
import axios from 'axios';
|
|
|
import { flowList } from "@/api/flow";
|
|
|
/**
|
|
|
* @param {String} device 'desktop' | 'mobile'
|
|
|
* @param {Object} info field参数
|
|
|
* @param {CreateElement} h
|
|
|
* @param {Object} row 子表单的row
|
|
|
* @param {Boolean} pWrite 主表单中子表单字段是否可写
|
|
|
* @param {Boolean} pReadable
|
|
|
* @return {VNode} 主表单包含el-form-item 子表单表单组件
|
|
|
**/
|
|
|
export default function formBuilder(device, info, h, row, pWrite = false,pReadable = false,pname) {
|
|
|
let target = row ? row : this.form
|
|
|
let formItem;
|
|
|
//下拉选项
|
|
|
let options = [];
|
|
|
if (info?.selection_model) {
|
|
|
options = info.selection_model_items || [];
|
|
|
} else if (info?.stub) {
|
|
|
options = info?.stub?.split(/\r\n/) || [];
|
|
|
}
|
|
|
if (device === "desktop") {
|
|
|
// 可写并且不为查看和子表单下
|
|
|
if (
|
|
|
info._writeable ||
|
|
|
(info.type === "relation" && info._readable) ||
|
|
|
pWrite
|
|
|
) {
|
|
|
switch (info.type) {
|
|
|
case "text":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {
|
|
|
props: {
|
|
|
value: target[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e)
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "textarea":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {
|
|
|
props: {
|
|
|
type: "textarea",
|
|
|
autosize: {
|
|
|
minRows: 2,
|
|
|
},
|
|
|
value: target[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e)
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "date":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {
|
|
|
props: {
|
|
|
type: "date",
|
|
|
"value-format": "yyyy-MM-dd",
|
|
|
format: "yyyy年MM月dd日",
|
|
|
value: target[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
"picker-options": {
|
|
|
shortcuts: [
|
|
|
{
|
|
|
text: "一年前",
|
|
|
onClick(picker) {
|
|
|
picker.$emit(
|
|
|
"pick",
|
|
|
moment().subtract(1, "years").toDate()
|
|
|
);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: "一月前",
|
|
|
onClick(picker) {
|
|
|
picker.$emit(
|
|
|
"pick",
|
|
|
moment().subtract(1, "months").toDate()
|
|
|
);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: "一周前",
|
|
|
onClick(picker) {
|
|
|
picker.$emit(
|
|
|
"pick",
|
|
|
moment().subtract(1, "weeks").toDate()
|
|
|
);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: "今天",
|
|
|
onClick(picker) {
|
|
|
picker.$emit("pick", new Date());
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: "一周后",
|
|
|
onClick(picker) {
|
|
|
picker.$emit("pick", moment().add(1, "weeks").toDate());
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: "一月后",
|
|
|
onClick(picker) {
|
|
|
picker.$emit("pick", moment().add(1, "months").toDate());
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
text: "一年后",
|
|
|
onClick(picker) {
|
|
|
picker.$emit("pick", moment().add(1, "years").toDate());
|
|
|
},
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
style: {
|
|
|
width: "100%",
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e)
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "datetime":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {
|
|
|
props: {
|
|
|
type: "datetime",
|
|
|
"value-format": "yyyy-MM-dd HH:mm:ss",
|
|
|
format: this.datetimeFormat,
|
|
|
value: target[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
"picker-options": {
|
|
|
shortcuts: this.shortcuts
|
|
|
},
|
|
|
},
|
|
|
style: {
|
|
|
width: "100%",
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e)
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "choice":
|
|
|
case "select":
|
|
|
const getSelectValue = () => {
|
|
|
if (!!info.multiple) {
|
|
|
return target[info.name] ? target[info.name].toString()?.split(/,|\|/).map(i => isNaN(Number(i)) ? i : Number(i)) : []
|
|
|
} else {
|
|
|
return (isNaN(Number(target[info.name])) || !target[info.name]) ? target[info.name] : Number(target[info.name])
|
|
|
}
|
|
|
}
|
|
|
console.log(info.name, getSelectValue(), target[info.name])
|
|
|
formItem = h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
value: getSelectValue(),
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
multiple: !!info.multiple,
|
|
|
'multiple-limit': info.multiple,
|
|
|
'collapse-tags': true,
|
|
|
filterable: true,
|
|
|
'value-key': 'id',
|
|
|
'allow-create': !!info.is_select2_tag,
|
|
|
'default-first-option': true
|
|
|
},
|
|
|
style: {
|
|
|
width: "100%",
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e.toString())
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
options.map((option) =>
|
|
|
h("el-option", {
|
|
|
key: typeof option === "object" ? option.id : option,
|
|
|
props: {
|
|
|
label: typeof option === "object" ? option.name : option,
|
|
|
value: typeof option === "object" ? option.id : option,
|
|
|
},
|
|
|
})
|
|
|
)
|
|
|
);
|
|
|
break;
|
|
|
case "radio":
|
|
|
formItem = h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
value: target[info.name],
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e)
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
options.map((option) =>
|
|
|
h(
|
|
|
"el-radio",
|
|
|
{
|
|
|
props: {
|
|
|
label: typeof option === "object" ? option.id : option,
|
|
|
},
|
|
|
},
|
|
|
typeof option === "object" ? option.name : option
|
|
|
)
|
|
|
)
|
|
|
);
|
|
|
break;
|
|
|
case "file":
|
|
|
formItem = row ?
|
|
|
h(
|
|
|
'vxe-upload',
|
|
|
{
|
|
|
props: {
|
|
|
value: row[info.name],
|
|
|
'progress-text': "{percent}%",
|
|
|
'more-config': { maxCount: 1, layout: 'horizontal' },
|
|
|
'show-button-text': false,
|
|
|
'limit-size': uploadSize / 1024 / 1024, // vxeupload 单位Mb
|
|
|
'limit-count': info.multiple ? 20 : 1,
|
|
|
multiple: !!info.multiple,
|
|
|
'name-field': 'original_name',
|
|
|
readonly: pReadable,
|
|
|
'upload-method': ({ file }) => {
|
|
|
const formData = new FormData()
|
|
|
formData.append('file', file)
|
|
|
window.$_uploading = true
|
|
|
return axios.post(process.env.VUE_APP_UPLOAD_API, formData, {
|
|
|
headers: {
|
|
|
Authorization: `Bearer ${getToken()}`,
|
|
|
}
|
|
|
}).then((response) => {
|
|
|
window.$_uploading = false
|
|
|
if (response.status === 200 && !response.data.code) {
|
|
|
if (!(row[info.name] instanceof Array)) {
|
|
|
row[info.name] = []
|
|
|
}
|
|
|
row[info.name].push({
|
|
|
response: response.data.data,
|
|
|
name: response.data.data.original_name,
|
|
|
url: response.data.data.url,
|
|
|
original_name: response.data.data.original_name
|
|
|
})
|
|
|
if (row[info.name].length > (info.multiple ? 20 : 1)) {
|
|
|
row[info.name].shift()
|
|
|
}
|
|
|
} else {
|
|
|
this.$message.error("上传失败")
|
|
|
}
|
|
|
}).catch(err => {
|
|
|
window.$_uploading = false
|
|
|
})
|
|
|
},
|
|
|
'remove-method': _ => {
|
|
|
row[info.name] = []
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
) :
|
|
|
h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
action: process.env.VUE_APP_UPLOAD_API,
|
|
|
headers: {
|
|
|
Authorization: `Bearer ${getToken()}`,
|
|
|
},
|
|
|
accept:
|
|
|
"application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
|
multiple: !!info.multiple,
|
|
|
limit: info.multiple ? 20 : 1,
|
|
|
fileList: this.form[info.name] instanceof Array ? this.form[info.name]?.map(i => {
|
|
|
if (i.hasOwnProperty('original_name')) {
|
|
|
i.name = i.original_name
|
|
|
}
|
|
|
return i
|
|
|
}) : [],
|
|
|
beforeUpload: (file) => {
|
|
|
if (file.size > uploadSize) {
|
|
|
this.$message({
|
|
|
type: "warning",
|
|
|
message: `上传图片大小超过${formatFileSize(uploadSize)}!`,
|
|
|
});
|
|
|
return false;
|
|
|
}
|
|
|
window.$_uploading = true
|
|
|
},
|
|
|
onSuccess: (response, file, fileList) => {
|
|
|
window.$_uploading = false
|
|
|
fileList.forEach((file) => {
|
|
|
if (file.response?.data && !file.response?.code) {
|
|
|
file.response = file.response.data;
|
|
|
}
|
|
|
});
|
|
|
this.form[info.name] = fileList
|
|
|
},
|
|
|
onRemove: (file, fileList) => {
|
|
|
this.form[info.name] = fileList
|
|
|
},
|
|
|
onError: (err, file, fileList) => {
|
|
|
window.$_uploading = false
|
|
|
this.form[info.name] = fileList
|
|
|
this.$message({
|
|
|
type: "warning",
|
|
|
message: err,
|
|
|
});
|
|
|
},
|
|
|
},
|
|
|
scopedSlots: {
|
|
|
file: (scope) => {
|
|
|
let { file } = scope;
|
|
|
return [
|
|
|
h("div", {}, [
|
|
|
h("i", {
|
|
|
class: {
|
|
|
"el-icon-circle-check": file.status === "success",
|
|
|
"el-icon-loading": file.status === "uploading",
|
|
|
},
|
|
|
style: {
|
|
|
color: file.status === "success" ? "green" : "",
|
|
|
},
|
|
|
}),
|
|
|
h(
|
|
|
"a",
|
|
|
{
|
|
|
class: {
|
|
|
"uploaded-a": file.status === "success",
|
|
|
},
|
|
|
style: {
|
|
|
padding: "0 4px",
|
|
|
},
|
|
|
on: {
|
|
|
click: _ => {
|
|
|
this.$bus.$emit('online-file', file.url)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
file.original_name || file.name
|
|
|
),
|
|
|
]),
|
|
|
h("i", {
|
|
|
class: "el-icon-close",
|
|
|
on: {
|
|
|
["click"]: () => {
|
|
|
if (file.status === "uploading") return
|
|
|
this.form[info.name].splice(this.form[info.name].indexOf(file), 1)
|
|
|
},
|
|
|
},
|
|
|
}),
|
|
|
];
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
[
|
|
|
h(
|
|
|
"el-button",
|
|
|
{
|
|
|
slot: "trigger",
|
|
|
props: {
|
|
|
size: "small",
|
|
|
type: "primary",
|
|
|
},
|
|
|
},
|
|
|
"选取文件"
|
|
|
),
|
|
|
h(
|
|
|
"div",
|
|
|
{
|
|
|
class: "el-upload__tip",
|
|
|
slot: "tip",
|
|
|
},
|
|
|
`文件不超过${formatFileSize(uploadSize)}`
|
|
|
),
|
|
|
]
|
|
|
);
|
|
|
break;
|
|
|
case "label":
|
|
|
formItem = h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
type: "primary",
|
|
|
},
|
|
|
},
|
|
|
info.label
|
|
|
);
|
|
|
break;
|
|
|
case "static":
|
|
|
formItem = h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
type: "primary",
|
|
|
},
|
|
|
attrs: {
|
|
|
href: target[info.name],
|
|
|
target: "_blank",
|
|
|
},
|
|
|
},
|
|
|
info.label
|
|
|
);
|
|
|
break;
|
|
|
case "hr":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {}, info.label);
|
|
|
break;
|
|
|
case "relation-flow":
|
|
|
if (!this.flows[info.name]) {
|
|
|
flowList('all', {
|
|
|
page: 1,
|
|
|
page_size: 9999,
|
|
|
is_simple: 1,
|
|
|
custom_model_id: info.stub,
|
|
|
is_auth: 1,
|
|
|
}).then(res => {
|
|
|
this.$set(this.flows, info.name, res.data.data)
|
|
|
})
|
|
|
}
|
|
|
formItem = h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
value: (target[info.name] ? target[info.name].toString()?.split(',').map(i => Number(i)) : []),
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
multiple: true,
|
|
|
filterable: true,
|
|
|
'reserve-keyword': true,
|
|
|
loading: this.flowSelectLoading
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
},
|
|
|
style: {
|
|
|
width: '100%'
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
this.$set(target, info.name, e.toString())
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
this.flows[info.name]?.map((option) =>
|
|
|
h("el-option", {
|
|
|
props: {
|
|
|
label: option.title,
|
|
|
value: option.id,
|
|
|
},
|
|
|
})
|
|
|
)
|
|
|
);
|
|
|
break;
|
|
|
case "relation":
|
|
|
formItem = h(
|
|
|
"vxe-table",
|
|
|
{
|
|
|
ref: `subForm-${info.name}`,
|
|
|
style: {
|
|
|
"margin-top": "10px",
|
|
|
},
|
|
|
props: {
|
|
|
"min-height": "200px",
|
|
|
border: true,
|
|
|
stripe: true,
|
|
|
data: (this.form[info.name] && typeof this.form[info.name] !== 'string') ? this.form[info.name] : [],
|
|
|
"keep-source": true,
|
|
|
"column-config": { resizable: true },
|
|
|
"show-overflow": true,
|
|
|
"edit-rules": info._writeable ? this.subRules[`${info.name}_rules`] : {},
|
|
|
"edit-config": info._writeable
|
|
|
? {
|
|
|
trigger: "click",
|
|
|
mode: "row",
|
|
|
showStatus: false,
|
|
|
isHover: true,
|
|
|
autoClear: false,
|
|
|
}
|
|
|
: {},
|
|
|
},
|
|
|
on: {
|
|
|
"edit-closed": ({ row, column }) => {
|
|
|
const $table = this.$refs[`subForm-${info.name}`];
|
|
|
if ($table) {
|
|
|
this.$set(
|
|
|
this.form,
|
|
|
info.name,
|
|
|
this.$refs[`subForm-${info.name}`].tableData
|
|
|
);
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
[
|
|
|
info._writeable
|
|
|
? h(
|
|
|
"vxe-column",
|
|
|
{
|
|
|
props: {
|
|
|
width: 56,
|
|
|
align: "center",
|
|
|
},
|
|
|
scopedSlots: {
|
|
|
default: ({ row }) => {
|
|
|
return h("el-button", {
|
|
|
slot: "default",
|
|
|
style: {
|
|
|
padding: "9px",
|
|
|
},
|
|
|
props: {
|
|
|
type: "danger",
|
|
|
size: "small",
|
|
|
icon: "el-icon-minus",
|
|
|
},
|
|
|
on: {
|
|
|
click: async (_) => {
|
|
|
const $table =
|
|
|
this.$refs[`subForm-${info.name}`];
|
|
|
if ($table) {
|
|
|
await $table.remove(row);
|
|
|
this.form[info.name] = $table.getTableData()?.tableData
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
[
|
|
|
h("el-button", {
|
|
|
slot: "header",
|
|
|
style: {
|
|
|
padding: "9px",
|
|
|
},
|
|
|
props: {
|
|
|
type: "primary",
|
|
|
size: "small",
|
|
|
icon: "el-icon-plus",
|
|
|
},
|
|
|
on: {
|
|
|
click: async (_) => {
|
|
|
const $table = this.$refs[`subForm-${info.name}`];
|
|
|
if ($table) {
|
|
|
const record = {};
|
|
|
this.form[info.name].unshift(record)
|
|
|
// 临时数据不好验证长度
|
|
|
// const { row: newRow } = await $table.insert(
|
|
|
// record
|
|
|
// );
|
|
|
await this.$nextTick();
|
|
|
await $table.setEditRow(record);
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
}),
|
|
|
]
|
|
|
)
|
|
|
: "",
|
|
|
...this.subForm
|
|
|
.get(info.sub_custom_model_id)
|
|
|
?.customModel?.fields?.map((subField, subIndex) =>
|
|
|
h("vxe-column", {
|
|
|
props: {
|
|
|
field: subField.name,
|
|
|
title: subField.label,
|
|
|
align: "center",
|
|
|
'min-width': '180',
|
|
|
"edit-render": {},
|
|
|
},
|
|
|
scopedSlots: {
|
|
|
edit: ({ row: myrow }) => {
|
|
|
return formBuilder.bind(this)(
|
|
|
device,
|
|
|
subField,
|
|
|
h,
|
|
|
myrow,
|
|
|
info._writeable,
|
|
|
false,
|
|
|
);
|
|
|
},
|
|
|
[['file', 'choices', 'choice', 'select', 'radio'].indexOf(subField.type) !== -1 ? 'default' : false]: ({ row: myrow }) => {
|
|
|
return formBuilder.bind(this)(
|
|
|
device,
|
|
|
subField,
|
|
|
h,
|
|
|
myrow,
|
|
|
false,
|
|
|
true,
|
|
|
);
|
|
|
}
|
|
|
},
|
|
|
})
|
|
|
),
|
|
|
]
|
|
|
);
|
|
|
break;
|
|
|
}
|
|
|
} else if (info._readable || pReadable) {
|
|
|
switch (info.type) {
|
|
|
case "date":
|
|
|
formItem = h(
|
|
|
"span",
|
|
|
{
|
|
|
style: {
|
|
|
color: "#333",
|
|
|
},
|
|
|
},
|
|
|
target[info.name] ? moment(target[info.name]).format("YYYY年MM月DD日") : ''
|
|
|
);
|
|
|
break;
|
|
|
case "datetime":
|
|
|
formItem = h(
|
|
|
"span",
|
|
|
{
|
|
|
style: {
|
|
|
color: "#333",
|
|
|
},
|
|
|
},
|
|
|
target[info.name] ? moment(target[info.name]).format("YYYY年MM月DD日 HH时mm分") : ''
|
|
|
);
|
|
|
break;
|
|
|
case "choice":
|
|
|
case "select":
|
|
|
const getDetailSelectValue = () => {
|
|
|
let res = ''
|
|
|
if (!!info.multiple) {
|
|
|
res = target[info.name] ? target[info.name].toString()?.split(/,|\|/).map(i => isNaN(Number(i)) ? i : Number(i)) : []
|
|
|
} else {
|
|
|
res = isNaN(Number(target[info.name])) ? target[info.name] : Number(target[info.name])
|
|
|
}
|
|
|
if (res instanceof Array) {
|
|
|
if (typeof options[0] === 'object') {
|
|
|
return options?.filter((i) =>
|
|
|
res.indexOf(i.id) !== -1
|
|
|
)?.map(i => i.name)?.toString()
|
|
|
} else {
|
|
|
return res
|
|
|
}
|
|
|
} else {
|
|
|
if (typeof options[0] === 'object') {
|
|
|
return options?.filter((i) =>
|
|
|
res === i.id
|
|
|
)?.map(i => i.name)?.toString()
|
|
|
} else {
|
|
|
return res
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
formItem = h(
|
|
|
"span",
|
|
|
{
|
|
|
style: {
|
|
|
color: "#333",
|
|
|
},
|
|
|
},
|
|
|
getDetailSelectValue()
|
|
|
);
|
|
|
break;
|
|
|
case "relation-flow":
|
|
|
if (!this.flows[info.name]) {
|
|
|
flowList('all', {
|
|
|
page: 1,
|
|
|
page_size: 9999,
|
|
|
is_simple: 1,
|
|
|
custom_model_id: info.stub,
|
|
|
is_auth: 1
|
|
|
}).then(res => {
|
|
|
this.$set(this.flows, info.name, res.data.data)
|
|
|
})
|
|
|
}
|
|
|
formItem = h(
|
|
|
"span",
|
|
|
{
|
|
|
style: {
|
|
|
color: "#333",
|
|
|
},
|
|
|
},
|
|
|
target[info.name]?.toString()?.split(',')?.map(j => {
|
|
|
let flow = this.flows[info.name]?.find((i) =>
|
|
|
i.id == j
|
|
|
)
|
|
|
return flow ? h('el-link', {
|
|
|
props: {
|
|
|
type: 'primary'
|
|
|
},
|
|
|
style: {
|
|
|
'line-height': '1.5'
|
|
|
},
|
|
|
on: {
|
|
|
click: _ => {
|
|
|
let target = this.$router.resolve({
|
|
|
path: '/flow/detail',
|
|
|
query: {
|
|
|
module_id: flow.custom_model_id,
|
|
|
flow_id: flow.id,
|
|
|
isSinglePage: 1
|
|
|
}
|
|
|
});
|
|
|
this.modalRender = h => h('iframe',{
|
|
|
attrs: {
|
|
|
src: target.href,
|
|
|
},
|
|
|
style: {
|
|
|
border: 'none',
|
|
|
width: '100%',
|
|
|
height: '100%'
|
|
|
}
|
|
|
})
|
|
|
this.isShowModal = true
|
|
|
}
|
|
|
}
|
|
|
},flow.title) : ''
|
|
|
})
|
|
|
);
|
|
|
break;
|
|
|
case "file":
|
|
|
formItem = row ?
|
|
|
h(
|
|
|
'vxe-upload',
|
|
|
{
|
|
|
props: {
|
|
|
value: row[info.name],
|
|
|
'name-field': 'original_name',
|
|
|
'progress-text': "{percent}%",
|
|
|
'more-config': { maxCount: 1, layout: 'horizontal' },
|
|
|
'show-button-text': false,
|
|
|
'limit-size': uploadSize / 1024 / 1024, //vxe upload单位为Mb
|
|
|
'limit-count': info.multiple ? 20 : 1,
|
|
|
readonly: true
|
|
|
}
|
|
|
}
|
|
|
) :
|
|
|
h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
action: process.env.VUE_APP_UPLOAD_API,
|
|
|
headers: {
|
|
|
Authorization: `Bearer ${getToken()}`,
|
|
|
},
|
|
|
disabled: true,
|
|
|
accept:
|
|
|
"application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
|
multiple: true,
|
|
|
fileList: (this.form[info.name] instanceof Array) ? this.form[info.name]?.map(i => {
|
|
|
if (i.hasOwnProperty('original_name')) {
|
|
|
i.name = i.original_name
|
|
|
}
|
|
|
return i
|
|
|
}) : [],
|
|
|
},
|
|
|
scopedSlots: {
|
|
|
file: (scope) => {
|
|
|
let { file } = scope;
|
|
|
return [
|
|
|
h("div", {}, [
|
|
|
h("i", {
|
|
|
class: "el-icon-circle-check",
|
|
|
style: {
|
|
|
color: "green",
|
|
|
},
|
|
|
}),
|
|
|
h(
|
|
|
"a",
|
|
|
{
|
|
|
class: {
|
|
|
"uploaded-a": file.status === "success",
|
|
|
},
|
|
|
style: {
|
|
|
padding: "0 4px",
|
|
|
},
|
|
|
on: {
|
|
|
click: _ => {
|
|
|
console.log(file)
|
|
|
this.$bus.$emit('online-file', file.url)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
file.name
|
|
|
),
|
|
|
]),
|
|
|
];
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
[
|
|
|
h(
|
|
|
"span",
|
|
|
{
|
|
|
slot: "trigger",
|
|
|
},
|
|
|
`数量:${(this.form[info.name] instanceof Array) ? this.form[info.name]?.length : 0}`
|
|
|
),
|
|
|
]
|
|
|
);
|
|
|
break;
|
|
|
default:
|
|
|
formItem = h(
|
|
|
"span",
|
|
|
{
|
|
|
style: {
|
|
|
color: "#333",
|
|
|
},
|
|
|
},
|
|
|
target[info.name]
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (formItem) {
|
|
|
let jointlySignContent = []
|
|
|
let isJointly = false
|
|
|
this.jointlySignLog.forEach(log => {
|
|
|
const data = JSON.parse(log.data)
|
|
|
Object.entries(data)?.forEach(([key, value]) => {
|
|
|
if (value.hasOwnProperty('custom_field_id') && (value['custom_field_id'] === info.id)) {
|
|
|
isJointly = log.is_jointly_sign
|
|
|
jointlySignContent.push(h('div',[
|
|
|
h('span', value.value),
|
|
|
h('br'),
|
|
|
info.is_sign ? (
|
|
|
(log.user.sign_file && log.user.sign_file.url) ? h('el-image',{
|
|
|
style: {
|
|
|
'max-height': '80px',
|
|
|
'max-width': '120px'
|
|
|
},
|
|
|
props: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
fit: 'contain',
|
|
|
alt: log.user?.name
|
|
|
},
|
|
|
attrs: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
alt: log.user?.name
|
|
|
}
|
|
|
}) : h('span', log.user?.name)
|
|
|
) : '',
|
|
|
info.is_sign ? h('br') : '',
|
|
|
h('span', log.updated_at ? this.$moment(log.updated_at).format('YYYY年MM月DD') : '')
|
|
|
]))
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
return row
|
|
|
? formItem
|
|
|
: h(
|
|
|
"el-form-item",
|
|
|
{
|
|
|
props: {
|
|
|
prop: info.name,
|
|
|
label: info.label_show ? info.label : '',
|
|
|
'label-width': !info.label_show ? '0': '',
|
|
|
},
|
|
|
style: {
|
|
|
"grid-column-start": info.gs_x + 1,
|
|
|
"grid-column-end": info.gs_x + 1 + info.gs_width,
|
|
|
"grid-row-start": info.gs_y + 1 + (info.name === 'flow_title' ? 0 : 1),
|
|
|
"grid-row-end": info.gs_y + 1 + (info.name === 'flow_title' ? 0 : 1) + info.gs_height,
|
|
|
},
|
|
|
},
|
|
|
isJointly ? [(/\/detail/.test(this.$route.path) && this.$route.query.flow_id && jointlySignContent.length > 0) ? '' : formItem,jointlySignContent] : [formItem,(() => {
|
|
|
if (info.is_sign) {
|
|
|
let log = this.logs.find(log => log.node?.fields?.findIndex(field => field?.field?.name === info.name && field.type === 'write') !== -1 && (target[info.name]))
|
|
|
if (log && log.user) {
|
|
|
return h('div',[
|
|
|
(log.user.sign_file && log.user.sign_file.url) ? h('el-image',{
|
|
|
style: {
|
|
|
'max-height': '80px',
|
|
|
'max-width': '120px'
|
|
|
},
|
|
|
props: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
fit: 'contain',
|
|
|
alt: log.user?.name
|
|
|
},
|
|
|
attrs: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
alt: log.user?.name
|
|
|
}
|
|
|
}) : h('span', log.user?.name),
|
|
|
h('div', this.$moment(log.updated_at).format('YYYY年MM月DD日 HH时mm分'))
|
|
|
])
|
|
|
}
|
|
|
}
|
|
|
})()]
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
if (device === "mobile") {
|
|
|
if (info._writeable || pWrite) {
|
|
|
let myRules = []
|
|
|
if (row && this.subRules && this.subRules[`${pname}_rules`] && this.subRules[`${pname}_rules`][info.name]) {
|
|
|
myRules = this.subRules[`${pname}_rules`][info.name]
|
|
|
} else {
|
|
|
myRules = this.rules[info.name]
|
|
|
}
|
|
|
switch (info.type) {
|
|
|
case "text":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {
|
|
|
props: {
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
value: row ? row[info.name] : this.form[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: myRules?.map(rule => {
|
|
|
if (rule.hasOwnProperty('required')) {
|
|
|
return rule
|
|
|
} else if (rule.hasOwnProperty('pattern')) {
|
|
|
return {
|
|
|
pattern: rule.pattern,
|
|
|
message: rule.message
|
|
|
}
|
|
|
} else {
|
|
|
return rule
|
|
|
}
|
|
|
}),
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
row
|
|
|
? this.$set(row, info.name, e)
|
|
|
: this.$set(this.form, info.name, e);
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "textarea":
|
|
|
formItem = h(formBuilderMap(device).get(info.type), {
|
|
|
props: {
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
type: "textarea",
|
|
|
value: row ? row[info.name] : this.form[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
input: (e) => {
|
|
|
row
|
|
|
? this.$set(row, info.name, e)
|
|
|
: this.$set(this.form, info.name, e);
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "date":
|
|
|
formItem = h("van-field", {
|
|
|
props: {
|
|
|
readonly: true,
|
|
|
clickable: true,
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
value: row ? row[info.name] : this.form[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
placeholder: info.help_text,
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
click: (_) => {
|
|
|
this.vanCalendarOption.forFormName = info.name;
|
|
|
this.vanCalendarOption.originalObj = row;
|
|
|
this.vanCalendarOption.isShow = true;
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "datetime":
|
|
|
formItem = h("van-field", {
|
|
|
props: {
|
|
|
readonly: true,
|
|
|
clickable: true,
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
value: row ? row[info.name] : this.form[info.name],
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
click: (_) => {
|
|
|
this.vanTimePickerOption.forFormName = info.name;
|
|
|
this.vanTimePickerOption.originalObj = row;
|
|
|
this.vanTimePickerOption.isShow = true
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "select":
|
|
|
let findSelect = options?.find((i) =>
|
|
|
typeof i === "object"
|
|
|
? i.id === (row ? row[info.name] : this.form[info.name])
|
|
|
: i === (row ? row[info.name] : this.form[info.name])
|
|
|
);
|
|
|
formItem = h("van-field", {
|
|
|
props: {
|
|
|
readonly: true,
|
|
|
clickable: true,
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
value: typeof findSelect === "object" ? findSelect.name : findSelect,
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
click: (_) => {
|
|
|
this.vanPopupOption.forFormName = info.name;
|
|
|
this.vanPopupOption.originalObj = row;
|
|
|
this.$set(this.vanPopupOption, "columns", options);
|
|
|
this.vanPopupOption.isShow = true;
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "choice":
|
|
|
let findChoice = info.multiple ? options?.filter((i) =>
|
|
|
typeof i === "object"
|
|
|
? (row ? row[info.name].indexOf(i.id) !== -1 : this.form[info.name].indexOf(i.id) !== -1)
|
|
|
: i === (row ? row[info.name] : this.form[info.name])
|
|
|
) : options?.find((i) =>
|
|
|
typeof i === "object"
|
|
|
? i.id === (row ? row[info.name] : this.form[info.name])
|
|
|
: i === (row ? row[info.name] : this.form[info.name])
|
|
|
);
|
|
|
formItem = h("van-field", {
|
|
|
props: {
|
|
|
readonly: true,
|
|
|
clickable: true,
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
value: (findChoice instanceof Array) ? (findChoice.map(i => typeof i === "object" ? i.name : i).toString()) : (typeof findChoice === "object" ? findChoice.name : findChoice),
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
click: (_) => {
|
|
|
this.multipleSelectOption.forFormName = info.name;
|
|
|
this.multipleSelectOption.originalObj = row;
|
|
|
this.multipleSelectOption.outputType = 'array';
|
|
|
this.$set(this.multipleSelectOption, "columns", options);
|
|
|
this.$set(this.multipleSelectOption, "options", {
|
|
|
label: 'name',
|
|
|
value: 'id'
|
|
|
});
|
|
|
this.$set(this.multipleSelectOption, "multipleLimit", info.multiple);
|
|
|
this.multipleSelectOption.isShow = true;
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "file":
|
|
|
formItem = h('van-cell',{
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
},[
|
|
|
h(
|
|
|
formBuilderMap(device).get(info.type),
|
|
|
{
|
|
|
props: {
|
|
|
action: process.env.VUE_APP_UPLOAD_API,
|
|
|
headers: {
|
|
|
Authorization: `Bearer ${getToken()}`,
|
|
|
},
|
|
|
accept:
|
|
|
"application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
|
multiple: !!info.multiple,
|
|
|
fileList: row ? row[info.name]?.map(i => {
|
|
|
if (i.hasOwnProperty('original_name')) {
|
|
|
i.name = i.original_name
|
|
|
}
|
|
|
return i
|
|
|
}) : this.form[info.name]?.map(i => {
|
|
|
if (i.hasOwnProperty('original_name')) {
|
|
|
i.name = i.original_name
|
|
|
}
|
|
|
return i
|
|
|
}),
|
|
|
beforeUpload: (file) => {
|
|
|
if (file.size > uploadSize) {
|
|
|
this.$message({
|
|
|
type: "warning",
|
|
|
message: `上传图片大小超过${formatFileSize(uploadSize)}!`,
|
|
|
});
|
|
|
return false;
|
|
|
}
|
|
|
window.$_uploading = true
|
|
|
},
|
|
|
onSuccess: (response, file, fileList) => {
|
|
|
window.$_uploading = false
|
|
|
fileList.forEach((file) => {
|
|
|
if (file.response?.data && !file.response?.code) {
|
|
|
file.response = file.response.data;
|
|
|
}
|
|
|
});
|
|
|
row ? row[info.name] = fileList : this.form[info.name] = fileList;
|
|
|
},
|
|
|
onRemove: (file, fileList) => {
|
|
|
row ? row[info.name] = fileList : this.form[info.name] = fileList;
|
|
|
},
|
|
|
onError: (err, file, fileList) => {
|
|
|
window.$_uploading = false
|
|
|
row ? row[info.name] = fileList : this.form[info.name] = fileList;
|
|
|
this.$message({
|
|
|
type: "warning",
|
|
|
message: err,
|
|
|
});
|
|
|
},
|
|
|
},
|
|
|
scopedSlots: {
|
|
|
file: (scope) => {
|
|
|
let { file } = scope;
|
|
|
return [
|
|
|
h("div", {}, [
|
|
|
h("i", {
|
|
|
class: {
|
|
|
"el-icon-circle-check": file.status === "success",
|
|
|
"el-icon-loading": file.status === "uploading",
|
|
|
},
|
|
|
style: {
|
|
|
color: file.status === "success" ? "green" : "",
|
|
|
},
|
|
|
}),
|
|
|
h(
|
|
|
"a",
|
|
|
{
|
|
|
class: {
|
|
|
"uploaded-a": file.status === "success",
|
|
|
},
|
|
|
style: {
|
|
|
padding: "0 4px",
|
|
|
},
|
|
|
on: {
|
|
|
click: _ => {
|
|
|
console.log(file)
|
|
|
this.$bus.$emit('online-file', file.url)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
file.name
|
|
|
),
|
|
|
]),
|
|
|
h("i", {
|
|
|
class: "el-icon-close",
|
|
|
on: {
|
|
|
["click"]: () => {
|
|
|
this.$set(
|
|
|
this.file,
|
|
|
info.field,
|
|
|
this.file[info.field].filter(
|
|
|
(item) => item !== file
|
|
|
)
|
|
|
);
|
|
|
},
|
|
|
},
|
|
|
}),
|
|
|
];
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
[
|
|
|
h(
|
|
|
"el-button",
|
|
|
{
|
|
|
slot: "trigger",
|
|
|
props: {
|
|
|
size: "mini",
|
|
|
type: "primary",
|
|
|
},
|
|
|
},
|
|
|
"选取文件"
|
|
|
),
|
|
|
h(
|
|
|
"div",
|
|
|
{
|
|
|
class: "el-upload__tip",
|
|
|
slot: "tip",
|
|
|
},
|
|
|
`文件不超过${formatFileSize(uploadSize)}`
|
|
|
),
|
|
|
]
|
|
|
)
|
|
|
])
|
|
|
break;
|
|
|
case 'relation-flow':
|
|
|
if (!this.flows[info.name]) {
|
|
|
flowList('all', {
|
|
|
page: 1,
|
|
|
page_size: 9999,
|
|
|
is_simple: 1,
|
|
|
custom_model_id: info.stub,
|
|
|
is_auth: 1
|
|
|
}).then(res => {
|
|
|
this.$set(this.flows, info.name, res.data.data)
|
|
|
})
|
|
|
}
|
|
|
formItem = h("van-field", {
|
|
|
props: {
|
|
|
readonly: true,
|
|
|
clickable: true,
|
|
|
name: info.name,
|
|
|
label: info.label,
|
|
|
value: row ? row[info.name]?.toString()?.split(',').map(j => {
|
|
|
return this.flows[info.name]?.find((i) =>
|
|
|
i.id == j
|
|
|
)?.title;
|
|
|
})?.toString() : this.form[info.name]?.toString()?.split(',').map(j => {
|
|
|
return this.flows[info.name]?.find((i) =>
|
|
|
i.id == j
|
|
|
)?.title;
|
|
|
})?.toString(),
|
|
|
clearable: true,
|
|
|
placeholder: info.help_text,
|
|
|
rules: this.rules[info.name],
|
|
|
required: !!myRules?.find(j => j.required)
|
|
|
},
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
on: {
|
|
|
click: (_) => {
|
|
|
this.multipleSelectOption.forFormName = info.name;
|
|
|
this.multipleSelectOption.originalObj = row;
|
|
|
this.multipleSelectOption.outputType = 'string';
|
|
|
this.$set(this.multipleSelectOption, "columns", this.flows[info.name]);
|
|
|
this.$set(this.multipleSelectOption, "options", {
|
|
|
label: 'title',
|
|
|
value: 'id'
|
|
|
});
|
|
|
this.$set(this.multipleSelectOption, "multipleLimit", info.multiple);
|
|
|
this.multipleSelectOption.isShow = true
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
break;
|
|
|
case "relation":
|
|
|
let copySubForm = deepCopy(this.form[info.name][0])
|
|
|
formItem = h("div", [
|
|
|
h("van-cell", {
|
|
|
props: {
|
|
|
"arrow-direction": "down",
|
|
|
title: info.label,
|
|
|
},
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
}
|
|
|
},[
|
|
|
h('van-button',{
|
|
|
props: {
|
|
|
color: 'var(--theme-color)',
|
|
|
icon: 'plus',
|
|
|
size: 'small'
|
|
|
},
|
|
|
on: {
|
|
|
'click':_ => {
|
|
|
this.form[info.name].push(copySubForm)
|
|
|
}
|
|
|
}
|
|
|
},'新增')
|
|
|
]),
|
|
|
h(
|
|
|
"div",
|
|
|
this.form[info.name] instanceof Array ? this.form[info.name]?.map((sForm, sIndex) =>
|
|
|
h(
|
|
|
"van-cell-group",
|
|
|
{
|
|
|
props: {
|
|
|
inset: false
|
|
|
}
|
|
|
},
|
|
|
[
|
|
|
h("van-cell", {
|
|
|
props: {
|
|
|
title: info.label + "-" + (sIndex + 1)
|
|
|
}
|
|
|
},[
|
|
|
h('van-button',{
|
|
|
props: {
|
|
|
size: 'mini',
|
|
|
type: 'danger',
|
|
|
icon: 'minus'
|
|
|
},
|
|
|
on: {
|
|
|
click: _ => {
|
|
|
this.form[info.name].splice(sIndex, 1)
|
|
|
}
|
|
|
}
|
|
|
},'删除')
|
|
|
]),
|
|
|
h(
|
|
|
"van-form",
|
|
|
{
|
|
|
ref: "subVanForm-"+sIndex,
|
|
|
props: {
|
|
|
"scroll-to-error": true,
|
|
|
},
|
|
|
style: {
|
|
|
margin: '0 10px'
|
|
|
}
|
|
|
},
|
|
|
Array.from(this.subForm)
|
|
|
.map((i) => i[1]?.customModel?.fields)
|
|
|
?.flat()
|
|
|
.map((subField) =>
|
|
|
formBuilder.bind(this)(
|
|
|
device,
|
|
|
subField,
|
|
|
h,
|
|
|
sForm,
|
|
|
info._writeable,
|
|
|
null,
|
|
|
info.name
|
|
|
)
|
|
|
)
|
|
|
),
|
|
|
]
|
|
|
)
|
|
|
) : ''
|
|
|
),
|
|
|
]);
|
|
|
break;
|
|
|
}
|
|
|
} else if(info._readable || pReadable) {
|
|
|
switch (info.type) {
|
|
|
case "date":
|
|
|
formItem = h(
|
|
|
"van-cell",
|
|
|
{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
value: this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日") : ''
|
|
|
}
|
|
|
}
|
|
|
);
|
|
|
break;
|
|
|
case "datetime":
|
|
|
formItem = h(
|
|
|
"van-cell",
|
|
|
{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
value: this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日 HH时mm分ss秒") : ''
|
|
|
}
|
|
|
},
|
|
|
);
|
|
|
break;
|
|
|
case "select":
|
|
|
let findSelect = options.find((i) =>
|
|
|
typeof i === "object"
|
|
|
? i.id === this.form[info.name]
|
|
|
: i === this.form[info.name]
|
|
|
);
|
|
|
formItem = h(
|
|
|
"van-cell",
|
|
|
{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
value: typeof findSelect === "object" ? findSelect.name : findSelect
|
|
|
}
|
|
|
},
|
|
|
);
|
|
|
break;
|
|
|
case 'choice':
|
|
|
let findChoice = options.find((i) =>
|
|
|
typeof i === "object"
|
|
|
? i.id === this.form[info.name]
|
|
|
: i === this.form[info.name]
|
|
|
);
|
|
|
formItem = h(
|
|
|
"van-cell",
|
|
|
{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
value: typeof findChoice === "object" ? findChoice.name : findChoice
|
|
|
}
|
|
|
},
|
|
|
);
|
|
|
break;
|
|
|
case 'file':
|
|
|
let files = (row ? row[info.name] : this.form[info.name])
|
|
|
formItem = h(
|
|
|
"van-cell",
|
|
|
{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
}
|
|
|
},
|
|
|
((files && files !== 'null' && files !== 'undefined') ? files : [])?.map(file => h("div", {}, [
|
|
|
h(
|
|
|
"a",
|
|
|
{
|
|
|
class: {
|
|
|
"uploaded-a": file.status === "success",
|
|
|
},
|
|
|
style: {
|
|
|
padding: "0 4px",
|
|
|
},
|
|
|
on: {
|
|
|
click:_ => {
|
|
|
console.log(file)
|
|
|
this.$bus.$emit('online-file', file.url)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
file.original_name || file.name
|
|
|
),
|
|
|
]))
|
|
|
);
|
|
|
break
|
|
|
case 'relation':
|
|
|
formItem = h("div", [
|
|
|
h("van-cell", {
|
|
|
props: {
|
|
|
"arrow-direction": "down",
|
|
|
title: info.label,
|
|
|
},
|
|
|
}),
|
|
|
h(
|
|
|
"div",
|
|
|
this.form[info.name] instanceof Array ? this.form[info.name]?.map((sForm, sIndex) =>
|
|
|
h(
|
|
|
"van-cell-group",
|
|
|
{
|
|
|
props: {
|
|
|
inset: false
|
|
|
}
|
|
|
},
|
|
|
[
|
|
|
h("van-cell", {
|
|
|
props: {
|
|
|
title: info.label + "-" + (sIndex + 1)
|
|
|
}
|
|
|
}),
|
|
|
h(
|
|
|
"van-form",
|
|
|
{
|
|
|
ref: "subVanForm",
|
|
|
props: {
|
|
|
"scroll-to-error": true,
|
|
|
},
|
|
|
style: {
|
|
|
margin: '0 10px'
|
|
|
}
|
|
|
},
|
|
|
Array.from(this.subForm)
|
|
|
.map((i) => i[1]?.customModel?.fields)
|
|
|
?.flat()
|
|
|
.map((subField) =>
|
|
|
formBuilder.bind(this)(
|
|
|
device,
|
|
|
subField,
|
|
|
h,
|
|
|
sForm,
|
|
|
info._writeable,
|
|
|
info._readable
|
|
|
)
|
|
|
)
|
|
|
),
|
|
|
]
|
|
|
)
|
|
|
) : ''
|
|
|
),
|
|
|
]);
|
|
|
break;
|
|
|
case 'relation-flow':
|
|
|
if (!this.flows[info.name]) {
|
|
|
flowList('all', {
|
|
|
page: 1,
|
|
|
page_size: 9999,
|
|
|
is_simple: 1,
|
|
|
custom_model_id: info.stub,
|
|
|
is_auth: 1
|
|
|
}).then(res => {
|
|
|
this.$set(this.flows, info.name, res.data.data)
|
|
|
})
|
|
|
}
|
|
|
formItem = h(
|
|
|
"van-cell",
|
|
|
{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label
|
|
|
}
|
|
|
},
|
|
|
this.form[info.name]?.toString()?.split(',')?.map(j => {
|
|
|
let flow = this.flows[info.name]?.find((i) =>
|
|
|
i.id == j
|
|
|
)
|
|
|
return flow ? h('el-link', {
|
|
|
props: {
|
|
|
type: 'primary'
|
|
|
},
|
|
|
style: {
|
|
|
'line-height': '1.5'
|
|
|
},
|
|
|
on: {
|
|
|
click: _ => {
|
|
|
let target = this.$router.resolve({
|
|
|
path: '/flow/detail',
|
|
|
query: {
|
|
|
module_id: flow.custom_model_id,
|
|
|
flow_id: flow.id,
|
|
|
isSinglePage: 1
|
|
|
}
|
|
|
});
|
|
|
this.modalRender = h => h('iframe',{
|
|
|
attrs: {
|
|
|
src: target.href,
|
|
|
},
|
|
|
style: {
|
|
|
border: 'none',
|
|
|
width: '100%',
|
|
|
height: '100%'
|
|
|
}
|
|
|
})
|
|
|
this.isShowModal = true
|
|
|
}
|
|
|
}
|
|
|
},flow.title) : ''
|
|
|
})
|
|
|
);
|
|
|
break;
|
|
|
default:
|
|
|
formItem = h('van-cell',{
|
|
|
attrs: {
|
|
|
for: info.name
|
|
|
},
|
|
|
props: {
|
|
|
title: info.label,
|
|
|
value: row ? row[info.name] : this.form[info.name]
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
let jointlySignContent = []
|
|
|
let isJointly = false
|
|
|
this.jointlySignLog.forEach(log => {
|
|
|
const data = JSON.parse(log.data)
|
|
|
Object.entries(data)?.forEach(([key, value]) => {
|
|
|
if (value.hasOwnProperty('custom_field_id') && (value['custom_field_id'] === info.id)) {
|
|
|
isJointly = log.is_jointly_sign
|
|
|
jointlySignContent.push(h('div',[
|
|
|
h('span', value.value),
|
|
|
h('br'),
|
|
|
info.is_sign ? (
|
|
|
(log.user.sign_file && log.user.sign_file.url) ? h('el-image',{
|
|
|
style: {
|
|
|
'max-height': '80px',
|
|
|
'max-width': '120px'
|
|
|
},
|
|
|
props: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
fit: 'contain',
|
|
|
alt: log.user?.name
|
|
|
},
|
|
|
attrs: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
alt: log.user?.name
|
|
|
}
|
|
|
}) : h('span', log.user?.name)
|
|
|
) : '',
|
|
|
info.is_sign ? h('br') : '',
|
|
|
h('span', log.updated_at ? this.$moment(log.updated_at).format('YYYY年MM月DD') : '')
|
|
|
]))
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
return isJointly ? [(/\/detail/.test(this.$route.path) && this.$route.query.flow_id && jointlySignContent.length > 0) ? '' : formItem,jointlySignContent] : [formItem,(() => {
|
|
|
if (info.is_sign) {
|
|
|
let log = this.logs.find(log => log.node?.fields?.findIndex(field => field?.field?.name === info.name && field.type === 'write') !== -1 && (target[info.name]))
|
|
|
if (log && log.user) {
|
|
|
return h('van-cell',[
|
|
|
(log.user.sign_file && log.user.sign_file.url) ? h('el-image',{
|
|
|
style: {
|
|
|
'max-height': '80px',
|
|
|
'max-width': '120px'
|
|
|
},
|
|
|
props: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
fit: 'contain',
|
|
|
alt: log.user?.name
|
|
|
},
|
|
|
attrs: {
|
|
|
src: log.user?.sign_file?.url,
|
|
|
alt: log.user?.name
|
|
|
}
|
|
|
}) : h('span', log.user?.name),
|
|
|
h('div', this.$moment(log.updated_at).format('YYYY年MM月DD日 HH时mm分'))
|
|
|
])
|
|
|
}
|
|
|
}
|
|
|
})()]
|
|
|
}
|
|
|
}
|