Browse Source

完成自定义表单设计端开发任务

v1
超级管理员 2 years ago
parent
commit
18e8572bb0
  1. 8
      src/api/DesignForm/index.ts
  2. 68
      src/api/DesignForm/requestapi.ts
  3. 49
      src/api/DesignForm/type.ts
  4. 21
      src/api/file/index.ts
  5. 17
      src/api/file/types.ts
  6. 165
      src/components/DesignForm/public/form/form.vue
  7. 499
      src/components/DesignForm/public/form/form2.vue
  8. 122
      src/components/DesignForm/public/form/formGroup.vue
  9. 437
      src/components/DesignForm/public/form/formGroup1.vue
  10. 23
      src/components/DesignForm/public/form/formItem.vue
  11. 56
      src/components/DesignForm/public/form/tinymce.vue
  12. 203
      src/components/DesignForm/public/form/tinymce_1.vue
  13. 4
      src/layout/components/AppMain.vue
  14. 2
      src/utils/DesignForm/index.ts
  15. 84
      src/utils/requestfile.ts
  16. 162
      src/views/sysworkflow/codepage/createform.vue
  17. 230
      src/views/sysworkflow/codepage/datatablestructure.vue
  18. 40
      src/views/sysworkflow/codepage/index.vue
  19. 2
      src/views/sysworkflow/codepage/page.vue
  20. 19
      src/views/sysworkflow/codepage/setupconfig.vue
  21. 237
      src/views/sysworkflow/codepage/setupfield.vue
  22. 14
      src/views/taskplatform/taskmanagement/tasklist.vue

8
src/api/DesignForm/index.ts

@ -5,6 +5,7 @@ import flow from './flow'
const allApi: any = Object.assign(form, system, flow)
export const getRequest = (apiKey: string, data?: any, options: any = {}) => {
let url = allApi[apiKey] || apiKey
console.log("apiKey",apiKey)
// 解决动态url 如/api/delete/id(id为动态时)
// url设置为:/api/delete/$id
// options参数设置:options:{apikey:$id:xx}
@ -13,6 +14,7 @@ export const getRequest = (apiKey: string, data?: any, options: any = {}) => {
url = url.replace(key, options.apiKey[key])
}
}
console.log("apiKey",url)
let obj: any = Object.assign(
{
url: '/api/' + url, // 添加个前缀
@ -62,13 +64,13 @@ export const getRequest = (apiKey: string, data?: any, options: any = {}) => {
}
// export const uploadUrl = '/api/' + allApi.upload
export const uploadUrl = import.meta.env.VITE_APP_BASE_API+"/api/upordown"
/*export function uploadFiledTinymce(data, url) {
export function uploadFiledTinymce(data:any, url:any) {
return request({
url: url || '/upload/single',
url: url || '/api/upordown',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}*/
}

68
src/api/DesignForm/requestapi.ts

@ -12,14 +12,21 @@ import {
customerFormVersionCont,
editFormInfo,
customerFromCont,
enableVersionId
enableVersionId,
databaseCallBackStruct,
haveFormTabelcontInfo,
getFormTableStruct,
optimizeRepairForm,
publicFormTableStruct,
formTabelStruct,
gogoBackFormTabelStruct
} from './type';
//自定义表单列表
export function getCustomerFormList(queryParams: SearchForm): AxiosPromise<CustomerFormPageResult> {
return request({
url: '/systemapi/customer_form/customer_form_list',
method: 'post',
params: queryParams
data: queryParams
});
}
//生成表单基本信息
@ -95,3 +102,60 @@ export function enableVersion(data: enableVersionId) {
data: data
});
}
//数据库表结构(版本及数据表)
export function callBackFormTableVersion(data: enableVersionId):AxiosPromise<databaseCallBackStruct> {
return request({
url: '/systemapi/customer_form/have_database_table_struct',
method: 'post',
data: data
});
}
//获取表单结构
export function haveFormTabelcont(data: haveFormTabelcontInfo):AxiosPromise<getFormTableStruct> {
return request({
url: '/systemapi/customer_form/have_form_tabelcont',
method: 'post',
data: data
});
}
//优化/修复数据表
export function optimizeOrRepairFormTable(data: optimizeRepairForm) {
return request({
url: '/systemapi/customer_form/optimize_repair_form',
method: 'post',
data: data
});
}
//优化/修复数据表
export function haveFormTablelist(data: enableVersionId):AxiosPromise<publicFormTableStruct[]>{
return request({
url: '/systemapi/customer_form/have_form_tablelist',
method: 'post',
data: data
});
}
//表单结构数据处理
export function formFieldHandle(data: any):AxiosPromise<gogoBackFormTabelStruct>{
return request({
url: '/systemapi/customer_form/form_field_handle',
method: 'post',
data: data
});
}
//表单结构数据处理
export function editFormField(data: any){
return request({
url: '/systemapi/customer_form/edit_form_field',
method: 'post',
data: data
});
}
//检测是否存在提交和返回按钮
export function judgeSubmitCancel(data: any){
return request({
url: '/systemapi/customer_form/judge_submit_cancel',
method: 'post',
data: data
});
}

49
src/api/DesignForm/type.ts

@ -38,7 +38,7 @@ export interface setupCustomerFormCont{
name:string;
permit:any;
states:number;
status:boolean;
openclose:boolean;
}
//自定义表单标识符
export interface customerFormLogo{
@ -78,3 +78,50 @@ export interface customerFromCont{
export interface enableVersionId{
id:string;
}
//通用数据表结构管理体
export interface publicFormTableStruct{
id:string;
name:string;
ismain:string;
isedit:string;
versionid:string;
}
//数据结构返回值
export interface databaseCallBackStruct{
version:publicFormTableStruct[];
tablelist:publicFormTableStruct[];
}
//获取表单结构
export interface haveFormTabelcontInfo extends enableVersionId{
name:string;
}
//表单结构体
export interface formTabelStruct{
field:string;
type:string;
attribute:string;
collation:string;
null:string;
key:string;
default:string;
extra:string;
privileges:string;
comment:string;
}
//获取表单结构
export interface getFormTableStruct{
filedlist:formTabelStruct[];
isedit:boolean;
}
//优化/修复数据表
export interface optimizeRepairForm{
name:string;
optimizerender:number;
}
//返回表结构
export interface gogoBackFormTabelStruct extends formTabelStruct{
formname:string;
integer:string;
decimal:string;
}

21
src/api/file/index.ts

@ -1,6 +1,6 @@
import request from '@/utils/request';
import request from '@/utils/requestfile';
import { AxiosPromise } from 'axios';
import { FileInfo } from './types';
import { FileInfo,FileContent } from './types';
/**
*
@ -11,7 +11,8 @@ export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
const formData = new FormData();
formData.append('file', file);
return request({
url: '/api/v1/files',
// url: '/api/v1/files',
url: '/api/upordown',
method: 'post',
data: formData,
headers: {
@ -20,6 +21,20 @@ export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
});
}
export function newUploadFileApi(params:FormData): AxiosPromise<FileContent> {
return request({
// url: '/api/v1/files',
url: '/api/upordown',
method: 'post',
data: params,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
/**
*
*

17
src/api/file/types.ts

@ -5,3 +5,20 @@ export interface FileInfo {
name: string;
url: string;
}
/**
*
*/
export interface FileContent {
id:string;
key:string;
name:string;
tag:string;
url:string;
physicspath:string;
CreatedAt:string;
UpdatedAt:string;
fileSize:number;
type:number;
size:string;
}

165
src/components/DesignForm/public/form/form.vue

@ -1,7 +1,7 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-12 15:08:07
@ 备注: 表单画布
@ 时间: 2023-09-20 08:35:17
@ 备注: 自定义表单通用模块
-->
<script lang='ts' setup>
import FormGroup from './formGroup.vue'
@ -20,8 +20,6 @@ import formatResult from '@/utils/DesignForm/formatResult'
import formChangeValue from '@/utils/DesignForm/formChangeValue'
import { jsonParseStringify } from '@/utils/DesignForm'
const props = withDefaults(
defineProps<{
formData: FormData
@ -67,9 +65,7 @@ const emits = defineEmits<{
}>()
const route = useRoute()
const router = useRouter()
const loading = ref(false)
let timer = 0
let eventName = ''
let getValueEvent = ''
@ -96,16 +92,15 @@ const setWindowEvent = (bool?: boolean) => {
}
}
}
}
}
watch(
() => props.formData,
() => {
console.log("监听数据----->1",props.formData)
emits('update:issave', false)
},
{ deep: true }
)
watch(
watch(
() => props.formData.config,
() => {
if (timer < 2) {
@ -115,27 +110,27 @@ watch(
appendRemoveStyle(true) //
},
{ deep: true }
)
setWindowEvent()
//
const resultDict = ref({})
//
const model = ref<any>({})
// model
const getInitModel = () => {
)
setWindowEvent()
//
const resultDict = ref({})
//
const model = ref<any>({})
// model
const getInitModel = () => {
const obj = {}
forEachGetFormModel(props.formData.list, obj)
model.value = obj
}
watch(
}
watch(
() => props.formData.list,
() => {
// formData
getInitModel()
}
)
// model
const forEachGetFormModel = (list: FormList[], obj: any) => {
)
// model
const forEachGetFormModel = (list: FormList[], obj: any) => {
list.forEach((item: any) => {
if (['table', 'flex'].includes(item.type)) {
obj[item.name] = jsonParseStringify(item.tableData)
@ -152,10 +147,10 @@ watch(
}
}
})
}
}
// tProp
provide(constControlChange, ({ key, value, data, tProp }: any) => {
// tProp
provide(constControlChange, ({ key, value, data, tProp }: any) => {
if (key) {
if (!tProp) {
// change
@ -176,8 +171,8 @@ watch(
// tProps
emits('change', { key, value, model: model.value, data, tProp })
}
})
const dictForm = computed(() => {
})
const dictForm = computed(() => {
const storage = window.localStorage.getItem('akFormDict')
let storageDict = {}
if (storage) {
@ -185,9 +180,9 @@ watch(
}
//
return Object.assign({}, storageDict, props.dict, resultDict.value)
})
//
const formProps = computed(() => {
})
//
const formProps = computed(() => {
return {
model: model.value,
type: props.type,
@ -195,11 +190,11 @@ watch(
showColon: props.formData.form.showColon,
dict: dictForm.value
}
})
provide(constFormProps, formProps)
})
provide(constFormProps, formProps)
// nameformData.list
const getNameForEach = (data: any, name: string) => {
// nameformData.list
const getNameForEach = (data: any, name: string) => {
let temp = {}
for (const key in data) {
const dataKey = data[key]
@ -216,14 +211,14 @@ watch(
}
}
return temp
}
const getControlByName = (name: string) => {
}
const getControlByName = (name: string) => {
return getNameForEach(props.formData.list, name)
}
provide(constGetControlByName, getControlByName)
//
const ruleForm = ref()
const validate = (callback: any) => {
}
provide(constGetControlByName, getControlByName)
//
const ruleForm = ref()
const validate = (callback: any) => {
ruleForm.value.validate((valid: boolean, fields: any) => {
let fieldValue = fields
if (valid) {
@ -232,9 +227,9 @@ watch(
}
callback(valid, fieldValue)
})
}
//
const getValue = (filter?: boolean) => {
}
//
const getValue = (filter?: boolean) => {
if (filter) {
const obj: any = {}
for (const key in model.value) {
@ -250,9 +245,9 @@ watch(
} else {
return model.value
}
}
//
const setValue = (obj: { [key: string]: any }, filter?: boolean) => {
}
//
const setValue = (obj: { [key: string]: any }, filter?: boolean) => {
// falseobjmodelobjmodel
// true
if (filter) {
@ -264,15 +259,15 @@ watch(
} else {
model.value = Object.assign({}, model.value, jsonParseStringify(obj)) // 使set
}
}
//
const setFormOptions = ref({})
provide(constSetFormOptions, setFormOptions)
const setOptions = (obj: { [key: string]: string[] }) => {
}
//
const setFormOptions = ref({})
provide(constSetFormOptions, setFormOptions)
const setOptions = (obj: { [key: string]: string[] }) => {
setFormOptions.value = obj
}
// style
const appendRemoveStyle = (type?: boolean) => {
}
// style
const appendRemoveStyle = (type?: boolean) => {
try {
const {
config:{ style }
@ -281,10 +276,10 @@ watch(
} catch (e) {
/* empty */
}
}
}
//
provide(constFormBtnEvent, (obj: any) => {
//
provide(constFormBtnEvent, (obj: any) => {
emits('btnClick', obj.key)
if ([3, 4, 5].includes(props.type)) {
return ElMessage.error('当前模式不能提交表单')
@ -300,14 +295,15 @@ watch(
router.go(-1) //
break
}
})
//
const getData = (params = {}) => {
})
//
const getData = (params = {}) => {
const requestUrl = props.formData.config?.requestUrl || props.requestUrl
if (props.type === 5 || !requestUrl || props.isSearch) {
console.error('执行了获取数据方法,但配置有误!')
return
}
loading.value = true
const newParams: any = params
// 使propsevents使使
@ -323,6 +319,9 @@ watch(
//
return
}
console.log("res------执行了获取数据方法,但配置有误----->", requestUrl,newParams2,newParams)
getRequest(requestUrl, newParams2 ?? newParams)
.then(res => {
// console.log(res)
@ -359,8 +358,8 @@ watch(
loading.value = false
return ElMessage.error(res.message)
})
}
const submit = (params = {}) => {
}
const submit = (params = {}) => {
const addUrl = props.formData.config?.addUrl || props.addUrl
const editUrl = props.formData.config?.editUrl || props.editUrl
const apiUrl = props.type === 1 ? addUrl : editUrl
@ -407,9 +406,9 @@ watch(
afterSubmit('validate', fields)
}
})
}
//
const afterSubmit = (type: string, res: any) => {
}
//
const afterSubmit = (type: string, res: any) => {
const afterSubmit = props.formData.events?.afterSubmit
let notReturn
if (typeof afterSubmit === 'function') {
@ -429,9 +428,9 @@ watch(
} else if (type === 'fail') {
ElMessage.error(res.message || '保存失败!')
}
}
//
watch(
}
//
watch(
() => props.value,
(v: any) => {
v && setValue(v)
@ -439,34 +438,34 @@ watch(
{
immediate: true
}
)
// options
watch(
)
// options
watch(
() => props.options,
(v: any) => {
v && setOptions(v)
}
)
// ------------------------------------------------
//
const resetFields = () => {
)
// ------------------------------------------------
//
const resetFields = () => {
ruleForm.value.resetFields()
// setValue(Object.assign(model.value, obj || {})) //
}
onMounted(() => {
}
onMounted(() => {
getInitModel()
nextTick(() => {
appendRemoveStyle(true)
})
})
onUnmounted(() => {
})
onUnmounted(() => {
if (eventName) {
// @ts-ignore
window[eventName] = ''
}
appendRemoveStyle()
})
defineExpose({
})
defineExpose({
setOptions,
setValue,
getValue,
@ -474,7 +473,7 @@ watch(
resetFields,
getData,
submit
})
})
</script>
<template>
<div v-loading="loading">

499
src/components/DesignForm/public/form/form2.vue

@ -0,0 +1,499 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-12 15:08:07
@ 备注: 表单画布
-->
<script lang='ts' setup>
import FormGroup from './formGroup.vue'
import { FormData,FormList,FormDataStyle } from '@/api/DesignForm/types'
import { getRequest } from '@/api/DesignForm'
import { useRoute, useRouter } from 'vue-router'
import {
constGetControlByName,
constSetFormOptions,
constFormBtnEvent,
constControlChange,
constFormProps,
appendOrRemoveStyle
} from '@/api/DesignForm/utils'
import formatResult from '@/utils/DesignForm/formatResult'
import formChangeValue from '@/utils/DesignForm/formChangeValue'
import { jsonParseStringify } from '@/utils/DesignForm'
const props = withDefaults(
defineProps<{
formData: FormData
type?: number // 123 4 5
disabled?: boolean //
requestUrl?: string // url
beforeRequest?: Function //
afterResponse?: Function | string //
addUrl?: string // url
editUrl?: string // url
beforeSubmit?: Function | string //
afterSubmit?: Function // return false
value?: { [key: string]: any } // setValue
options?: { [key: string]: any } // setOptions
dict?: object //
isSearch?: boolean // 使
}>(),
{
type: 1, // 123 4 5
formData: () => {
return {
list: [],
form: {},
config: {
style:''
}
}
},
dict: () => {
return {}
},
isSearch: false,
issave:{
type:Boolean,
default:true
},
}
)
const emits = defineEmits<{
(e: 'btnClick', type: string): void
(e: 'change', val: any): void //
(e: 'update:issave', type: boolean): void
}>()
const route = useRoute()
const router = useRouter()
const loading = ref(false)
let timer = 0
let eventName = ''
let getValueEvent = ''
// window
const setWindowEvent = (bool?: boolean) => {
if (props.formData.list.length > 0) {
const formName = props.formData.form?.name
if (!formName) {
// .vuename
return
}
eventName = `get${formName}ControlByName`
getValueEvent = `get${formName}ValueByName`
if (formName && (!window[eventName as any] || !bool)) {
// name
// @ts-ignore
window[eventName] = (name: string) => {
return getNameForEach(props.formData.list, name)
}
// name
// @ts-ignore
window[getValueEvent] = (name: string) => {
return model.value[name]
}
}
}
}
watch(
() => props.formData,
() => {
console.log("监听数据----->1",props.formData)
emits('update:issave', false)
},
{ deep: true }
)
watch(
() => props.formData.config,
() => {
if (timer < 2) {
setWindowEvent() //
}
timer++
appendRemoveStyle(true) //
},
{ deep: true }
)
setWindowEvent()
//
const resultDict = ref({})
//
const model = ref<any>({})
// model
const getInitModel = () => {
const obj = {}
forEachGetFormModel(props.formData.list, obj)
model.value = obj
}
watch(
() => props.formData.list,
() => {
// formData
getInitModel()
}
)
// model
const forEachGetFormModel = (list: FormList[], obj: any) => {
list.forEach((item: any) => {
if (['table', 'flex'].includes(item.type)) {
obj[item.name] = jsonParseStringify(item.tableData)
} else if (['grid', 'tabs'].includes(item.type)) {
item.columns.forEach((col: any) => {
forEachGetFormModel(col.list, obj)
})
} else if (['card', 'div'].includes(item.type)) {
forEachGetFormModel(item.list, obj)
} else {
const excludeType = ['title', 'divider', 'txt', 'button']
if (excludeType.indexOf(item.type) === -1) {
obj[item.name] = jsonParseStringify(item.control.modelValue)
}
}
})
}
// tProp
provide(constControlChange, ({ key, value, data, tProp }: any) => {
if (key) {
if (!tProp) {
// change
model.value[key] = value
}
// 线AB
if (props.formData.events?.change) {
model.value = props.formData.events.change(key, model.value)
}
const onFormChange = props.formData.events?.change
if (onFormChange) {
if (typeof onFormChange === 'function') {
model.value = onFormChange(key, model.value)
} else {
model.value = formChangeValue(key, model.value, onFormChange)
}
}
// tProps
emits('change', { key, value, model: model.value, data, tProp })
}
})
const dictForm = computed(() => {
const storage = window.localStorage.getItem('akFormDict')
let storageDict = {}
if (storage) {
storageDict = JSON.parse(storage)
}
//
return Object.assign({}, storageDict, props.dict, resultDict.value)
})
//
const formProps = computed(() => {
return {
model: model.value,
type: props.type,
hideField: props.formData.config?.hideField as [],
showColon: props.formData.form.showColon,
dict: dictForm.value
}
})
provide(constFormProps, formProps)
// nameformData.list
const getNameForEach = (data: any, name: string) => {
let temp = {}
for (const key in data) {
const dataKey = data[key]
if (dataKey.name === name) {
return dataKey
}
if (['grid', 'tabs'].includes(dataKey.type)) {
dataKey.columns.forEach((co: any) => {
temp = getNameForEach(co.list, name)
})
}
if (['card', 'div'].includes(dataKey.type)) {
temp = getNameForEach(dataKey.list, name)
}
}
return temp
}
const getControlByName = (name: string) => {
return getNameForEach(props.formData.list, name)
}
provide(constGetControlByName, getControlByName)
//
const ruleForm = ref()
const validate = (callback: any) => {
ruleForm.value.validate((valid: boolean, fields: any) => {
let fieldValue = fields
if (valid) {
//
fieldValue = getValue()
}
callback(valid, fieldValue)
})
}
//
const getValue = (filter?: boolean) => {
if (filter) {
const obj: any = {}
for (const key in model.value) {
// eslint-disable-next-line no-prototype-builtins
if (model.value.hasOwnProperty(key)) {
const val = (model.value as any)[key]
if (!/^\s*$/.test(val)) {
obj[key] = val
}
}
}
return obj
} else {
return model.value
}
}
//
const setValue = (obj: { [key: string]: any }, filter?: boolean) => {
// falseobjmodelobjmodel
// true
if (filter) {
for (const key in obj) {
if (model.value[key] !== undefined) {
model.value[key] = obj[key]
}
}
} else {
model.value = Object.assign({}, model.value, jsonParseStringify(obj)) // 使set
}
}
//
const setFormOptions = ref({})
provide(constSetFormOptions, setFormOptions)
const setOptions = (obj: { [key: string]: string[] }) => {
setFormOptions.value = obj
}
// style
const appendRemoveStyle = (type?: boolean) => {
try {
const {
config:{ style }
} = props.formData
appendOrRemoveStyle('formStyle', style || '', type)
} catch (e) {
/* empty */
}
}
//
provide(constFormBtnEvent, (obj: any) => {
emits('btnClick', obj.key)
if ([3, 4, 5].includes(props.type)) {
return ElMessage.error('当前模式不能提交表单')
}
switch (obj.key) {
case 'submit':
submit() //
break
case 'reset':
resetFields() //
break
case 'cancel': //
router.go(-1) //
break
}
})
//
const getData = (params = {}) => {
const requestUrl = props.formData.config?.requestUrl || props.requestUrl
if (props.type === 5 || !requestUrl || props.isSearch) {
console.error('执行了获取数据方法,但配置有误!')
return
}
loading.value = true
const newParams: any = params
// 使propsevents使使
let newParams2
const beforeRequest = props.formData.events?.beforeRequest
if (typeof beforeRequest === 'function') {
newParams2 = beforeRequest(newParams, route)
}
if (typeof props.beforeRequest === 'function') {
newParams2 = props.beforeRequest(newParams, route)
}
if (newParams2 === false) {
//
return
}
getRequest(requestUrl, newParams2 ?? newParams)
.then(res => {
// console.log(res)
loading.value = false
const result = res.data
if (result) {
let formatRes: any = result
//
const afterResponse = props.formData.events?.afterResponse
if (typeof afterResponse === 'string' && afterResponse) {
formatRes = formatResult(result, afterResponse)
} else if (typeof afterResponse === 'function') {
formatRes = afterResponse(result) ?? result
}
// vue
if (typeof props.afterResponse === 'string' && props.afterResponse) {
formatRes = formatResult(result, props.afterResponse)
} else if (typeof props.afterResponse === 'function') {
formatRes = props.afterResponse(result) ?? result
}
if (formatRes === false) {
return
}
setValue(formatRes.result || formatRes)
nextTick(() => {
// dictoptions
if (formatRes.dict && Object.keys(formatRes.dict).length) {
resultDict.value = formatRes.dict
}
})
}
})
.catch((res: any) => {
loading.value = false
return ElMessage.error(res.message)
})
}
const submit = (params = {}) => {
const addUrl = props.formData.config?.addUrl || props.addUrl
const editUrl = props.formData.config?.editUrl || props.editUrl
const apiUrl = props.type === 1 ? addUrl : editUrl
if (props.isSearch || !apiUrl || loading.value) {
if (!props.isSearch && !apiUrl) {
console.error(
new Error('请在表单设计处配置接口事件url或选择数据源或设置props')
)
}
//
return
}
validate((valid: boolean, fields: any) => {
if (valid) {
const formatParams = Object.assign({}, fields, params)
let submitParams
const beforeSubmit = props.formData.events?.beforeSubmit
if (beforeSubmit) {
if (typeof beforeSubmit === 'function') {
submitParams = beforeSubmit(formatParams, route)
} else {
submitParams = formatResult(formatParams, beforeSubmit)
}
}
if (props.beforeSubmit && typeof props.beforeSubmit === 'string') {
submitParams = formatResult(formatParams, props.beforeSubmit)
} else if (typeof props.beforeSubmit === 'function') {
submitParams = props.beforeSubmit(formatParams, route)
}
if (submitParams === false) {
return
}
loading.value = true
//
getRequest(apiUrl, submitParams ?? formatParams)
.then((res: any) => {
afterSubmit('success', res)
})
.catch(res => {
afterSubmit('fail', res)
})
} else {
//
afterSubmit('validate', fields)
}
})
}
//
const afterSubmit = (type: string, res: any) => {
const afterSubmit = props.formData.events?.afterSubmit
let notReturn
if (typeof afterSubmit === 'function') {
notReturn = afterSubmit(type, res)
} else if (typeof props.afterSubmit === 'function') {
notReturn = props.afterSubmit(type, res)
}
loading.value = false
//
// resetFields()
if (notReturn === false) {
// false
return
}
if (type === 'success') {
ElMessage.success(res.message || '保存成功!')
} else if (type === 'fail') {
ElMessage.error(res.message || '保存失败!')
}
}
//
watch(
() => props.value,
(v: any) => {
v && setValue(v)
},
{
immediate: true
}
)
// options
watch(
() => props.options,
(v: any) => {
v && setOptions(v)
}
)
// ------------------------------------------------
//
const resetFields = () => {
ruleForm.value.resetFields()
// setValue(Object.assign(model.value, obj || {})) //
}
onMounted(() => {
getInitModel()
nextTick(() => {
appendRemoveStyle(true)
})
})
onUnmounted(() => {
if (eventName) {
// @ts-ignore
window[eventName] = ''
}
appendRemoveStyle()
})
defineExpose({
setOptions,
setValue,
getValue,
validate,
resetFields,
getData,
submit
})
</script>
<template>
<div v-loading="loading">
<el-form
v-bind="formData.form"
ref="ruleForm"
:model="model as any"
:disabled="disabled || type === 3"
class="add-form"
:class="{
'design-form': type === 5,
'detail-form': type === 3 || type === 4
}"
>
<FormGroup :data="formData.list" />
<slot></slot>
</el-form>
</div>
</template>
<style lang='scss' scoped>
</style>

122
src/components/DesignForm/public/form/formGroup.vue

@ -1,7 +1,7 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 08:46:51
@ 备注: 表单组
@ 时间: 2023-09-20 13:00:49
@ 备注: 自定义表单组件渲染
-->
<script lang='ts' setup>
import { computed, watch, inject, onUnmounted } from 'vue'
@ -29,10 +29,10 @@ const props = withDefaults(
}
}
)
const store = useDesignFormStore() as any
const store = useDesignFormStore() as any //
const formProps = inject(constFormProps, {}) as any
const type = computed(() => {
console.log("11111",formProps.value.type)
const type = computed(() => { //
return formProps.value.type
})
const state = reactive({
@ -40,23 +40,23 @@ const state = reactive({
gridAdd: false
})
const dataList = ref<any>(props.data)
watch(
watch(
() => props.data,
(v: FormList[]) => {
dataList.value = v
}
)
const activeKey = computed(() => {
)
const activeKey = computed(() => {
return store.activeKey
})
//
const notNested = (type: string) => {
})
//
const notNested = (type: string) => {
const controlType = ['grid', 'table', 'tabs', 'div', 'flex', 'card']
return controlType.includes(type)
}
//
const click = (action: string, index: number, item?: any) => {
}
//
const click = (action: string, index: number, item?: any) => {
if (type.value !== 5) {
return //
}
@ -77,8 +77,8 @@ const dataList = ref<any>(props.data)
} else if (action === 'delGridChild') {
item.splice(index, 1)
}
}
const draggableAdd = (evt: any) => {
}
const draggableAdd = (evt: any) => {
if (type.value !== 5) {
return //
}
@ -134,8 +134,8 @@ const dataList = ref<any>(props.data)
}
Object.assign(obj, nameObj, objectItem)
groupClick(obj)
}
const getGroupName = (item: any) => {
}
const getGroupName = (item: any) => {
if (item.name) {
return item.name
} else {
@ -144,9 +144,9 @@ const dataList = ref<any>(props.data)
let md5Str = md5Object.end()
return md5Str
}
}
//
const groupClick = (item: any, ele?: string) => {
}
//
const groupClick = (item: any, ele?: string) => {
//
if (type.value !== 5) {
return
@ -159,18 +159,18 @@ const dataList = ref<any>(props.data)
// grid
state.gridAdd = item.type === 'grid'
state.clone = !notNested(item.type)
}
//
const getFormItemStyle = (ele: FormList) => {
}
//
const getFormItemStyle = (ele: FormList) => {
if (ele.config?.span === 0) {
return { width: 'auto', margin: '0 5px' }
}
if (ele.config && ele.config.span) {
return { width: (ele.config.span / 24) * 100 + '%' }
}
}
//
const linksShow = (el: FormList, index: number) => {
}
//
const linksShow = (el: FormList, index: number) => {
//
if (!el.config) {
return true
@ -190,9 +190,9 @@ const dataList = ref<any>(props.data)
}
}
return true
}
//
const linksIf = (obj: FormList) => {
}
//
const linksIf = (obj: FormList) => {
const { type } = formProps.value
const { config: { disabledAdd, disabledEdit, disabledDetail } = {} } = obj
if (type === 1) {
@ -217,10 +217,10 @@ const dataList = ref<any>(props.data)
return vIf.indexOf(obj.name) === -1 // false
}
return true
}
//
const injectBtnEvent:any = inject(constFormBtnEvent)
const clickBtn = (control: any) => {
}
//
const injectBtnEvent:any = inject(constFormBtnEvent)
const clickBtn = (control: any) => {
// 0: '',
// 1: '',
// 2: '',
@ -229,13 +229,13 @@ const dataList = ref<any>(props.data)
//
injectBtnEvent && injectBtnEvent(control)
}
}
onUnmounted(() => {
}
onUnmounted(() => {
// console.log('formGroup onUnmounted')
dataList.value = {}
store.setActiveKey('')
store.setControlAttr({})
})
})
</script>
<template>
<draggable
@ -264,6 +264,7 @@ const dataList = ref<any>(props.data)
v-show="linksShow(element, index)"
v-if="linksIf(element)"
>
<!--选项卡组件-->
<template v-if="element.type === 'tabs'">
<div class="form-tabs">
<el-tabs
@ -280,7 +281,7 @@ const dataList = ref<any>(props.data)
</el-tabs>
</div>
</template>
<!--标题组件-->
<template v-else-if="element.type === 'title'">
<div
class="title"
@ -294,23 +295,23 @@ const dataList = ref<any>(props.data)
/>
</div>
</template>
<!--文字组件-->
<template v-else-if="element.type === 'txt'">
<div
v-bind="element.control"
:class="[element.config.className]"
v-html="element.control.modelValue"
></div>
>
</div>
</template>
<!--表格组件-->
<template v-else-if="element.type === 'table'">
<div class="form-table" v-if="type === 5">
<form-group :data="element.list" data-type="not-nested" />
</div>
<child-table v-else :data="element" />
</template>
<!--格栅布局-->
<template v-else-if="element.type === 'grid'">
<el-row class="form-row" :class="[element.className]">
<el-col
@ -329,16 +330,15 @@ const dataList = ref<any>(props.data)
<div class="item-control">
<i
class="icon-del"
@click.stop="
click('delGridChild', i as number, element.columns)
"
></i>
@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">
@ -350,13 +350,11 @@ const dataList = ref<any>(props.data)
</el-collapse-item>
</el-collapse>
</template>
<!--分割线-->
<template v-else-if="element.type === 'divider'">
<el-divider v-bind="element.control"
>{{ element.item && element.item.label }}
</el-divider>
<el-divider v-bind="element.control">{{ element.item && element.item.label }}</el-divider>
</template>
<!--div容器-->
<template v-else-if="element.type === 'div'">
<div
class="div-layout"
@ -370,7 +368,7 @@ const dataList = ref<any>(props.data)
<form-group :data="element.list" data-type="not-nested" />
</div>
</template>
<!--弹性布局-->
<template v-else-if="element.type === 'flex'">
<form-group
:data="element.list"
@ -382,10 +380,11 @@ const dataList = ref<any>(props.data)
style="position: relative; top: -28px; left: 10px"
v-if="element.config.addBtnText && type === 5"
size="small"
>{{ element.config.addBtnText }}</el-button
>
{{ element.config.addBtnText }}
</el-button>
</template>
<!--按钮-->
<template v-else-if="element.type === 'button'">
<div
:class="[element.config?.className]"
@ -394,17 +393,18 @@ const dataList = ref<any>(props.data)
<el-button
v-bind="element.control"
@click="clickBtn(element.control)"
>{{ element.control?.label }}</el-button
>
{{ element.control?.label }}
</el-button>
</div>
</template>
<template v-else-if="element.type === 'inputSlot' && type !== 5">
<!-- 除设计外其他无需处理-->
</template>
<!--其他组件-->
<FormItem v-else :data="element" />
<!--组件设计外功能框架-->
<template v-if="type === 5">
<div class="drag-control">
<div class="item-control">
@ -427,7 +427,6 @@ const dataList = ref<any>(props.data)
<div class="tooltip" style="display: none;">{{ element.name }}</div>
</template>
</div>
</template>
</draggable>
@ -435,3 +434,4 @@ const dataList = ref<any>(props.data)
<style lang='scss' scoped>
</style>

437
src/components/DesignForm/public/form/formGroup1.vue

@ -0,0 +1,437 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 08:46:51
@ 备注: 表单组
-->
<script lang='ts' setup>
import { computed, watch, inject, onUnmounted } from 'vue'
import Draggable from 'vuedraggable-es'
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 } from '@/api/DesignForm/types'
import {
constFormBtnEvent,
constFormProps
} from '@/api/DesignForm/utils'
import { Md5 } from 'ts-md5';
import { jsonParseStringify } from '@/utils/DesignForm'
const props = withDefaults(
defineProps<{
data: FormList[]
}>(),
{
data: () => {
return []
}
}
)
const store = useDesignFormStore() as any
const formProps = inject(constFormProps, {}) as any
const type = computed(() => {
console.log("11111",formProps.value.type)
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
}
)
const activeKey = computed(() => {
return store.activeKey
})
//
const notNested = (type: string) => {
const controlType = ['grid', 'table', 'tabs', 'div', 'flex', 'card']
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') //
if (isNested === 'not-nested' && notNested(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'
]
if (!notNeedItem.includes(obj.type)) {
objectItem = {
item: {
label: label
}
}
}
// name
let nameObj = {}
const notNeedName = [
'txt',
'title',
'button',
'grid',
'tabs',
'divider',
'div',
'card'
]
if (!notNeedName.includes(obj.type) && !obj.name) {
nameObj = {
name: obj.type + key
}
}
Object.assign(obj, nameObj, objectItem)
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
}
}
//
const groupClick = (item: any, ele?: string) => {
//
if (type.value !== 5) {
return
}
if (ele) {
item.type = ele
}
store.setActiveKey(getGroupName(item))
store.setControlAttr(item)
// grid
state.gridAdd = item.type === 'grid'
state.clone = !notNested(item.type)
}
//
const getFormItemStyle = (ele: FormList) => {
if (ele.config?.span === 0) {
return { width: 'auto', margin: '0 5px' }
}
if (ele.config && ele.config.span) {
return { width: (ele.config.span / 24) * 100 + '%' }
}
}
//
const linksShow = (el: FormList, index: number) => {
//
if (!el.config) {
return true
}
const key = el.config.linkKey
const value = el.config.linkValue
const linkResult = el.config.linkResult
if (key && value && type.value !== 5) {
const Fn = new Function('$', `return (${value})`)
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
}
}
// namevIf
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) => {
// 0: '',
// 1: '',
// 2: '',
// 3: '()'
if (type.value !== 5) {
//
injectBtnEvent && injectBtnEvent(control)
}
}
onUnmounted(() => {
// console.log('formGroup onUnmounted')
dataList.value = {}
store.setActiveKey('')
store.setControlAttr({})
})
</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"
>
<form-group :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"
>
<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'">
<div class="form-table" v-if="type === 5">
<form-group :data="element.list" data-type="not-nested" />
</div>
<child-table v-else :data="element" />
</template>
<template v-else-if="element.type === 'grid'">
<el-row class="form-row" :class="[element.className]">
<el-col
class="form-col"
:class="{
'active-col': activeKey === getGroupName(col),
[col.className]: col.className
}"
v-bind="col.attr"
v-for="(col, i) in element.columns"
:key="i"
@click.stop="groupClick(col, 'gridChild')"
>
<form-group :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>
<form-group :data="element.list" data-type="not-nested" />
</el-collapse-item>
</el-collapse>
</template>
<template v-else-if="element.type === 'divider'">
<el-divider v-bind="element.control"
>{{ element.item && element.item.label }}
</el-divider>
</template>
<template v-else-if="element.type === 'div'">
<div
class="div-layout"
v-bind="element.control"
:class="{
[element.className]: element.className,
inline: element.config?.inline,
[element.config?.textAlign]: element.config?.textAlign
}"
>
<form-group :data="element.list" data-type="not-nested" />
</div>
</template>
<template v-else-if="element.type === 'flex'">
<form-group
:data="element.list"
data-type="not-nested"
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)"
>{{ element.control?.label }}</el-button
>
</div>
</template>
<template v-else-if="element.type === 'inputSlot' && type !== 5">
<!-- 除设计外其他无需处理-->
</template>
<FormItem v-else :data="element" />
<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: none;">{{ element.name }}</div>
</template>
</div>
</template>
</draggable>
</template>
<style lang='scss' scoped>
</style>

23
src/components/DesignForm/public/form/formItem.vue

@ -55,7 +55,11 @@ const config = computed(() => {
return props.data.config || {}
})
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)
const changeEvent = inject(constControlChange, '') as any
@ -338,9 +342,12 @@ watch(
// -----------------------
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
@ -352,19 +359,20 @@ const fileList = computed<any>(() => {
})
//
const uploadSuccess = (response: any, uploadFile: any, uploadFiles: any) => {
console.log("response==>",response)
console.log("uploadFile==>",uploadFile)
console.log("uploadFiles==>",uploadFiles)
// 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.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)
// console.log("uploadSuccess===>",control.value)
// console.log("uploadSuccess=fileList==>",fileList)
}
//
const uploadRemove = (uploadFile: any, uploadFiles: any) => {
@ -422,9 +430,10 @@ onMounted(() => {
getAxiosOptions()
})
onUnmounted(() => {})
const imgUploadApiUrl = import.meta.env.VITE_APP_BASE_API+"/api/upordown"
</script>
<template>
<el-form-item
v-bind="data.item"
:prop="tProp || data.name"

56
src/components/DesignForm/public/form/tinymce.vue

@ -1,12 +1,13 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 16:38:32
@ 时间: 2023-09-19 13:09:24
@ 备注:
-->
<script lang='ts' setup>
import { onMounted, watch, ref, computed, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { getRequest } from '@/api/DesignForm'
import { newUploadFileApi } from '@/api/file/index'
const props = withDefaults(
defineProps<{
modelValue: string
@ -65,28 +66,23 @@ const commInit = {
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)
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
}
}
getRequest('upload', params, options)
.then(res => {
// console.log(res)
// console.log(res.data.path)
if (res.data.code === 1) {
resolve(res.data.path) //
// console.log('[]', res.data)
} else {
reject('上传失败')
}
newUploadFileApi(params)
.then(res =>{
// console.log("",res.data)
resolve(res.data.url)
})
.catch(() => {
reject('上传出错,示例暂不提供上传接口')
.catch(()=>{
reject('上传出错,请查看你上传的文件是否符合要求!')
})
})
const fileUpload = (callback: any, value: string, meta: any) => {
@ -98,8 +94,6 @@ const fileUpload = (callback: any, value: string, meta: any) => {
input.click()
input.onchange = () => {
const file = input?.files && input.files[0] //
// console.log(file)
// metafile_picker_types
let attr = {}
if (meta.filetype === 'file') {
attr = { text: file?.name }
@ -110,13 +104,6 @@ const fileUpload = (callback: any, value: string, meta: any) => {
if (meta.filetype === 'media') {
// attr={source2: 'alt.ogg', poster: 'image.jpg'}
}
/*if(file.type.slice(0,5)=='image'&&file.size/1024/1024>2){
alert("上传失败,图片大小请控制在2M以内")
}else if(file.type.slice(0,5)=='video'&&file.size/1024/1024>500){
alert("上传失败,视频大小请控制在 500M 以内")
}else if(file.size/1024/1024>10){
alert("上传失败,文件大小请控制在 10M 以内")
}*/
const params = new FormData()
params.append('file', file as any)
let options = {}
@ -125,16 +112,13 @@ const fileUpload = (callback: any, value: string, meta: any) => {
url: props.blobUrl
}
}
getRequest('upload', params, options)
.then(res => {
if (res.data.code === 1) {
callback(res.data.path, attr) //
} else {
ElMessage.error(res.data?.message)
}
newUploadFileApi(params)
.then(res =>{
// console.log("",res.data)
callback(res.data.url, attr)
})
.catch(res => {
ElMessage.error(res.data?.message)
ElMessage.error(res.data?.msg)
})
}
}
@ -174,6 +158,14 @@ const myInit = computed(() => {
props.config?.style === 'simple' ? simpleInit : defaultInit
return Object.assign(commInit, styleType)
})
onMounted(() => {
// @ts-ignore
tinymce.init(myInit.value)

203
src/components/DesignForm/public/form/tinymce_1.vue

@ -0,0 +1,203 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 16:38:32
@ 备注:
-->
<script lang='ts' setup>
import { onMounted, watch, ref, computed, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { getRequest } from '@/api/DesignForm'
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())
let options = {}
if (props.imgUrl) {
options = {
url: props.imgUrl
}
}
getRequest('upload', params, options)
.then(res => {
// console.log(res)
// console.log(res.data.path)
if (res.data.code === 1) {
resolve(res.data.path) //
// console.log('[]', res.data)
} else {
reject('上传失败')
}
})
.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] //
// console.log(file)
// metafile_picker_types
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'}
}
/*if(file.type.slice(0,5)=='image'&&file.size/1024/1024>2){
alert("上传失败,图片大小请控制在2M以内")
}else if(file.type.slice(0,5)=='video'&&file.size/1024/1024>500){
alert("上传失败,视频大小请控制在 500M 以内")
}else if(file.size/1024/1024>10){
alert("上传失败,文件大小请控制在 10M 以内")
}*/
const params = new FormData()
params.append('file', file as any)
let options = {}
if (props.blobUrl) {
options = {
url: props.blobUrl
}
}
getRequest('upload', params, options)
.then(res => {
if (res.data.code === 1) {
callback(res.data.path, attr) //
} else {
ElMessage.error(res.data?.message)
}
})
.catch(res => {
ElMessage.error(res.data?.message)
})
}
}
const defaultInit = {
plugins: buttonPlugins, //
toolbar: toolbar, // false
menubar: true, // 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, // csscsscss
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', //linkimageaxupimgsmedia
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>

4
src/layout/components/AppMain.vue

@ -7,11 +7,11 @@ const tagsViewStore = useTagsViewStore();
<template>
<section class="app-main">
<router-view v-slot="{ Component, route }">
<transition name="router-fade" mode="out-in">
<!-- <transition name="router-fade" mode="out-in"> -->
<keep-alive :include="tagsViewStore.cachedViews">
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</transition>
<!-- </transition> -->
</router-view>
</section>
</template>

2
src/utils/DesignForm/index.ts

@ -39,7 +39,7 @@ export const dateFormatting = (time: any, cFormat?: string) => {
w: date.getDay()
}
return format.replace(/{(y|m|d|h|i|s|w)+}/g, (result, key) => {
let value = formatObj[key]
let value:any = formatObj[key]
if (key === 'w') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}

84
src/utils/requestfile.ts

@ -0,0 +1,84 @@
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
import { useUserStoreHook } from '@/store/modules/user';
// 创建 axios 实例
const service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 50000,
});
// 请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const userStore = useUserStoreHook();
if (userStore.tokenIng) {
config.headers.Authorization = userStore.tokenIng;
}
if (userStore.userKey) {
config.headers["user-key"] = userStore.userKey;
}
if (userStore.userToken) {
config.headers["user-token"] = userStore.userToken;
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
const { code, msg } = response.data;
if (code === 0) {
return response.data;
}
if (code === 7 || code === 300 || code === 301 || code === 302){
ElMessageBox.confirm("身份令牌已失效!请重新登录!", "提示", {
confirmButtonText: "确定",
type: "warning",
}).then(() => {
localStorage.clear();
window.location.href = "/";
});
return response.data;
}
// 响应数据为二进制流处理(Excel导出)
if (response.data instanceof ArrayBuffer) {
return response;
}
ElMessage.error(msg || '系统出错');
return Promise.reject(new Error(msg || 'Error'));
},
(error: any) => {
if (error.response.data) {
const { code, msg } = error.response.data;
// token 过期,重新登录
if (code === 'A0230') {
ElMessageBox.confirm('当前页面已失效,请重新登录', '提示', {
confirmButtonText: '确定',
type: 'warning'
}).then(() => {
localStorage.clear();
window.location.href = '/';
});
}else if(code === 7 || code === 300 || code === 301 || code === 302){
ElMessageBox.confirm("身份令牌已失效!请重新登录!", "提示", {
confirmButtonText: "确定",
type: "warning",
}).then(() => {
localStorage.clear();
window.location.href = "/";
});
} else {
ElMessage.error(msg || '系统出错');
}
}
return Promise.reject(error.message);
}
);
// 导出 axios 实例
export default service;

162
src/views/sysworkflow/codepage/createform.vue

@ -34,11 +34,96 @@ import { ElMessage } from 'element-plus'
import { useLayoutStore } from '@/store/DesignForm/layout'
import { FormData,formStruct,DrawerStruct } from '@/api/DesignForm/types'
import { customerFormVersionCont } from '@/api/DesignForm/type'
import { saveProductionForm,getOneProductionForm,haveCustomerFormVersion,editCustomerFormInfo,saveAsNewVersion,enableVersion } from '@/api/DesignForm/requestapi'
import { saveProductionForm,getOneProductionForm,haveCustomerFormVersion,editCustomerFormInfo,saveAsNewVersion,enableVersion,judgeSubmitCancel } from '@/api/DesignForm/requestapi'
const isSave = ref(false)
const versionCont = ref<customerFormVersionCont[]>([])
const versionId = ref<string>("")
const submitButton = {
type: "div",
control:
{},
config:
{
textAlign: "center",
span: ""
},
list: [
{
type: "button",
control:
{
label: "保存",
type: "primary",
key: "submit"
},
config:
{
textAlign: "center"
}
}]
}
const cancelButton = {
type: "div",
control:
{},
config:
{
textAlign: "center",
span: ""
},
list: [
{
type: "button",
control:
{
label: "返回",
type: "danger",
key: "cancel"
},
config:
{
textAlign: "center"
}
}]
}
const submitAndCancelButton = {
type: "div",
control:
{},
config:
{
span: 24,
textAlign: "center"
},
list: [
{
type: "button",
control:
{
label: "保存",
type: "primary",
key: "submit"
},
config:
{
span: 0
}
},
{
type: "button",
control:
{
label: "返回",
type: "danger",
key: "cancel"
},
config:
{
span: 0
}
}]
};
const props = defineProps({
draweropenclose:{
@ -312,6 +397,32 @@ const getInitData = () => {
//
const saveOtherData = () =>{
isSave.value = true
let formJsonData = JSON.stringify(state.formData)
// judgeSubmitCancel({"name":formJsonData})
// .then((data:any) =>{
// if(data.code == 0){
// switch (data.data){
// case 1:
// break;
// case 2:
// state.formData.list.push(cancelButton)
// break;
// case 3:
// state.formData.list.push(submitButton)
// break;
// default:
// state.formData.list.push(submitAndCancelButton)
// }
// othenSaveFormCont()
// }else{
// ElMessage.error('')
// }
// })
othenSaveFormCont()
}
//
function othenSaveFormCont(){
let params: any = {
jsondata:JSON.stringify(state.formData),
data: objToStringify(state.formData),
@ -353,6 +464,30 @@ const saveOtherData = () =>{
//
const editSaveData = () =>{
// console.log("---------->",versionId.value)
// let formJsonData = JSON.stringify(state.formData)
// judgeSubmitCancel({"name":formJsonData})
// .then((data:any) =>{
// if(data.code == 0){
// switch (data.data){
// case 1:
// break;
// case 2:
// state.formData.list.push(cancelButton)
// break;
// case 3:
// state.formData.list.push(submitButton)
// break;
// default:
// state.formData.list.push(submitAndCancelButton)
// }
// writeDataFormNwe()
// }else{
// ElMessage.error('')
// }
// })
writeDataFormNwe()
}
function writeDataFormNwe(){
let params: any = {
jsondata:JSON.stringify(state.formData),
data: objToStringify(state.formData),
@ -396,6 +531,31 @@ const editSaveData = () =>{
//()
const saveDataNew = () => {
isSave.value = true
// let formJsonData = JSON.stringify(state.formData)
// judgeSubmitCancel({"name":formJsonData})
// .then((data:any) =>{
// if(data.code == 0){
// switch (data.data){
// case 1:
// break;
// case 2:
// state.formData.list.push(cancelButton)
// break;
// case 3:
// state.formData.list.push(submitButton)
// break;
// default:
// state.formData.list.push(submitAndCancelButton)
// }
// writeDataForm()
// }else{
// ElMessage.error('')
// }
// })
writeDataForm()
}
//
function writeDataForm(){
let params: any = {
jsondata:JSON.stringify(state.formData),
data: objToStringify(state.formData),

230
src/views/sysworkflow/codepage/datatablestructure.vue

@ -0,0 +1,230 @@
<!--
@ 作者: 秦东
@ 时间: 2023-09-13 10:43:12
@ 备注: 数据结构表单
-->
<script lang='ts' setup>
import { publicFormTableStruct,formTabelStruct } from "@/api/DesignForm/type";
import { callBackFormTableVersion,haveFormTabelcont,optimizeOrRepairFormTable,haveFormTablelist } from '@/api/DesignForm/requestapi'
//
import SetupField from '@/views/sysworkflow/codepage/setupfield.vue'
import {
Ticket,
Finished
} from '@element-plus/icons-vue'
const props = defineProps({
isshow:{
type:Boolean,
default:true
},
formcont:{
type:Object,
default(){
return {}
}
},
})
const emits = defineEmits(["update:isshow"]);
const isShow = computed({
get: () => props.isshow,
set: (val) => {
emits("update:isshow", val);
},
});
//
const formTableFieldList = ref<formTabelStruct[]>()
const versionIndex = ref("") //
const formTableIndex = ref("") //
const versionAry = ref<publicFormTableStruct[]>([]) //
const formTableAry = ref<publicFormTableStruct[]>([]) //
const isEditForm = ref(false)
const formTableCont = ref<publicFormTableStruct>() //
const isEditFormField = ref(false)
const tableLoading = ref(false)
//
const clickVersion = (val:any) =>{
// console.log("",val,versionIndex.value)
formTableAry.value.slice(0,formTableAry.value.length)
// console.log("",formTableAry.value)
haveFormTablelist({id:val.toString()})
.then(({data})=>{
// console.log("",data,formTableAry.value)
formTableAry.value = data
if(data.length > 0){
data.forEach( item =>{
if(item.ismain){
formTableIndex.value = item.name
}
})
}
})
.finally(()=>{
getTableFieldList(versionIndex.value,formTableIndex.value)
})
}
//
const clickFormTable = (val:any) =>{
// console.log("",val,formTableIndex.value)
getTableFieldList(versionIndex.value,val)
}
//
const getVersionFormTable = () =>{
callBackFormTableVersion({id:props.formcont.id})
.then(({ data }) =>{
// console.log("--->",data)
versionAry.value = data.version
formTableAry.value = data.tablelist
if(data.version){
if(data.version.length > 0){
data.version.forEach( item =>{
if(item.ismain){
versionIndex.value = item.versionid
}
})
}
}
if(data.tablelist){
if(data.tablelist.length > 0){
data.tablelist.forEach( item =>{
if(item.ismain){
formTableIndex.value = item.name
}
})
}
}
})
.finally(() =>{
// console.log("-->",formTableIndex.value,versionIndex.value)
getTableFieldList(versionIndex.value,formTableIndex.value)
});
}
function getTableFieldList(id:string,name:string){
tableLoading.value = true;
haveFormTabelcont({"id":id, "name":name})
.then(({data}) =>{
// console.log("-->",data)
formTableFieldList.value = data.filedlist
isEditForm.value = data.isedit
})
.finally(()=>{
tableLoading.value = false;
})
}
//
watch(()=>props.isshow,()=>{
if(props.isshow){
getVersionFormTable()
}
})
//
const editCustomerFormField = (val:any) =>{
// optimizeOrRepairFormTable()
formTableCont.value = val
isEditFormField.value = true
}
//
const optimizeOrRepairTable = (val:number) =>{
optimizeOrRepairFormTable({name:formTableIndex.value,optimizerender:val})
.then((data:any)=>{
// console.log("",data,formTableIndex.value,val)
ElMessage.success(data.msg || '加载异常')
})
}
//
const refreshTable = () =>{
getTableFieldList(versionIndex.value,formTableIndex.value)
}
</script>
<template>
<el-dialog v-model="isShow" :title="'<'+props.formcont.name+'>数据结构'" width="70%" draggable>
<div class="common-layout">
<el-container>
<el-main style="padding: 0;">
<!-- 表结构 -->
<el-tabs v-model="formTableIndex" class="form_version" style="height: 40px;" @tab-change="clickFormTable">
<el-tab-pane v-for="item in formTableAry" :key="item.name" :name="item.name" >
<template #label>
<el-icon v-if="item.ismain"><Management /></el-icon>
<el-icon v-else><Memo /></el-icon>
{{ item.name }}
</template>
</el-tab-pane>
</el-tabs>
<el-table v-loading="tableLoading" :data="formTableFieldList" border height="460" style="width: 100%;">
<el-table-column fixed prop="field" label="字段" width="120" />
<el-table-column prop="type" label="类型" width="120" />
<el-table-column prop="collation" label="排序规则" width="180" />
<el-table-column prop="attribute" label="属性" width="100" />
<el-table-column prop="null" label="空" align="center" />
<el-table-column prop="default" label="默认值" align="center" />
<el-table-column prop="extra" label="补充信息" width="200" />
<el-table-column fixed="right" prop="comment" label="备注" width="200" />
<el-table-column fixed="right" v-if="isEditForm" label="操作" align="center">
<template #default="scope">
<el-button
type="primary"
link
size="small"
@click.stop="editCustomerFormField(scope.row)"
>
<i-ep-edit />编辑
</el-button>
</template>
</el-table-column>
</el-table>
<el-row style="margin-top: 10px;margin-bottom: 10px;">
<el-col :span="24">
<el-button :icon="Finished" type="primary" @click.stop="optimizeOrRepairTable(1)">优化表单</el-button>
<el-button :icon="Ticket" type="warning" @click.stop="optimizeOrRepairTable(2)">修复表单</el-button>
</el-col>
</el-row>
</el-main>
<el-aside width="100px">
<!-- 版本 -->
<el-tabs v-model="versionIndex" tab-position="right" style="height: 500px;" @tab-change="clickVersion">
<el-tab-pane v-for="item in versionAry" :key="item.versionid" :label="item.name" :name="item.versionid">
<template #label>
<div class="version_field" title="ConfigConfigConfig">
{{ item.name }}
</div>
</template>
</el-tab-pane>
</el-tabs>
</el-aside>
</el-container>
</div>
<SetupField v-model:isEditFormField="isEditFormField" :formtablecont="formTableCont" :formname="formTableIndex" @refreshtable="refreshTable" />
</el-dialog>
</template>
<style lang='scss'>
.form_version{
height: 500px;
}
.form_table{
height: 500px;
width: 100%;
overflow-y: auto;
}
.form_version > .el-tabs__content{
padding: 0;
}
.version_field{
width:60px;
// white-space: normal;
// word-break: break-word;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.but_clic{
margin-top: 10px;
}
</style>

40
src/views/sysworkflow/codepage/index.vue

@ -9,6 +9,7 @@ import { getCustomerFormList,getProductionMarkForm,editProductionFormStatus } fr
//
import CreateForm from '@/views/sysworkflow/codepage/createform.vue'
import SetupConfig from '@/views/sysworkflow/codepage/setupconfig.vue'
import DataTableStructure from '@/views/sysworkflow/codepage/datatablestructure.vue'
const queryParams = reactive<SearchForm>({
@ -33,14 +34,17 @@ const formId = ref<string>("");
function handleQuery(){
getCustomerFormList(queryParams)
.then(({ data }) => {
console.log("搜索表单-->",data);
// console.log("-->",data);
total.value = data.total
contList.value = data.list
})
.finally(() => {})
}
//
function resetQuery(){}
function resetQuery(){
queryParams.page = 1;
queryParams.keywords = "";
}
//
function openDialog(){
formId.value = ""
@ -48,7 +52,7 @@ function openDialog(){
.then(({data})=>{
formConfigCont.formlogo = data.formlogo
formConfigCont.formname = data.formname
console.log("新增表单",formConfigCont)
// console.log("",formConfigCont)
})
.finally(()=>{
drawerOpenOrClose.value = true;
@ -83,7 +87,7 @@ function handleDelete(){
}
//
function editCustomerFormState(cont:customerFormCont){
console.log("删除单一自定义表单",cont)
// console.log("",cont)
editIds.push(cont.id)
ElMessageBox.confirm(
'请问是否真的删除?删除后数据将无法找回!',
@ -122,14 +126,21 @@ onMounted(()=>{
});
window.addEventListener("resize", function(){
drawerWith.value = window.innerWidth -220
console.log("搜索表单-->",window.innerWidth);
// console.log("-->",window.innerWidth);
})
//
function editCustomerForm(cont:customerFormCont){
formId.value = cont.id.toString();
drawerOpenOrClose.value = true;
}
const dataTableIsShow = ref(false)
const formCont = ref<customerFormCont>()
//
const openDataTableStructure = (cont:customerFormCont) =>{
formCont.value = cont
dataTableIsShow.value = true;
// console.log("",cont)
}
</script>
<template>
<div class="app-container">
@ -144,13 +155,13 @@ function editCustomerForm(cont:customerFormCont){
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery"
><template #icon><i-ep-search /></template>搜索</el-button
>
<el-button type="primary" @click="handleQuery">
<template #icon><i-ep-search /></template>搜索
</el-button>
<el-button @click="resetQuery">
<template #icon><i-ep-refresh /></template>
重置</el-button
>
<template #icon>
<i-ep-refresh /></template>重置
</el-button>
</el-form-item>
</el-form>
</div>
@ -173,7 +184,7 @@ function editCustomerForm(cont:customerFormCont){
@selection-change="handleSelectionChange"
>
<el-table-column fixed type="selection" width="55" align="center" />
<el-table-column fixed label="表单名称" prop="name" />
<el-table-column fixed label="表单名称" prop="name" width="350" />
<el-table-column label="分类" align="center" width="150">
<template #default="scope">
<el-tag v-if="scope.row.classify === 1" effect="plain">表单</el-tag>
@ -208,7 +219,7 @@ function editCustomerForm(cont:customerFormCont){
type="warning"
link
size="small"
@click.stop="setupCustomerForm(scope.row)"
@click.stop="openDataTableStructure(scope.row)"
>
<i-ep-MessageBox />数据结构
</el-button>
@ -244,6 +255,7 @@ function editCustomerForm(cont:customerFormCont){
<CreateForm v-model:draweropenclose="drawerOpenOrClose" :formid="formId" :formconfigcont="formConfigCont" @handlequery="handleQuery" />
</el-drawer>
<SetupConfig v-model:show="show" :editid="editid" @handle_query="handleQuery" />
<DataTableStructure v-model:isshow="dataTableIsShow" :formcont="formCont" />
</template>
<style lang='scss' scoped>
.drawerClass{

2
src/views/sysworkflow/codepage/page.vue

@ -67,7 +67,7 @@ const getFormData = () => {
state.formData = stringToObj(result.data)
state.dict = string2json(result.dict)
formEl.value.getData({ formId: state.formId, id: 1})
console.log("res----------->", res.data)
console.log("res----------->", formEl.value)
nextTick(() => {
state.loading = false
})

19
src/views/sysworkflow/codepage/setupconfig.vue

@ -19,7 +19,7 @@ const props = defineProps({
default:""
},
})
const emits = defineEmits(["update:show","handlequery"]);
const emits = defineEmits(["update:show","handle_query"]);
const isShow = computed({
get: () => props.show,
set: (val) => {
@ -31,7 +31,7 @@ const dataInfo = reactive<setupCustomerFormCont>({
name:"",
permit:[],
states:1,
status:true
openclose:false,
})
//
const caseProps = {
@ -60,6 +60,7 @@ function setupSave(){
}
})
.finally(() => {
emits("handle_query");
closeDialog()
})
}
@ -69,7 +70,7 @@ function initData(){
dataInfo.name = "",
dataInfo.permit = [],
dataInfo.states = 1,
dataInfo.status = true
dataInfo.openclose = true
orgOptionsList.value?.splice(orgOptionsList.value.length);
}
//
@ -82,9 +83,9 @@ watch(()=>props.show,()=>{
dataInfo.permit = res.data.permit_list
dataInfo.states = res.data.states
if(res.data.states == 1){
dataInfo.status = true
dataInfo.openclose = true
}else{
dataInfo.status = false
dataInfo.openclose = false
}
console.log(dataInfo)
})
@ -97,8 +98,8 @@ watch(()=>props.show,()=>{
initData()
}
})
watch(()=>dataInfo.status,()=>{
if(dataInfo.status){
watch(()=>dataInfo.openclose,()=>{
if(dataInfo.openclose){
dataInfo.states = 1
}else{
dataInfo.states = 2
@ -106,7 +107,7 @@ watch(()=>dataInfo.status,()=>{
})
</script>
<template>
<el-dialog v-model="isShow" title="Tips" width="30%" draggable>
<el-dialog v-model="isShow" title="设置表单信息" width="30%" draggable>
<el-form :model="dataInfo" label-width="80px">
<el-form-item label="表单名称">
<el-input v-model="dataInfo.name" />
@ -123,7 +124,7 @@ watch(()=>dataInfo.status,()=>{
</el-form-item>
<el-form-item label="状态">
<el-switch
v-model="dataInfo.status"
v-model="dataInfo.openclose"
:active-action-icon="View"
:inactive-action-icon="Hide"
active-text="启用"

237
src/views/sysworkflow/codepage/setupfield.vue

@ -0,0 +1,237 @@
<!--
@ 作者: 秦东
@ 时间: 2023-09-14 09:47:27
@ 备注: 编辑表单字段
-->
<script lang='ts' setup>
import { gogoBackFormTabelStruct } from "@/api/DesignForm/type";
import { formFieldHandle,editFormField } from '@/api/DesignForm/requestapi'
const fieldType = ["tinyint","smallint","mediumint","int","integer","bigint","decimal", "float", "double","char","varchar","binary","varbinary","enum","set","text","tinytext","mediumtext","longtext","blob","year","date","time","datetime","timestamp"];
const props = defineProps({
isEditFormField:{
type:Boolean,
default:true
},
formname:{
type:String,
default:""
},
formtablecont:{
type:Object,
default(){
return {}
}
},
})
const unsignedIsShow = ref(false); //
const decimalIsShow = ref(false); //
const fieldLenghtIsShow = ref(false); //
const isNull = ref(false); //
const butLoad = ref(false);
const formTableField = reactive<gogoBackFormTabelStruct>({
formname:props.formname,
field:"",
type:"",
attribute:"",
collation:"",
null:"",
key:"",
default:"",
extra:"",
privileges:"",
comment:"",
integer:"",
decimal:"",
})
const dialogTitle = ref<string>()
const isEditOk = ref(false)
const emits = defineEmits(["update:isEditFormField","refreshtable","xxxxx"]);
const isShow = computed({
get: () => props.isEditFormField,
set: (val) => {
emits("update:isEditFormField", val);
emits("refreshtable");
},
});
watch(()=>props.isEditFormField,()=>{
// console.log("----->",props.isEditFormField,props.formtablecont)
if(props.isEditFormField){
if(props.formtablecont.comment != null && props.formtablecont.comment != ""){
dialogTitle.value = "编辑<"+props.formtablecont.field+">字段(PS:"+props.formtablecont.comment+")"
}else{
dialogTitle.value = "编辑<"+props.formtablecont.field+">字段"
}
formFieldHandle(props.formtablecont)
.then(({data})=>{
// console.log("---1-->",data)
formTableField.formname=props.formname
formTableField.field = data.field;
formTableField.type = data.type;
formTableField.attribute = data.attribute;
formTableField.collation = data.collation;
formTableField.null = data.null;
formTableField.key = data.key;
formTableField.default = data.default;
formTableField.extra = data.extra;
formTableField.privileges = data.privileges;
formTableField.comment = data.comment;
formTableField.integer = data.integer;
formTableField.decimal = data.decimal;
if(["tinyint","smallint","mediumint","int","integer","bigint","decimal", "float", "double"].indexOf(data.type) != -1){
unsignedIsShow.value = true
}else{
unsignedIsShow.value = false
}
if(["decimal", "float", "double"].indexOf(data.type) != -1){
decimalIsShow.value = true
}else{
decimalIsShow.value = false
}
if(["enum","set","text","tinytext","mediumtext","longtext","blob","year","date","time","datetime","timestamp"].indexOf(data.type) != -1){
fieldLenghtIsShow.value = false
}else{
fieldLenghtIsShow.value = true
}
})
// formTableField.value = props.formtablecont
}else{
if(isEditOk.value){
emits("refreshtable")
}
initData()
// formTableField.value=new Value(props.formtablecont)
}
})
//
function initData(){
formTableField.formname="";
formTableField.field = ""; //field;
formTableField.type = ""; //type;
formTableField.attribute = ""; //attribute;
formTableField.collation = ""; //collation;
formTableField.null = ""; //null;
formTableField.key = ""; //key;
formTableField.default = ""; //default;
formTableField.extra = ""; //extra;
formTableField.privileges = ""; //privileges;
formTableField.comment = ""; //comment;
formTableField.integer = ""; //integer;
formTableField.decimal = ""; //decimal;
unsignedIsShow.value = false;
decimalIsShow.value = false;
fieldLenghtIsShow.value = false;
}
/**
* 关闭弹窗
*/
function closeDialog() {
isShow.value = false;
emits("update:isEditFormField", false);
initData();
}
//
function sendFormData(){
butLoad.value=true;
// console.log("--->",props.formname,formTableField)
editFormField(formTableField)
.then((data)=>{
// console.log("--1->",data)
ElMessage.success('成功')
isEditOk.value=true;
})
.finally(()=>{
butLoad.value=false;
closeDialog();
})
}
//
const judgeFieldType = (typeStr:string) => {
if(["tinyint","smallint","mediumint","int","integer","bigint","decimal", "float", "double"].indexOf(typeStr) != -1){
unsignedIsShow.value = true
formTableField.attribute = "unsigned"
formTableField.integer = "3"
formTableField.decimal = ""
}else{
unsignedIsShow.value = false
formTableField.attribute = ""
}
if(["decimal", "float", "double"].indexOf(typeStr) != -1){
decimalIsShow.value = true
}else{
decimalIsShow.value = false
}
if(["enum","set","text","tinytext","mediumtext","longtext","blob","year","date","time","datetime","timestamp"].indexOf(typeStr) != -1){
fieldLenghtIsShow.value = false
formTableField.integer = ""
formTableField.decimal = ""
}else{
fieldLenghtIsShow.value = true
}
if(["char","varchar","binary","varbinary"].indexOf(typeStr) != -1){
formTableField.integer = "255"
}
}
</script>
<template>
<el-dialog
v-model="isShow"
width="550"
:title="dialogTitle"
append-to-body
draggable
@close="closeDialog"
>
<el-form :model="formTableField" label-width="80px" border>
<el-form-item label="字段">
{{ formTableField.field }}
</el-form-item>
<el-form-item label="类型">
<el-select v-model="formTableField.type" class="m-2" placeholder="请选择数据类型" @change="judgeFieldType(formTableField.type)">
<el-option
v-for="item in fieldType"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item v-if="unsignedIsShow" label="无符号">
<el-radio-group v-model="formTableField.attribute" class="ml-4">
<el-radio label="unsigned" size="large">正数</el-radio>
<el-radio label="" size="large">区分正负</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="不是Null">
<el-radio-group v-model="formTableField.null" class="ml-4">
<el-radio label="YES" size="large">YES</el-radio>
<el-radio label="NO" size="large">NO</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="fieldLenghtIsShow" label="长度">
<el-input v-model="formTableField.integer" />
</el-form-item>
<el-form-item v-if="decimalIsShow" label="小数点">
<el-input v-model="formTableField.decimal" />
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="formTableField.default" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="formTableField.comment" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="sendFormData">提交</el-button>
</span>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
</style>

14
src/views/taskplatform/taskmanagement/tasklist.vue

@ -0,0 +1,14 @@
<!--
@ 作者: 秦东
@ 时间: 2023-09-21 13:41:04
@ 备注: 任务
-->
<script lang='ts' setup>
</script>
<template>
<div>任务列表</div>
</template>
<style lang='scss' scoped>
</style>
Loading…
Cancel
Save