Compare commits

...

21 Commits

Author SHA1 Message Date
zzq 0ca73b71b9 按钮组对接发布,导出功能实现 2024-06-19 13:33:03 +08:00
Zhufu 78b2d33879 【表单设计】下拉列表添加使用字典字段 2024-06-19 10:42:43 +08:00
滕嵩 c7ea9deb0c 表单设计-级联选择,第二级的选项无法配置的bug 2024-06-19 10:01:07 +08:00
刘妍 336786356c 优化大屏页面第一次跳转图表不显示问题 2024-06-18 17:39:06 +08:00
刘妍 f2d783714a 大屏不继承layout 2024-06-18 15:32:52 +08:00
刘妍 89e22cf3e1 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-18 15:24:14 +08:00
刘妍 1af27d1841 驳回选择节点数据筛选,只获取审核任务 2024-06-18 15:24:11 +08:00
Zhufu 969774015c [流程设计]解析字段列表名称列被字段挤压问题 2024-06-18 14:55:37 +08:00
刘妍 2c8af2da8c Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-18 14:21:12 +08:00
刘妍 ec8f828c08 大屏代码更换路径,菜单可配置大屏菜单 2024-06-18 14:21:08 +08:00
Zhufu cf2e56868c 【流程设计弹窗】左侧空白修改 2024-06-18 11:17:02 +08:00
Zhufu 909566938f [流程发布]createOrModifyList结构变化修改 2024-06-18 11:08:52 +08:00
Zhufu 3867d86679 [流程发起]创建修改人时间是否显示同时受流程设计时控制 2024-06-18 10:39:32 +08:00
刘妍 6b63e96e5c Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-18 10:13:50 +08:00
刘妍 0315793722 待办、已办单独提出来;优化流程任务点击列设置取消字段再勾选展示时,列表溢出界面 2024-06-18 10:13:46 +08:00
Zhufu b1f7b943b8 【流程发起】创建修改人时间在选项卡里显示 2024-06-18 10:08:48 +08:00
徐景良 f8efe3b391 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-18 09:59:53 +08:00
徐景良 f82a05592d merge 2024-06-18 09:59:49 +08:00
Zhufu 365bec19f2 【流程设计】开始节点,任务节点中的字段解析列表添加一键全选功能 2024-06-18 09:08:14 +08:00
滕嵩 4b8d2fad0c 表单设计-自动建表-测试bug修改 2024-06-17 17:31:52 +08:00
Zhufu cebfc0d2d0 #68 表单发布及表单删除后菜单及时响应显示最新菜单列表 2024-06-17 16:49:24 +08:00
44 changed files with 1544 additions and 605 deletions

View File

@ -9,12 +9,10 @@ VITE_PUBLIC_PATH = /
#财源
# VITE_GLOB_API_URL= http://192.168.10.102:9500
#基础框架
VITE_GLOB_API_URL= http://192.168.10.102:9023
VITE_GLOB_API_URL=http://123.132.248.154:9104
# File upload address optional
# VITE_GLOB_UPLOAD_URL=http://192.168.10.104:9011
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=http://60.213.14.14:6070
# Interface prefix

View File

@ -12,8 +12,9 @@ enum Api {
GETFORMPAGEDATA = '/api/FormScheme/GetFormDataPage?id=', //获取表单分页数据
SAVEFORMDATA = '/api/FormScheme/SaveForm', //新增编辑自定义表单
DELFORMSDATA = '/api/FormScheme/DeleteFormData?id=', //删除表单数据
GETFORMSDATADETAIL = '/api/FormScheme/GetFormData', //删除表单数据详情
GETFORMSDATADETAIL = '/api/FormScheme/GetFormData', //表单数据详情
getFormData = '/api/FormScheme/GetFormData', //获取单行数据
exportForm = '/api/FormModule/Export?id=', //导出
}
/**
@ -40,3 +41,9 @@ export const getFormData = (params: getFormsParams) => {
url: `${Api.getFormData}?id=${params.id}&key=${params.key}&keyValue=${params.keyValue}`,
});
};
export const exportForm = (params: AccountParams) =>
defHttp.post<AccountListGetResultModel[]>({
url: Api.exportForm + params.id + '&mid=' + params.mid + '&code=' + params.code,
responseType: 'blob',
params,
});

View File

@ -11,6 +11,12 @@ enum Api{
export function getLeftTree() {
return defHttp.get({ url: Api.getLeftTree, });
}
export function getDictionaryType() {
return defHttp.get({ url: Api.getLeftTree, });
}
export function getDictionary(params){
return defHttp.get({ url: Api.getRightTable, params });
}
export function getRightTable(params) {
return defHttp.get({ url: Api.getRightTable, params });
}

View File

@ -12,6 +12,9 @@
:parentValue="cardGroupData[index].field"
ref="groupRef"
/>
<template v-for="(item, useIndex) in createOrModifyList[index]" :key="useIndex">
<CreateOrModifyComponent :data="item" />
</template>
</a-tab-pane>
</a-tabs>
</template>
@ -58,8 +61,10 @@
/>
</template>
<!-- todo 创建/修改 /时间 -->
<template v-for="(item, index) in createOrModifyList" :key="index">
<CreateOrModifyComponent :data="item" />
<template v-if="tabsColumns.length < 1">
<template v-for="(item, index) in createOrModifyList[0]" :key="index">
<CreateOrModifyComponent :data="item" />
</template>
</template>
</div>
</template>
@ -137,6 +142,7 @@
if (data) {
const scheme = JSON.parse(data.scheme);
scheme.formInfo.tabList.forEach((tabElement, index) => {
createOrModifyList.value.push([])
tabElement.schemas.forEach((element) => {
//
props.formConfig.forEach((configElement) => {
@ -221,7 +227,7 @@
getCardLayoutKey(element.columns[0].children, element.field);
}
if (['createuser', 'createtime', 'modifyuser', 'modifytime'].includes(element.type)) {
createOrModifyList.value.push(element);
createOrModifyList.value[index].push(element);
}
//
if (element.type === 'subTable') {
@ -369,6 +375,7 @@
data[mainTableName].forEach((item) => {
infoUseMainTableData.value = { ...infoUseMainTableData.value, ...item };
});
}
if (Object.keys(cardValues.value).length > 0) {
Object.keys(cardValues.value).forEach((cardItem) => {
@ -386,9 +393,8 @@
});
});
}
console.log("");
emit("getFormSuccess")
let mainTable = subTableDB.value.find((item) => item.type === 'main').name;
emit("getFormSuccess",data[mainTable][0])
}
const groupRef = ref();
async function getForm() {
@ -422,19 +428,21 @@
}
//
if (createOrModifyList.value.length > 0) {
createOrModifyList.value.forEach((item) => {
if (!item.componentProps.disabled) {
if (item.type == 'createuser' || item.type == 'modifyuser') {
query[item.field] = userName;
} else if (item.type == 'createtime' || item.type == 'modifytime') {
query[item.field] = nowTime.value;
createOrModifyList.value.forEach((childTab) => {
childTab.forEach(item => {
if (!item.componentProps.disabled) {
if (item.type == 'createuser' || item.type == 'modifyuser') {
query[item.field] = userName;
} else if (item.type == 'createtime' || item.type == 'modifytime') {
query[item.field] = nowTime.value;
}
}
}
})
});
}
return query;
} catch (error) {
console.log(error);
console.error(error);
return false;
}
}

View File

@ -245,7 +245,6 @@ const handlerUploadFile = ()=>{
axios.post(url,formData,{headers: {'Content-Type': 'multipart/form-data;charset=UTF-8','X-Token':"95a1a7a8"}}).then(res => {
alert(res.data.result[0].filePath);
handlerCreateLayer(res.data.result[0].filePath)
})
}

View File

@ -239,7 +239,6 @@
}
baseLayers.push(layers)
})
map.addControl(new SwitchLayerControl({
name:"图层管理" ,
position:"top-left",
@ -263,8 +262,6 @@
},
}
}),"top-left");
});
});
//
@ -747,10 +744,9 @@
handlerLocation,
handlerCancleDraw,
});
</script>
<style>
<style scoped>
.map-container {
width: 100%;
height: 100%;
@ -806,6 +802,7 @@
padding: 6px;
border-radius: 12px;
top: 5px;
right:0px;
}
.mapbox-gl-draw_ctrl-draw-btn {
width: 20px !important;
@ -814,7 +811,7 @@
}
.mapboxgl-ctrl-top-right {
width:360px;
}
.mapboxgl-ctrl-group button + button {
@ -894,7 +891,8 @@
padding:0px!important;
}
::v-deep .jas-ctrl-extend-desktop-container {
width:320px!important;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div :class="prefixCls" :style="{ width: `${props.width}px` }">
<div :class="prefixCls" style="width: 30%">
<a-tabs v-model:activeKey="configActiveName">
<a-tab-pane :tab="data.wfNodeName" key="1">
<!-- 开始节点 -->
@ -582,6 +582,7 @@
::v-deep .ant-tabs-content-holder {
overflow-y: auto;
padding-right: 10px;
}
.hidden {

View File

@ -102,6 +102,17 @@
:pagination="false"
v-if="node.formType == 1"
>
<template #headerCell="{ column }">
<template v-if="column.dataIndex === 'required'">
<a-checkbox v-model:checked="requiredCheck" @change="handleChangeCheck('required',$event)">{{column.title}}</a-checkbox>
</template>
<template v-if="column.dataIndex === 'disabled'">
<a-checkbox v-model:checked="disabledCheck" @change="handleChangeCheck('disabled',$event)">{{column.title}}</a-checkbox>
</template>
<template v-if="column.dataIndex === 'ifShow'">
<a-checkbox v-model:checked="ifShowCheck" @change="handleChangeCheck('ifShow',$event)">{{column.title}}</a-checkbox>
</template>
</template>
<template #bodyCell="{ column, text, record }">
<template v-if="['label', 'field'].includes(column.dataIndex)">
<div>
@ -191,6 +202,9 @@
const flowWfDataStore = flowStore();
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const requiredCheck = ref(false)
const disabledCheck = ref(false)
const ifShowCheck = ref(false)
//
const props = defineProps({
disabled: {
@ -224,22 +238,27 @@
{
title: '名称',
dataIndex: 'label',
width: 100,
},
{
title: '字段',
dataIndex: 'fieldName',
ellipsis: true,
},
{
title: '必填',
dataIndex: 'required',
width: 85,
},
{
title: '编辑',
dataIndex: 'disabled',
width: 85,
},
{
title: '查看',
dataIndex: 'ifShow',
width: 85,
},
],
formRelations: [],
@ -421,6 +440,22 @@
function handleDeleteAuthField(key) {
node.value.authFields = node.value.authFields.filter((item) => item.field !== key);
}
const handleChangeCheck = (type: string, data) => {
let checked = data.target.checked
node.value.authFields.forEach(item => {
switch (type) {
case 'required':
item.required = checked
break
case 'disabled':
item.disabled = checked
break
case 'ifShow':
item.ifShow = checked
break
}
})
}
</script>
<style lang="less" scoped>
.site-space-compact-wrapper {
@ -450,6 +485,9 @@
}
}
}
:deep(.ant-checkbox+span){
padding-inline-end: 0px;
}
.l-rblock {
width: 100%;
height: 100%;

View File

@ -246,11 +246,22 @@
:pagination="false"
v-if="node.formType == 1"
>
<template #headerCell="{ column }">
<template v-if="column.dataIndex === 'required'">
<a-checkbox v-model:checked="requiredCheck" @change="handleChangeCheck('required',$event)">{{column.title}}</a-checkbox>
</template>
<template v-if="column.dataIndex === 'disabled'">
<a-checkbox v-model:checked="disabledCheck" @change="handleChangeCheck('disabled',$event)">{{column.title}}</a-checkbox>
</template>
<template v-if="column.dataIndex === 'ifShow'">
<a-checkbox v-model:checked="ifShowCheck" @change="handleChangeCheck('ifShow',$event)">{{column.title}}</a-checkbox>
</template>
</template>
<template #bodyCell="{ column, text, record }">
<template v-if="['label', 'fieldName'].includes(column.dataIndex)">
<div>
<!-- <div> -->
{{ text }}
</div>
<!-- </div> -->
</template>
<template v-else-if="['required', 'disabled', 'ifShow'].includes(column.dataIndex)">
<div>
@ -549,6 +560,9 @@
const activeKey = ref('1');
const nodeId = ref('');
let node: any = ref({});
const requiredCheck = ref(false)
const disabledCheck = ref(false)
const ifShowCheck = ref(false)
const props = defineProps({
element: {
type: Object,
@ -614,22 +628,27 @@
{
title: '名称',
dataIndex: 'label',
width: 100,
},
{
title: '字段',
dataIndex: 'fieldName',
ellipsis: true,
},
{
title: '必填',
dataIndex: 'required',
width: 85,
},
{
title: '编辑',
dataIndex: 'disabled',
width: 85,
},
{
title: '查看',
dataIndex: 'ifShow',
width: 85,
},
],
isLooker: false,
@ -974,6 +993,22 @@
function handleDeleteAuthField(key) {
node.value.authFields = node.value.authFields.filter((item) => item.field !== key);
}
const handleChangeCheck = (type: string, data) => {
let checked = data.target.checked
node.value.authFields.forEach(item => {
switch (type) {
case 'required':
item.required = checked
break
case 'disabled':
item.disabled = checked
break
case 'ifShow':
item.ifShow = checked
break
}
})
}
defineExpose({});
</script>
@ -994,6 +1029,10 @@
padding: 0 !important;
}
:deep(.ant-checkbox+span){
padding-inline-end: 0px;
}
::v-deep .ant-space {
width: 90%;
margin-left: 5%;

View File

@ -70,6 +70,9 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
genMenus();
},
);
watch(() => permissionStore.getChangeMenu, () => {
genMenus();
})
// Handle left menu split
async function handleSplitLeftMenu(parentPath: string) {

View File

@ -23,15 +23,15 @@ const dashboard: AppRouteModule = {
title: t('routes.dashboard.analysis'),
},
},
{
path: '/dashboard/dataScreen',
name: 'DataScreen',
component: () => import('@/views/dashboard/dataScreen/index.vue'),
meta: {
// affix: true,
title: t('routes.dashboard.dataScreen'),
},
},
// {
// path: '/dashboard/dataScreen',
// name: 'DataScreen',
// component: () => import('@/views/dashboard/dataScreen/index.vue'),
// meta: {
// // affix: true,
// title: t('routes.dashboard.dataScreen'),
// },
// },
{
path: '/formCallPage',
name: 'formCallPage',

View File

@ -0,0 +1,17 @@
import { defineStore } from 'pinia';
import { ref } from 'vue'
export const useOnlineFormDesignStore = defineStore('onlineFormDesign', () => {
const selectOptions = ref({})
function setSelectOptions(key, data){
selectOptions.value[key] = data
}
function getSelectOption(key){
return selectOptions.value[key]? selectOptions.value[key] : []
}
return {
selectOptions,
setSelectOptions,
getSelectOption,
}
})

View File

@ -26,6 +26,7 @@ import { PageEnum } from '@/enums/pageEnum';
import { router } from '@/router';
import { LAYOUT } from '@/router/constant';
import dayjs from 'dayjs';
interface PermissionState {
// Permission code list
@ -42,6 +43,7 @@ interface PermissionState {
backMenuList: Menu[];
// 菜单列表
frontMenuList: Menu[];
changeMenu: number;
}
export const usePermissionStore = defineStore({
@ -61,8 +63,12 @@ export const usePermissionStore = defineStore({
// menu List
// 菜单列表
frontMenuList: [],
changeMenu: dayjs().valueOf(),
}),
getters: {
getChangeMenu(state): number {
return state.changeMenu;
},
getPermCodeList(state): string[] | number[] {
return state.permCodeList;
},
@ -89,6 +95,10 @@ export const usePermissionStore = defineStore({
list?.length > 0 && this.setLastBuildMenuTime();
},
setChangeMenu() {
this.changeMenu = dayjs().valueOf();
},
setFrontMenuList(list: Menu[]) {
this.frontMenuList = list;
},
@ -122,6 +132,19 @@ export const usePermissionStore = defineStore({
const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
const normalizeMenu = (data) => {
let path = '';
if (data.item.url.indexOf('@') > 0) {
path = data.item.url.replace('@', '/');
} else {
path =
data.item.url ||
'/formCallPage?id=' +
data.item.id +
'&name=' +
data.item.name +
'&code=' +
data.item.code;
}
const newPath = {
orderNo: data.item.sortNo,
icon: data.item.iconName,
@ -134,14 +157,7 @@ export const usePermissionStore = defineStore({
},
name: data.item.name,
hideMenu: data.item.status == 1 ? false : true,
path:
data.item.url ||
'/formCallPage?id=' +
data.item.id +
'&name=' +
data.item.name +
'&code=' +
data.item.code,
path: path,
id: data.item.id || '',
children: [],
};
@ -154,65 +170,135 @@ export const usePermissionStore = defineStore({
};
// 注册路由
const registeredRoute = (data) => {
const modules = import.meta.glob('../../views/demo/**/**/index.vue');
if (data.children.length == 0 && data.item.parentId == 0 && data.item.status == 1) {
const modules = import.meta.glob('../../views/**/**/**/index.vue');
if (data.item.url.split('/')[1] == 'map') {
// 大屏的情况下不继承layout
router.addRoute('Root', {
path: data.item.url,
name: data.item.code,
meta: {
title: data.item.name,
icon: data.item.iconName,
hideChildrenInMenu: true,
elements: data.item.elements,
},
component: LAYOUT,
children: [
{
path: data.item.url,
name: data.item.url.replaceAll('/', ''),
component: modules['../../views' + data.item.url + '/index.vue'],
});
} else {
// 正常菜单
if (data.children.length == 0 && data.item.parentId == 0 && data.item.status == 1) {
// 没有子菜单
if (data.item.url.indexOf('@') > 0) {
//给带参数的路由先注册主路由
const path = data.item.url.substring(0, data.item.url.indexOf('@'));
router.addRoute('Root', {
path: path,
name: data.item.code,
meta: {
title: data.item.name,
icon: data.item.iconName,
hideChildrenInMenu: true,
elements: data.item.elements,
},
component: modules['../../views/demo' + data.item.url + '/index.vue'],
},
],
});
} else {
if (data.item.status == 0) {
return;
}
router.addRoute('Root', {
path: data.item.url,
name: data.item.code,
meta: {
title: data.item.name,
icon: data.item.iconName,
elements: data.item.elements,
},
// component: data.item.parentId == 0 ? LAYOUT : () => import('../../views/demo' + data.item.url + '/index.vue'),
component:
data.item.parentId == 0
? LAYOUT
: modules['../../views/demo' + data.item.url + '/index.vue'],
});
if (data.children && data.children.length > 0) {
data.children.forEach((element) => {
if (element.item.code && element.item.status == 1) {
router.addRoute(element.item.code, {
path: element.item.url,
name: element.item.url.replaceAll('/', ''),
meta: {
title: element.item.name,
icon: element.item.iconName,
elements: element.item.elements,
component: LAYOUT,
children: [
{
path: path + '/:id',
name: data.item.url.replaceAll('/', ''),
meta: {
title: data.item.name,
icon: data.item.iconName,
elements: data.item.elements,
},
component: modules['../../views/demo' + path + '/index.vue'],
},
// component: () => import('../../views/demo' + element.item.url + '/index.vue')
component: modules['../../views/demo' + element.item.url + '/index.vue'],
});
}
],
});
} else {
router.addRoute('Root', {
path: data.item.url,
name: data.item.code,
meta: {
title: data.item.name,
icon: data.item.iconName,
hideChildrenInMenu: true,
elements: data.item.elements,
},
component: LAYOUT,
children: [
{
path: data.item.url,
name: data.item.url.replaceAll('/', ''),
meta: {
title: data.item.name,
icon: data.item.iconName,
elements: data.item.elements,
},
component: modules['../../views/demo' + data.item.url + '/index.vue'],
},
],
});
}
} else {
// 有子菜单
if (data.item.status == 0) {
return;
}
router.addRoute('Root', {
path: data.item.url,
name: data.item.code,
meta: {
title: data.item.name,
icon: data.item.iconName,
elements: data.item.elements,
},
component:
data.item.parentId == 0
? LAYOUT
: modules['../../views/demo' + data.item.url + '/index.vue'],
});
if (data.children && data.children.length > 0) {
data.children.forEach((element) => {
// 菜单里配置带参数,但没有单独的主路由,先注册主路由
if (element.item.status == 1 && element.item.url.indexOf('@') > 0) {
const path = element.item.url.substring(0, element.item.url.indexOf('@'));
router.addRoute('Root', {
path: path,
name: element.item.code,
meta: {
title: element.item.name,
icon: element.item.iconName,
hideChildrenInMenu: true,
elements: element.item.elements,
},
component: LAYOUT,
children: [
{
path: path + '/:id',
name: element.item.url.replaceAll('/', ''),
meta: {
title: element.item.name,
icon: element.item.iconName,
elements: element.item.elements,
},
component: modules['../../views/demo' + path + '/index.vue'],
},
],
});
} else if (element.item.code && element.item.status == 1) {
router.addRoute(element.item.code, {
path: element.item.url,
name: element.item.url.replaceAll('/', ''),
meta: {
title: element.item.name,
icon: element.item.iconName,
elements: element.item.elements,
},
// component: () => import('../../views/demo' + element.item.url + '/index.vue')
component: modules['../../views/demo' + element.item.url + '/index.vue'],
});
}
});
}
}
}
// console.log(router.getRoutes())

View File

@ -50,6 +50,9 @@ const transform: AxiosTransform = {
// return '[HTTP] Request has no return value';
throw new Error(t('sys.api.apiRequestFailed'));
}
if (!data.code && !data.result) {
return data;
}
// 这里 coderesultmessage为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
const { code, result, message } = data;
// 这里逻辑可以根据项目进行修改

View File

@ -101,7 +101,6 @@
label="选项"
v-if="
[
'Select',
'CheckboxGroup',
'RadioGroup',
'TreeSelect',
@ -114,7 +113,35 @@
>
<FormOptions />
</FormItem>
<FormItem
label="选项"
v-if="['Select'].includes(formConfig.currentItem.component)">
<div class="select-radio">
<a-radio-group v-model:value="formConfig.currentItem.dataType" button-style="solid">
<a-radio-button value="1">静态数据</a-radio-button>
<a-radio-button value="2">数据字典</a-radio-button>
</a-radio-group>
</div>
<template v-if="formConfig.currentItem.dataType === '1'">
<FormOptions />
</template>
<template v-else-if="formConfig.currentItem.dataType === '2'">
<a-select
v-model:value="formConfig.currentItem.dataCode"
show-search
style="width: 100%"
placeholder="请选择字典类型"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
:options="selectDictionaryData"
@search="handleSearch"
@change="handleChange"
@focus="handleSelectFocus"
></a-select>
</template>
</FormItem>
<FormItem
label="栅格"
v-if="
@ -187,6 +214,8 @@
import { getOutKeyList } from '@/api/formdesign/index';
import { BasicModal, useModal } from '@/components/Modal';
import { formItemPropsScript } from '../../VFormDesign/config/formItemPropsScript';
import { getDictionaryType, getDictionary } from '@/api/sys/categories.ts'
import { useOnlineFormDesignStore } from '@/store/modules/onlineFormDesign'
export default defineComponent({
name: 'ComponentProps',
@ -209,10 +238,15 @@
useModal,
},
setup() {
const onlineFormDesignStore = useOnlineFormDesignStore()
let fieldTableValue = ref();
let FieldTableOptions = ref();
let ChlidTableOptions = ref(); //
let receivedData = ref();
const selectRadio = ref(0)
const selectDictionary = ref()
const selectDictionaryData = ref<any[]>([])
const timeout = ref()
const handleNextStepsData = inject('handleNextStepsData');
let currentIndex = ref(); //
watch(
@ -238,7 +272,52 @@
},
{ deep: true, immediate: true },
);
function getSelectData(value: string, callback: any) {
if (timeout.value) {
clearTimeout(timeout.value);
timeout.value = null;
}
function fake() {
getDictionaryType()
.then(res => {
let data: any[] = [];
res.forEach(item => {
data.push({
value: item.itemCode,
label: item.itemName,
})
})
if(value !== ""){
data = data.filter(item => {
return item.label.indexOf(value) > -1
})
}
callback(data)
});
}
timeout.value = setTimeout(fake, 300);
}
const handleSearch = (val: string) => {
getSelectData(val, (d: any[]) => (selectDictionaryData.value = d));
};
const handleSelectFocus = () => {
getSelectData("", (d: any[]) => (selectDictionaryData.value = d));
}
const handleChange = (val: string) => {
let params = {code: val}
getDictionary(params).then(res => {
let data: any[] = []
res.forEach(item => {
data.push({
value: item.itemValue,
label: item.itemName,
})
})
onlineFormDesignStore.setSelectOptions(formConfig.value.currentItem.field, data)
}).catch(error => {
console.log(error)
})
};
let FieldNamesOptions = ref<SelectProps['options']>([]);
const fetch = () => {
@ -287,7 +366,6 @@
formConfig.value.currentItem.componentProps =
formConfig.value.currentItem.componentProps || {};
}
watch(
() => formConfig.value.currentItem?.field,
(_newValue, oldValue) => {
@ -335,7 +413,11 @@
});
baseComponentCommonAttrs.forEach((item) => {
if (formType_design.value != 2 || !['dataTable', 'fieldName'].includes(item.name)) {
if (
(formType_design.value != 2 &&
!['Divider', 'Button'].includes(formConfig.value.currentItem?.component)) ||
!['dataTable', 'fieldName'].includes(item.name)
) {
item.category = 'input';
if (item.includes) {
if (item.includes.includes(formConfig.value.currentItem!.component)) {
@ -506,12 +588,23 @@
closeModal,
handleButtonClick,
handleSubmit,
selectRadio,
selectDictionary,
selectDictionaryData,
handleSearch,
handleChange,
handleSelectFocus,
};
},
});
</script>
<style lang="less" scoped>
.select-radio{
display: flex;
justify-content: center;
margin-bottom: 15px;
}
.alertModal {
display: flex;
background-color: @border-color-base;

View File

@ -178,7 +178,7 @@
watch(
() => formConfig.value,
() => {
console.log("formConfig",formConfig.value);
console.log('formConfig', formConfig.value);
if (formConfig.value.currentItem) {
formConfig.value.currentItem.itemProps = formConfig.value.currentItem.itemProps || {};
formConfig.value.currentItem.itemProps.labelCol =
@ -187,11 +187,13 @@
formConfig.value.currentItem.itemProps.wrapperCol || {};
if (formConfig.value.currentItem.component === 'MapGeom') {
//
formConfig.value.currentItem.mapSetData = formConfig.value.currentItem.mapSetData ? formConfig.value.currentItem.mapSetData : {
chooseLayer: '',
isAllowEditPolygon: false,
isEnablePostionJump: false,
};
formConfig.value.currentItem.mapSetData = formConfig.value.currentItem.mapSetData
? formConfig.value.currentItem.mapSetData
: {
chooseLayer: '',
isAllowEditPolygon: false,
isEnablePostionJump: false,
};
//
if (shpLayerSourceOptions.value.length == 0) {
getShpLayerSourceOptions();

View File

@ -14,6 +14,40 @@
添加栅格
</a>
</div>
<div v-if="['TreeSelect', 'Cascader'].includes(formConfig.currentItem!.component)">
<BasicTree
ref="treeDataRef"
:treeData="treeDataAndOptions"
:fieldNames="{ key: 'value', title: 'label' }"
:clickRowToExpand="false"
:defaultExpandAll="true"
>
<template #title="{ label, value }">
<div class="options-box">
<Input
:value="label"
@blur="updateLabelOrValue('label', label, value, $event.target.value)"
/>
<Input
:value="value"
@blur="updateLabelOrValue('value', label, value, $event.target.value)"
class="options-value"
/>
<!-- {{ key }}-{{ label }}-{{ value }} -->
<a class="options-delete" @click="addTreeNode(value)">
<Icon icon="ant-design:folder-add-outlined" />
</a>
<a class="options-delete" @click="deleteTreeNode(value)">
<Icon icon="ant-design:delete-outlined" />
</a>
</div>
</template>
</BasicTree>
<a @click="addTreeNode(null)">
<Icon icon="ant-design:file-add-outlined" />
添加父级选项
</a>
</div>
<div v-else>
<div v-for="(item, index) of formConfig.currentItem!.componentProps![key]" :key="index">
<div class="options-box">
@ -33,22 +67,105 @@
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue';
import { defineComponent, reactive, toRefs, ref, unref, watch } from 'vue';
import { useFormDesignState } from '../../../hooks/useFormDesignState';
import { BasicTree, TreeItem, TreeActionType } from '@/components/Tree';
import { remove } from '../../../utils';
import message from '../../../utils/message';
import { Input } from 'ant-design-vue';
import Icon from '@/components/Icon/Icon.vue';
import { v4 as uuidv4 } from 'uuid';
export default defineComponent({
name: 'FormOptions',
components: { Input, Icon },
components: { Input, Icon, BasicTree },
// props: {},
setup() {
const state = reactive({});
const { formConfig } = useFormDesignState();
const key = formConfig.value.currentItem?.component === 'TreeSelect' ? 'treeData' : 'options';
let key: string = '';
// ref
const treeDataAndOptions = ref<TreeItem[]>([]);
//
let len: number = 1;
watch(
() => formConfig.value.currentItem?.component,
() => {
if (formConfig.value.currentItem?.component == 'Select') {
treeDataAndOptions.value = [];
key = 'options';
} else if (formConfig.value.currentItem?.component == 'TreeSelect') {
treeDataAndOptions.value = formConfig.value.currentItem?.componentProps?.treeData;
key = 'treeData';
} else if (formConfig.value.currentItem?.component == 'Cascader') {
treeDataAndOptions.value = formConfig.value.currentItem?.componentProps?.options;
key = 'options';
} else if (formConfig.value.currentItem?.component == 'Transfer') {
treeDataAndOptions.value = [];
key = 'dataSource';
}
},
{ deep: true, immediate: true },
);
//
const treeDataRef = ref<Nullable<TreeActionType>>(null);
function getTree(): any {
return unref(treeDataRef);
}
//
function addTreeNode(value) {
len = 1;
getLength(treeDataAndOptions.value);
getTree().insertNodeByKey({
parentKey: value,
node: {
label: `选项${len}`,
value: len,
},
//
push: 'push',
});
refresh();
}
//
function deleteTreeNode(value) {
getTree().deleteNodeByKey(value);
refresh();
}
//
function getLength(treeDataOrOptions) {
treeDataOrOptions.forEach((to) => {
if (to.value) {
len++;
}
if (to.children) {
getLength(to.children);
}
});
}
// labelvalue
function updateLabelOrValue(type, label, value, newLabelOrValue) {
if (type == 'label') {
getTree().updateNodeByKey(value, { label: newLabelOrValue, value: value });
}
if (type == 'value') {
getTree().updateNodeByKey(value, { label: label, value: newLabelOrValue });
}
refresh();
// console.log(getTree().getTreeData());
}
//
function refresh() {
getTree().expandAll(true);
treeDataAndOptions.value = getTree().getTreeData();
formConfig.value.currentItem.componentProps[key] = treeDataAndOptions.value;
}
const addOptions = () => {
if (!formConfig.value.currentItem?.componentProps?.[key])
formConfig.value.currentItem!.componentProps![key] = [];
@ -60,7 +177,7 @@
value: '' + len,
children: [],
});
}else if (['CardGroup'].includes(formConfig.value.currentItem!.component)) {
} else if (['CardGroup'].includes(formConfig.value.currentItem!.component)) {
formConfig.value.currentItem!.componentProps![key].push({
label: `卡片${len}`,
value: '' + len,
@ -97,6 +214,11 @@
key,
deleteGridOptions,
addGridOptions,
treeDataRef,
treeDataAndOptions,
addTreeNode,
deleteTreeNode,
updateLabelOrValue,
};
},
});

View File

@ -1,5 +1,5 @@
import { IAnyObject } from '../../../typings/base-type';
import { baseComponents, customComponents } from '../../../core/formItemConfig';
import { baseComponents, commonComponents } from '../../../core/formItemConfig';
import { Input, Select, RadioGroup, Slider } from 'ant-design-vue';
import { Component } from 'vue';
@ -185,7 +185,7 @@ export const baseFormItemProps: IBaseFormAttrs[] = [
label: '控件-FormItem',
component: Select,
componentProps: {
options: baseComponents.concat(customComponents[1]).map((item) => ({
options: commonComponents.concat(baseComponents).map((item) => ({
value: item.component,
label: item.label,
key: item.component + '===' + item.label,

View File

@ -18,6 +18,14 @@
breakpoint="md"
>
<div class="collapseItem-box">
<CollapseContainer title="常用控件" isTitleBold="true">
<CollapseItem
:list="commonComponents"
:handleListPush="handleListPushDrag"
@add-attrs="handleAddAttrs"
@handle-list-push="handleListPush"
/>
</CollapseContainer>
<CollapseContainer title="基础控件" isTitleBold="true">
<CollapseItem
:list="baseComponents"
@ -114,7 +122,12 @@
import { IVFormComponent, IFormConfig, PropsTabKey } from '../../typings/v-form-component';
import { formItemsForEach, generateKey, removeAttrs } from '../../utils';
import { cloneDeep } from 'lodash-es';
import { baseComponents, customComponents, layoutComponents } from '../../core/formItemConfig';
import {
commonComponents,
baseComponents,
customComponents,
layoutComponents,
} from '../../core/formItemConfig';
import { useRefHistory, UseRefHistoryReturn } from '@vueuse/core';
import { globalConfigState } from './config/formItemPropsConfig';
import { IFormDesignMethods, IPropsPanel, IToolbarMethods } from '../../typings/form-type';

View File

@ -66,7 +66,17 @@
</template>
</a-input>
</div>
<div v-else-if="schema.component == 'Select'">
<a-select
:placeholder="schema.componentProps.placeholder"
:allowClear="schema.componentProps.allowClear"
:mode="schema.componentProps.mode"
:showSearch="schema.componentProps.showSearch"
:disabled="schema.componentProps.disabled"
:options="selectUseOptions? schema.componentProps.options: showSelectDictionaryList"
:defaultValue="schema.defaultValue">
</a-select>
</div>
<component
v-else
class="v-form-item-wrapper"
@ -95,6 +105,7 @@
import { useFormModelState } from '../../hooks/useFormDesignState';
import { UserOutlined } from '@ant-design/icons-vue'
import dayjs from 'dayjs';
import { useOnlineFormDesignStore } from '@/store/modules/onlineFormDesign'
export default defineComponent({
name: 'VFormItem',
@ -127,11 +138,20 @@
loginUserName: localStorage.getItem('fireUserLoginName'),
nowTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
});
const onlineFormDesignStore = useOnlineFormDesignStore()
const { formModel: formData1, setFormModel } = useFormModelState();
const colPropsComputed = computed(() => {
const { colProps = {} } = props.schema;
return colProps;
});
const selectUseOptions = computed(() => {
if(props.schema.dataType === undefined || props.schema.dataType === '1'){
return true
}else{
return false
}
})
const showSelectDictionaryList = computed(() => onlineFormDesignStore.getSelectOption(props.schema.field))
const formItemProps = computed(() => {
const { formConfig } = unref(props);
let { field, required, rules, labelCol, wrapperCol } = unref(props.schema);
@ -246,6 +266,8 @@
cmpProps,
handleChange,
colPropsComputed,
selectUseOptions,
showSelectDictionaryList,
};
},
});

View File

@ -82,35 +82,6 @@ export function setFormDesignComponents(config: IVFormComponent | IVFormComponen
//外部设置的自定义控件
export const customComponents: IVFormComponent[] = [
{
component: 'Tabs',
label: '选项卡',
icon: 'ant-design:database-outlined',
colProps: { span: 24 },
field: 'Tabs',
componentProps: {
options: [
{
label: '选项卡1',
value: '1',
children: [],
},
{
label: '选项卡2',
value: '2',
children: [],
},
],
},
},
{
component: 'InputGuid',
label: 'GUID主键',
icon: 'bi:braces-asterisk',
field: '',
colProps: { span: 24 },
componentProps: {},
},
{
component: 'TreeSelect',
label: '职级选择',
@ -163,85 +134,20 @@ export const customComponents: IVFormComponent[] = [
colProps: { span: 24 },
componentProps: {},
},
{
field: '',
component: 'Grid',
label: '设计子表',
icon: 'bi:list-ul',
type: 'subTable',
componentProps: {},
columns: [
{
span: 24,
children: [],
},
],
colProps: { span: 24 },
options: {
gutter: 0,
},
},
];
// 左侧控件列表与初始化的控件属性
// props.slotName,会在formitem级别生成一个slot,并绑定当前record值
// 属性props类型为对象不能为undefined或是null。
export const baseComponents: IVFormComponent[] = [
export const commonComponents: IVFormComponent[] = [
{
component: 'InputCountDown',
label: '倒计时输入',
icon: 'ant-design:hourglass-outlined',
colProps: { span: 24 },
component: 'InputGuid',
label: 'GUID主键',
icon: 'bi:braces-asterisk',
field: '',
colProps: { span: 24 },
componentProps: {},
},
{
component: 'IconPicker',
label: '图标选择器',
icon: 'bi:grid',
colProps: { span: 24 },
field: '',
componentProps: {},
},
{
component: 'StrengthMeter',
label: '密码强度',
icon: 'wpf:password1',
colProps: { span: 24 },
field: '',
componentProps: {},
},
{
component: 'AutoComplete',
label: '自动完成',
icon: 'bi:check2-circle',
colProps: { span: 24 },
field: '',
componentProps: {
placeholder: '请输入正则表达式',
options: [
{
value: '/^(?:(?:\\+|00)86)?1[3-9]\\d{9}$/',
label: '手机号码',
},
{
value: '/^((ht|f)tps?:\\/\\/)?[\\w-]+(\\.[\\w-]+)+:\\d{1,5}\\/?$/',
label: '网址带端口号',
},
],
},
},
{
component: 'Divider',
label: '分割线',
icon: 'radix-icons:divider-horizontal',
colProps: { span: 24 },
field: '',
componentProps: {
orientation: 'center',
dashed: true,
},
},
{
component: 'Input',
label: '输入框',
@ -301,6 +207,7 @@ export const baseComponents: IVFormComponent[] = [
icon: 'bi:check-square',
colProps: { span: 24 },
field: '',
componentProps: {},
},
{
component: 'CheckboxGroup',
@ -357,22 +264,6 @@ export const baseComponents: IVFormComponent[] = [
colProps: { span: 24 },
componentProps: {},
},
{
component: 'Slider',
label: '滑动输入条',
icon: 'vaadin:slider',
field: '',
colProps: { span: 24 },
componentProps: {},
},
{
component: 'Rate',
label: '评分',
icon: 'ic:outline-star-rate',
field: '',
colProps: { span: 24 },
componentProps: {},
},
{
component: 'Switch',
label: '开关',
@ -401,6 +292,8 @@ export const baseComponents: IVFormComponent[] = [
label: '下拉选择',
icon: 'gg:select',
field: '',
dataType:"1",
dataCode: '',
colProps: { span: 24 },
componentProps: {
options: [
@ -428,8 +321,8 @@ export const baseComponents: IVFormComponent[] = [
value: '1',
children: [
{
label: '选项',
value: '1-1',
label: '选项3',
value: '3',
},
],
},
@ -440,16 +333,6 @@ export const baseComponents: IVFormComponent[] = [
],
},
},
// {
// component: 'Upload',
// label: '上传',
// icon: 'ant-design:upload-outlined',
// field: '',
// colProps: { span: 24 },
// componentProps: {
// api: () => 1,
// },
// },
{
component: 'Cascader',
label: '级联选择',
@ -463,8 +346,8 @@ export const baseComponents: IVFormComponent[] = [
value: '1',
children: [
{
label: '选项',
value: '1-1',
label: '选项3',
value: '3',
},
],
},
@ -475,6 +358,112 @@ export const baseComponents: IVFormComponent[] = [
],
},
},
{
component: 'Transfer',
label: '穿梭框',
icon: 'bx:bx-transfer-alt',
field: '',
colProps: { span: 24 },
componentProps: {
render: (item) => item.title,
dataSource: [
{
key: 'key-1',
title: '标题1',
description: '描述',
disabled: false,
chosen: true,
},
{
key: 'key-2',
title: 'title2',
description: 'description2',
disabled: true,
},
{
key: 'key-3',
title: '标题3',
description: '描述3',
disabled: false,
chosen: true,
},
],
},
},
{
component: 'Divider',
label: '分割线',
icon: 'radix-icons:divider-horizontal',
colProps: { span: 24 },
field: '',
componentProps: {
orientation: 'center',
dashed: true,
},
},
];
export const baseComponents: IVFormComponent[] = [
{
component: 'InputCountDown',
label: '倒计时输入',
icon: 'ant-design:hourglass-outlined',
colProps: { span: 24 },
field: '',
componentProps: {},
},
{
component: 'IconPicker',
label: '图标选择器',
icon: 'bi:grid',
colProps: { span: 24 },
field: '',
componentProps: {},
},
{
component: 'StrengthMeter',
label: '密码强度',
icon: 'wpf:password1',
colProps: { span: 24 },
field: '',
componentProps: {},
},
{
component: 'AutoComplete',
label: '自动完成',
icon: 'bi:check2-circle',
colProps: { span: 24 },
field: '',
componentProps: {
placeholder: '请输入正则表达式',
options: [
{
value: '/^(?:(?:\\+|00)86)?1[3-9]\\d{9}$/',
label: '手机号码',
},
{
value: '/^((ht|f)tps?:\\/\\/)?[\\w-]+(\\.[\\w-]+)+:\\d{1,5}\\/?$/',
label: '网址带端口号',
},
],
},
},
{
component: 'Slider',
label: '滑动输入条',
icon: 'vaadin:slider',
field: '',
colProps: { span: 24 },
componentProps: {},
},
{
component: 'Rate',
label: '评分',
icon: 'ic:outline-star-rate',
field: '',
colProps: { span: 24 },
componentProps: {},
},
// {
// component: 'ColorPicker',
// label: '颜色选择器',
@ -486,16 +475,6 @@ export const baseComponents: IVFormComponent[] = [
// value: '',
// },
// },
{
component: 'slot',
label: '插槽',
icon: 'bi:inboxes',
field: '',
colProps: { span: 24 },
componentProps: {
slotName: 'slotName',
},
},
{
component: 'CreateUser',
type: 'createuser',
@ -579,6 +558,16 @@ export const baseComponents: IVFormComponent[] = [
server: 'http://192.168.10.102:9023',
},
},
{
component: 'slot',
label: '插槽',
icon: 'bi:inboxes',
field: '',
colProps: { span: 24 },
componentProps: {
slotName: 'slotName',
},
},
{
component: 'Location',
label: '获取位置',
@ -594,48 +583,39 @@ export const baseComponents: IVFormComponent[] = [
},
];
// https://next.antdv.com/components/transfer-cn
const transferControl = {
component: 'Transfer',
label: '穿梭框',
icon: 'bx:bx-transfer-alt',
field: '',
colProps: { span: 24 },
componentProps: {
render: (item) => item.title,
dataSource: [
{
key: 'key-1',
title: '标题1',
description: '描述',
disabled: false,
chosen: true,
},
{
key: 'key-2',
title: 'title2',
description: 'description2',
disabled: true,
},
{
key: 'key-3',
title: '标题3',
description: '描述3',
disabled: false,
chosen: true,
},
],
},
};
// // https://next.antdv.com/components/transfer-cn
// const transferControl = ;
baseComponents.push(transferControl);
// baseComponents.push(transferControl);
export const layoutComponents: IVFormComponent[] = [
{
component: 'Tabs',
label: '选项卡',
icon: 'ant-design:database-outlined',
colProps: { span: 24 },
field: 'Tabs',
componentProps: {
options: [
{
label: '选项卡1',
value: '1',
children: [],
},
{
label: '选项卡2',
value: '2',
children: [],
},
],
},
},
{
field: '',
component: 'Grid',
label: '栅格布局',
icon: 'bi:border-all',
label: '设计子表',
icon: 'bi:list-ul',
type: 'subTable',
componentProps: {},
columns: [
{
@ -688,4 +668,21 @@ export const layoutComponents: IVFormComponent[] = [
],
},
},
{
field: '',
component: 'Grid',
label: '栅格布局',
icon: 'bi:border-all',
componentProps: {},
columns: [
{
span: 24,
children: [],
},
],
colProps: { span: 24 },
options: {
gutter: 0,
},
},
];

View File

@ -14,6 +14,8 @@ export interface IState {
// 语言
locale: any;
// 公用组件
commonComponents: IVFormComponent[];
// 公用组件
baseComponents: IVFormComponent[];
// 自定义组件
customComponents: IVFormComponent[];

View File

@ -109,6 +109,10 @@ export interface IVFormComponent {
mapSetData?: MapComponent;
// 判断子表的字段
type?: string;
// 下拉选择中字段选择类型
dataType?: string;
// 下拉选择中选择的字典类型
dataCode? : string;
}
declare type namesType = string | string[];

View File

@ -2,7 +2,7 @@
<a-row v-if="isTime && show" style="width:100%;margin-bottom:10px;">
<a-col flex="100px" style="display: flex;align-items: center;justify-content: right;padding-right: 7px;">{{ props.data.label }}</a-col>
<a-col flex="auto">
<a-input v-model:value="nowTime" readOnly>
<a-input v-model:value="nowTime" readOnly :disabled="disabled">
<template #suffix>
<FieldTimeOutlined />
</template>
@ -12,7 +12,7 @@
<a-row v-else-if="!isTime && show" style="width:100%;margin-bottom:10px;" >
<a-col flex="100px" style="display: flex;align-items: center;justify-content: right;padding-right: 7px;">{{ props.data.label }}</a-col>
<a-col flex="auto">
<a-input v-model:value="userName" readOnly>
<a-input v-model:value="userName" readOnly :disabled="disabled">
<template #suffix>
<UserOutlined />
</template>
@ -28,7 +28,8 @@ import { ref, defineProps, onMounted } from 'vue'
import { UserOutlined, FieldTimeOutlined } from '@ant-design/icons-vue';
import dayjs from 'dayjs';
const props = defineProps(['data', 'createOrModifyData', 'isUpdate', 'isDetail'])
const show = props.data.display
const show = props.data.display && (Object.keys(props.data).includes('ifShow')? props.data.ifShow: true)
const disabled = Object.keys(props.data.componentProps).includes('disabled')? props.data.componentProps.disabled: false
const isTime = ['createtime', 'modifytime'].includes(props.data.type)
const nowTime = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
const userName = ref(localStorage.getItem('fireUserLoginName'))

View File

@ -19,109 +19,111 @@
width="80%"
:closeFunc="closeFunc"
> -->
<template v-if="tabsColumns.length > 1">
<a-tabs style="width: 100%" @change="tabsChange">
<a-tab-pane v-for="(colItem, index) in tabsColumns" :tab="colItem.label" :key="index">
<div class="map-content">
<template v-if="tabsColumns.length > 1">
<a-tabs style="width: 100%" @change="tabsChange">
<a-tab-pane v-for="(colItem, index) in tabsColumns" :tab="colItem.label" :key="index">
<BasicForm
ref="myDataBaseFormRef"
@register="registerForm"
@click="codeClickFunction('beforeSetData', beforeSetData)"
@change="codeClickFunction('changeDataEvent', changeDataEvent)"
>
<template #CardGroup>
<CardGourp
v-if="cardGroupData.length > 0 && cardGroupData[index]"
:data="cardGroupData[index]"
:formData="cardGourpFormData"
:parentValue="cardGroupData[index].field"
:callModal="true"
/>
</template>
</BasicForm>
</a-tab-pane>
</a-tabs>
</template>
<BasicForm
ref="myDataBaseFormRef"
@register="registerForm"
@click="codeClickFunction('beforeSetData', beforeSetData)"
@change="codeClickFunction('changeDataEvent', changeDataEvent)"
>
<template #CardGroup>
<CardGourp
v-if="cardGroupData.length > 0 && cardGroupData[index]"
:data="cardGroupData[index]"
:formData="cardGourpFormData"
:parentValue="cardGroupData[index].field"
:callModal="true"
/>
</template>
</BasicForm>
</a-tab-pane>
</a-tabs>
</template>
<BasicForm
ref="myDataBaseFormRef"
@register="registerForm"
v-if="formModalVisible && tabsColumns.length < 1"
@click="codeClickFunction('beforeSetData', beforeSetData)"
@change="codeClickFunction('changeDataEvent', changeDataEvent)"
/>
<template v-for="(item, index) in cardLayout" :key="index">
<a-row style="width: 100%">
<a-col :span="item?.colProps?.span || 24" style="padding: 10px">
<a-card
:title="item.label"
:class="
item.shadow === 'always' ? 'card-always' : item.shadow === 'hover' ? 'card-hover' : ''
"
>
<template v-for="(childItem, childIndex) in item.columns[0].children" :key="childIndex">
<a-row style="width: 100%; margin-bottom: 10px">
<a-col :span="childItem?.colProps?.span || 24">
<CallModalFormItem :data="childItem" :dataKey="item.field" :values="cardValues" />
</a-col>
</a-row>
</template>
</a-card>
</a-col>
</a-row>
</template>
<template v-if="tabsColumns.length < 1">
<CardGourp
v-if="cardGroupData.length > 0"
:data="cardGroupData[0]"
:formData="cardGourpFormData"
:parentValue="cardGroupData[0].field"
:callModal="true"
/>
</template>
<template v-for="(item, index) in buttonLayout" :key="index">
<a-row style="width: 100%">
<a-col :span="item?.colProps?.span || 24" style="padding: 10px">
<a-button
:type="item.componentProps.type"
:shape="item.componentProps.shape"
:size="item.componentProps.size"
@click="codeClickFunction('codeClick', item.componentProps.clickCode)"
>
{{ item.label }}
</a-button>
</a-col>
</a-row>
</template>
<a-table
class="sub-table"
:columns="subTableColumns"
:data-source="subTableList"
:pagination="false"
v-if="subTableId"
:scroll="scrollValue"
>
<template #headerCell="{ column, record }">
<template v-if="column.key === 'setting'">
<PlusOutlined class="icon-button" @click="addListItem" v-if="!isDetail" />
</template>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'setting'">
<DeleteOutlined
class="icon-button"
@click="delListItem(column, record)"
v-if="!isDetail"
ref="myDataBaseFormRef"
@register="registerForm"
v-if="formModalVisible && tabsColumns.length < 1"
@click="codeClickFunction('beforeSetData', beforeSetData)"
@change="codeClickFunction('changeDataEvent', changeDataEvent)"
/>
</template>
<template v-else>
<FormItem :data="column" :record="record" />
</template>
</template>
</a-table>
<!-- todo 创建/修改 /时间 -->
<div class="footer-button" v-if="!isDetail">
<a-button style="margin-right: 20px" @click="handlerCloseForm"></a-button>
<a-button type="primary" @click="ModalSureClick"></a-button>
</div>
<template v-for="(item, index) in cardLayout" :key="index">
<a-row style="width: 100%">
<a-col :span="item?.colProps?.span || 24" style="padding: 10px">
<a-card
:title="item.label"
:class="
item.shadow === 'always' ? 'card-always' : item.shadow === 'hover' ? 'card-hover' : ''
"
>
<template v-for="(childItem, childIndex) in item.columns[0].children" :key="childIndex">
<a-row style="width: 100%; margin-bottom: 10px">
<a-col :span="childItem?.colProps?.span || 24">
<CallModalFormItem :data="childItem" :dataKey="item.field" :values="cardValues" />
</a-col>
</a-row>
</template>
</a-card>
</a-col>
</a-row>
</template>
<template v-if="tabsColumns.length < 1">
<CardGourp
v-if="cardGroupData.length > 0"
:data="cardGroupData[0]"
:formData="cardGourpFormData"
:parentValue="cardGroupData[0].field"
:callModal="true"
/>
</template>
<template v-for="(item, index) in buttonLayout" :key="index">
<a-row style="width: 100%">
<a-col :span="item?.colProps?.span || 24" style="padding: 10px">
<a-button
:type="item.componentProps.type"
:shape="item.componentProps.shape"
:size="item.componentProps.size"
@click="codeClickFunction('codeClick', item.componentProps.clickCode)"
>
{{ item.label }}
</a-button>
</a-col>
</a-row>
</template>
<a-table
class="sub-table"
:columns="subTableColumns"
:data-source="subTableList"
:pagination="false"
v-if="subTableId"
:scroll="scrollValue"
>
<template #headerCell="{ column, record }">
<template v-if="column.key === 'setting'">
<PlusOutlined class="icon-button" @click="addListItem" v-if="!isDetail" />
</template>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'setting'">
<DeleteOutlined
class="icon-button"
@click="delListItem(column, record)"
v-if="!isDetail"
/>
</template>
<template v-else>
<FormItem :data="column" :record="record" />
</template>
</template>
</a-table>
<!-- todo 创建/修改 /时间 -->
<div class="footer-button" v-if="!isDetail">
<a-button style="margin-right: 20px" @click="handlerCloseForm"></a-button>
<a-button type="primary" @click="ModalSureClick"></a-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
@ -774,5 +776,11 @@
.map-form-close:hover{
color:#aaa;
}
.map-content{
width:100%;
height: calc( 100% - 60px);
overflow:auto;
}
</style>

View File

@ -93,6 +93,7 @@
getFormsPageData,
delFormsData,
getFormData,
exportForm,
} from '@/api/formrender/index';
import { getOutKeyList } from '@/api/formdesign/index';
import { getGeom } from '@/api/sys/layerManagement';
@ -113,12 +114,12 @@
const mapFormData = ref<Object>({});
const { createConfirm, createMessage } = useMessage();
const route = useRoute();
const btnArr: any = [
const btnArr: any = ref([
{ label: '新增', prop: 'Add', class: 'primary' },
{ label: '编辑', prop: 'Edit', class: 'success' },
{ label: '删除', prop: 'Delete', class: 'error' },
{ label: '详情', prop: 'Details', class: 'default' },
];
]);
const mapSetData = ref({
width: 100,
});
@ -149,6 +150,7 @@
const isUpdate = ref(false); //
const infoUseSubTableData = ref();
const infoUseMainTableData = ref({});
const exportParams: any = ref();
//
const layers = reactive();
const geometryForm = ref({});
@ -289,6 +291,7 @@
},
queryJson: JSON.stringify(querys),
};
exportParams.value = temp;
return temp;
},
afterFetch: () => {
@ -500,13 +503,13 @@
// mapSetData.value?.isAllowEditPolygon,
// );
// openModal(true, toProps);
previewOpen.value = true;
flowFormData.value = rows[0];
isUpdate.value = true;
// previewOpen.value = true;
// flowFormData.value = rows[0];
// isUpdate.value = true;
openModal(true, toProps);
} else {
openModal(true, toProps);
}
} else {
previewOpen.value = true;
flowFormData.value = rows[0];
@ -571,6 +574,29 @@
case 'Import':
break;
case 'Export':
let params = exportParams.value;
params.code = paramsCode;
console.log('params', params);
exportForm(params).then((res) => {
console.log('aaaa', res);
const content = res;
const blob = new Blob([content]);
const fileName = '数据导出' + getToday() + '.xlsx';
if ('download' in document.createElement('a')) {
// IE
const elink = document.createElement('a');
elink.download = fileName;
elink.style.display = 'none';
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // URL
document.body.removeChild(elink);
} else {
// IE10+
navigator.msSaveBlob(blob, fileName);
}
});
break;
default:
break;
@ -579,6 +605,25 @@
const chooseLayer = ref<string>('');
const geomfield = ref<string>('');
function getToday() {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var time = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
if (month >= 1 && month <= 9) {
month = '0' + month;
}
if (dates >= 0 && dates <= 9) {
dates = '0' + dates;
}
let datatime = year + '0' + month + '0' + dates + time + '0' + minutes + '0' + seconds;
return datatime;
}
function findValue(obj, targetKey) {
for (var key in obj) {
if (typeof obj[key] === 'object') {
@ -597,6 +642,7 @@
}
async function handlerShowGeomtrys(currentNode, rows) {
console.log('currentNode222', currentNode.value);
findValue(currentNode.value.schemas, 'component');
let info = currentNode.value.schemas?.find((item, index) => {
@ -672,6 +718,7 @@
let columnObj = JSON.parse(res.entity.scheme);
let formObj = JSON.parse(res.formScheme.scheme);
console.log('formObj', formObj);
console.log('columnObj', columnObj);
// card
if (formObj.formInfo.tabList && formObj.formInfo.tabList.length > 0) {
formObj.formInfo.tabList = cardNestStructure(formObj.formInfo.tabList);
@ -720,6 +767,7 @@
codeId.value = res.entity.id;
paramsId.value = res.formScheme.id;
btnList.value = columnObj.table.btns;
btnArr.value = columnObj.table.btns;
if (columnObj.table.columns) {
columnObj.table.columns.forEach((item) => {
callColumns.push({

View File

@ -61,7 +61,8 @@
// api
import { getMenuList } from '@/api/demo/system';
import { fun_GetPageList, fun_DeleteForm } from '@/api/demo/formModule';
import { usePermissionStore } from '@/store/modules/permission';
const permissionStore = usePermissionStore();
defineOptions({ name: 'FormModule' });
const searchInfo = reactive<Recordable>({});
const { createConfirm, createMessage } = useMessage();
@ -136,6 +137,8 @@
createMessage.warn('删除失败');
}
reload();
await permissionStore.buildRoutesAction()
permissionStore.setChangeMenu()
},
});
}
@ -173,9 +176,11 @@
}
// -
function submitReload() {
async function submitReload() {
clearSelectedRowKeys();
reload();
await permissionStore.buildRoutesAction()
permissionStore.setChangeMenu()
}
function onBtnClicked(domId) {

View File

@ -156,7 +156,7 @@
prop: 'Import',
icon: 'ant-design:upload-outlined',
isRowBtn: false,
class: 'primary',
class: 'success',
sort: 1,
},
{
@ -192,7 +192,7 @@
prop: 'Details',
icon: 'ant-design:align-center-outlined',
isRowBtn: true,
class: 'primary',
class: 'default',
sort: 5,
},
],

View File

@ -10,31 +10,30 @@
@ok="dataBaseClick"
>
<BasicTable @register="registerImportTable" />
</BasicModal>
<BasicModal
v-bind="$attrs"
@register="registerModal"
:canFullscreen="false"
:defaultFullscreen="false"
:maskClosable="false"
:width="800"
title="数据对象选择"
@ok="modalSuReClick"
>
<BasicTable @register="registerDataTable">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'stateSlot'">
<div>
<span class="tbBtnBox" @click="tbBtnClick(record)"></span>
</div>
</template>
<BasicModal
v-bind="$attrs"
@register="registerModal"
:canFullscreen="false"
:defaultFullscreen="false"
:maskClosable="false"
:width="800"
title="数据对象选择"
@ok="modalSuReClick"
>
<BasicTable @register="registerDataTable">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'stateSlot'">
<div>
<span class="tbBtnBox" @click="tbBtnClick(record)"></span>
</div>
</template>
</BasicTable>
<template #centerFooter>
<a-button type="success" @click="handleAddForm"> </a-button>
</template>
</BasicModal>
</BasicTable>
<template #centerFooter>
<a-button type="success" @click="handleAddForm"> </a-button>
</template>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
@ -103,6 +102,7 @@
api: getImportBaseTableList,
formConfig: {
labelWidth: 80,
schemas: searchFormSchema,
},
columns: importColumns,
size: 'small',
@ -111,16 +111,17 @@
type: 'checkbox',
// type: 'radio',
},
useSearchForm: false,
useSearchForm: true,
showTableSetting: false,
canResize: false,
bordered: true,
pagination: {
pageSize: 10,
},
beforeFetch: () => {
beforeFetch: (data) => {
var temp = {
code: receiceDbCode.value,
key: data.key,
};
return temp;
},

View File

@ -38,7 +38,7 @@
<a-input
v-model:value="db.tableName"
:disabled="!isNewTable(db)"
@change="changeTableName(db)"
@change="if (!db.tableName) db.tableName = db.name;"
/>
</a-col>
<a-col class="gutter-row" :span="11">
@ -155,7 +155,7 @@
dataType: '',
length: 0,
columnDescription: '',
isNullable: 0,
isNullable: 1,
isIdentity: 0,
isPrimarykey: 0,
decimalDigits: 0,
@ -295,7 +295,7 @@
schemas = sch.schemas;
schemas?.forEach((item: any, index: number) => {
// 线
if (item.component && !item.component.includes(notComponentArray)) {
if (item.component && !notComponentArray.includes(item.component)) {
//
if (fieldArray.includes(item.field)) {
db_temp.dbColumnInfoList.push({
@ -304,7 +304,7 @@
dataType: 'varchar',
length: 200,
columnDescription: '图斑组件id',
isNullable: 0,
isNullable: 1,
isIdentity: 0,
isPrimarykey: 0,
decimalDigits: 0,
@ -315,7 +315,7 @@
dataType: 'geometry(GEOMETRY)',
length: 0,
columnDescription: '图斑组件',
isNullable: 0,
isNullable: 1,
isIdentity: 0,
isPrimarykey: 0,
decimalDigits: 0,
@ -323,6 +323,7 @@
item.componentProps.dataTable = db_temp.tableName;
item.componentProps.fieldName = 'gid';
item.csType = 'string';
}
// -
else if (item.component == 'Grid' && item.type == 'subTable') {
@ -338,6 +339,7 @@
);
item.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
item.csType = 'string';
}
//
else if (gridArray.includes(item.component)) {
@ -359,6 +361,7 @@
);
ch.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
ch.csType = 'string';
}
// -/
else if (fieldArray.includes(ch.field) || gridArray.includes(ch.component)) {
@ -392,6 +395,7 @@
// componentProps
ch.componentProps.dataTable = temp.tableName;
ch.componentProps.fieldName = temp.dbColumnName;
ch.csType = 'string';
db_temp.dbColumnInfoList.push(temp);
}
@ -484,11 +488,12 @@
schemas = sch.children;
schemas?.forEach((item: any, index: number) => {
// 线
if (item.component && !item.component.includes(notComponentArray)) {
if (item.component && !notComponentArray.includes(item.component)) {
if (fieldArray.includes(item.field)) {
// -
item.componentProps.dataTable = db_temp.tableName;
item.componentProps.fieldName = 'gid';
item.csType = 'string';
// item.componentProps.fieldName = 'geom';
} else if (item.component == 'Grid' && item.type == 'subTable') {
// -
@ -504,6 +509,7 @@
);
item.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
item.csType = 'string';
} else if (gridArray.includes(item.component)) {
//
if (item.component == 'Tabs') {
@ -523,6 +529,7 @@
);
ch.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
ch.csType = 'string';
}
// -/
else if (fieldArray.includes(ch.field) || gridArray.includes(ch.component)) {
@ -548,6 +555,7 @@
// componentProps
ch.componentProps.dataTable = temp.tableName;
ch.componentProps.fieldName = temp.dbColumnName;
ch.csType = 'string';
db_temp.dbColumnInfoList.push(temp);
}
@ -571,6 +579,7 @@
);
ch.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
ch.csType = 'string';
}
// -/
else if (fieldArray.includes(ch.field) || gridArray.includes(ch.component)) {
@ -596,6 +605,8 @@
// componentProps
ch.componentProps.dataTable = temp.tableName;
ch.componentProps.fieldName = temp.dbColumnName;
ch.csType = 'string';
db_temp.dbColumnInfoList.push(temp);
}
});
@ -618,6 +629,7 @@
);
ch.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
ch.csType = 'string';
}
// -/
else if (fieldArray.includes(ch.field) || gridArray.includes(ch.component)) {
@ -643,6 +655,7 @@
// componentProps
ch.componentProps.dataTable = temp.tableName;
ch.componentProps.fieldName = temp.dbColumnName;
ch.csType = 'string';
db_temp.dbColumnInfoList.push(temp);
}
});
@ -667,6 +680,7 @@
);
ch.componentProps.dataTable =
res?.columns[0]?.children[0]?.componentProps?.dataTable;
ch.csType = 'string';
}
// -/
else if (fieldArray.includes(ch.field) || gridArray.includes(ch.component)) {
@ -692,6 +706,7 @@
// componentProps
ch.componentProps.dataTable = temp.tableName;
ch.componentProps.fieldName = temp.dbColumnName;
ch.csType = 'string';
db_temp.dbColumnInfoList.push(temp);
}
@ -771,8 +786,28 @@
if (checkflag) {
return;
}
//
db_list.value.forEach((db, db_index) => {
if (db.name != db.tableName) {
// scheme
let scheme_replace = saveFormDatas.scheme.scheme;
scheme_replace = replaceInJson(scheme_replace, db.name, db.tableName);
saveFormDatas.scheme.scheme = scheme_replace;
// db
// db.name = db.tableName;
db.dbColumnInfoList?.forEach((d, d_index) => {
d.tableName = db.tableName;
db.dbColumnInfoList[d_index] = d;
});
db_list.value[db_index] = db;
}
});
// relationField
getRelationField();
if (props.isAddVisible) {
db_list.value.forEach(async (db) => {
//
@ -796,7 +831,7 @@
if (!oldDbColumnArray.includes(dbColumn.dbColumnName)) {
dbColumn.isNullable = 1;
let query: any = {
dbCode: forminfoDbCode,
dbCode: forminfoDbCode || 'hcsystemdb',
dbColumn: dbColumn,
};
await AddColumn(query);
@ -832,11 +867,13 @@
}
//
let query: any = { tableName: db.tableName };
let res = await CheckTableExist(query);
if (res) {
createMessage.warn('数据库已有表' + db.tableName);
flag = true;
if (db.tableName) {
let query: any = { tableName: db.tableName };
let res = await CheckTableExist(query);
if (res) {
createMessage.warn('数据库已有表' + db.tableName);
flag = true;
}
}
if (!flag) {
@ -859,16 +896,16 @@
}
//
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(dbColumn.dbColumnName)) {
if (dbColumn.dbColumnName && !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(dbColumn.dbColumnName)) {
createMessage.warn('字段名不符合数据库字段名的命名规则!');
flag = true;
}
//
if (!dbColumns.includes(dbColumn.dbColumnName)) {
if (dbColumn.dbColumnName && !dbColumns.includes(dbColumn.dbColumnName)) {
dbColumns.push(dbColumn.dbColumnName);
} else {
createMessage.warn('字段名不能重复!');
createMessage.warn('同表内的字段名不能重复!');
flag = true;
}
});
@ -881,6 +918,17 @@
return results;
}
//
function replaceInJson(jsonString, itemToReplace, newItem) {
// 使
// itemToReplace
let escapedItem = itemToReplace.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
let regex = new RegExp(escapedItem, 'g');
let replacedJsonString = jsonString.replace(regex, newItem);
return replacedJsonString;
}
// relationField
function getRelationField() {
// primaryKey
@ -923,22 +971,6 @@
closeModalDeleteGrid();
}
//
function changeTableName(db) {
if (db.tableName) {
//
db.tableName = db.tableName.toLowerCase();
let scheme_replace = JSON.stringify(saveFormDatas.scheme.scheme);
scheme_replace = scheme_replace.replace(db.name, db.tableName);
saveFormDatas.scheme.scheme = JSON.parse(scheme_replace);
db.name = db.tableName;
db.dbColumnInfoList?.forEach((d) => {
d.tableName = db.tableName;
});
}
}
//
function closeModalDeleteGrid() {
//

View File

@ -11,7 +11,7 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'type'">
{{ record.type ? '空间类型' : '非空间类型' }}
{{ record.type ? '空间表' : '普通表' }}
</template>
<template v-if="column.key === 'action'">
<TableAction

View File

@ -0,0 +1,176 @@
<template>
<div style="width: 100%">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '撤销',
color: 'error',
popConfirm: {
title: '是否确认撤销',
confirm: () => {
handleRevocation(record);
},
},
},
]"
/>
</template>
</template>
</BasicTable>
<a-modal
width="100%"
wrap-class-name="full-modal"
v-model:open="auditOpen"
title="详情"
:destroyOnClose="true"
>
<template #footer> </template>
<Look ref="posRef" :processId="processId" />
</a-modal>
</div>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getLoadMyCompletedPage } from '@/api/sys/WFTask';
import { revokeAudit } from '@/api/sys/WFProcess';
import { Tag } from 'ant-design-vue';
import { Look } from '@/views/demo/workflow/task/process/page';
import { useMessage } from '@/hooks/web/useMessage';
import { getDetail } from '@/api/sys/WFSchemeInfo';
import { flowStore } from '@/store/modules/flow';
import { useRoute } from 'vue-router';
const { createMessage } = useMessage();
const flowWfDataStore = flowStore();
const searchInfo = reactive<Recordable>({});
const auditOpen = ref(false);
const processId = ref('');
const route = useRoute();
// searchInfo.category = route.query.category;
searchInfo.category = route.params?.id;
const [registerTable, { reload }] = useTable({
api: getLoadMyCompletedPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '审核',
dataIndex: 'operationName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == 1) {
const color = 'red';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
async function handleDetail(record) {
let data = await getDetail({ code: record.processCode });
let scheme = JSON.parse(data.scheme.content);
let wfData = scheme.wfData;
flowWfDataStore.setWfDataAll(wfData);
processId.value = record.processId;
auditOpen.value = true;
// go('/dashboard/task_look_preview/detail?processId=' + record.processId);
}
async function handleRevocation(record) {
if (record.isFinished == 1) {
return createMessage.warning('结束的流程不能撤销。');
}
const data = await revokeAudit({
taskId: record.id,
id: record.processId,
});
if (data) {
reload();
return createMessage.success('撤销成功');
} else {
return createMessage.error('撤销失败');
}
}
</script>
<style lang="less">
.full-modal {
.ant-modal {
max-width: 100%;
top: 0;
}
.ant-modal-content {
height: calc(100vh);
}
.ant-modal-body {
height: 85%;
}
}
</style>

View File

@ -0,0 +1,199 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '审核',
onClick: handleDetail.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
<a-modal
width="100%"
wrap-class-name="full-modal"
v-model:open="auditOpen"
title="审核"
footer=""
:destroyOnClose="true"
>
<template #footer> </template>
<Audit
ref="posRef"
:processId="processId"
:taskId="taskId"
:isRead="isRead"
:type="type"
@closeModel="closeMolder"
/>
</a-modal>
<a-modal
width="100%"
wrap-class-name="full-modal"
v-model:open="previewOpen"
title="流程发起"
:destroyOnClose="true"
>
<template #footer> </template>
<Preview
ref="posRef"
:code="childRecord.childSchemeInfoCode"
:ParentNodeId="childRecord.unitId"
:ParentTaskId="childRecord.id"
:ParentProcessId="childRecord.processId"
@closeModel="closeMolder"
/>
</a-modal>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyUncompletedPage } from '@/api/sys/WFTask';
import { getDetail } from '@/api/sys/WFSchemeInfo';
import { Tag } from 'ant-design-vue';
import { Audit } from '@/views/demo/workflow/task/process/page';
import { flowStore } from '@/store/modules/flow';
import { Preview } from '@/views/demo/workflow/create/index';
import { useRoute } from 'vue-router';
const flowWfDataStore = flowStore();
const searchInfo = reactive<Recordable>({});
const processId = ref('');
const taskId = ref('');
const isRead: any = ref(0);
const type = ref('');
const auditOpen = ref(false);
const previewOpen = ref(false);
const childRecord = ref();
const route = useRoute();
// searchInfo.category = route.query.category;
searchInfo.category = route.params?.id;
const [registerTable, { reload }] = useTable({
api: getLoadMyUncompletedPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '状态',
dataIndex: 'isUrge',
width: 80,
customRender: ({ record }) => {
if (record.isUrge == '1') {
const color = 'red';
const text = '催办';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '正常';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
async function handleDetail(record) {
if (record.type == 3) {
previewOpen.value = true;
childRecord.value = record;
} else {
let data = await getDetail({ code: record.processCode });
let scheme = JSON.parse(data.scheme.content);
let wfData = scheme.wfData;
flowWfDataStore.setWfDataAll(wfData);
auditOpen.value = true;
processId.value = record.processId;
taskId.value = record.id;
type.value = record.type;
}
// go(
// '/dashboard/task_audit_preview/detail?processId=' +
// record.processId +
// '&taskId=' +
// record.id +
// '&type=' +
// record.type +
// '&isRead=0',
// );
}
function closeMolder() {
auditOpen.value = false;
previewOpen.value = false;
reload();
}
</script>
<style lang="less">
.full-modal {
.ant-modal {
max-width: 100%;
top: 0;
}
.ant-modal-content {
height: calc(100vh);
}
.ant-modal-body {
height: 85%;
}
}
::v-deep .full-modal .ant-modal-body {
height: 95% !important;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div style="width: 100%">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
@ -34,13 +34,12 @@
<template #footer> </template>
<Look ref="posRef" :processId="processId" />
</a-modal>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyCompletedPage } from '@/api/sys/WFTask';
import { revokeAudit } from '@/api/sys/WFProcess';
import { Tag } from 'ant-design-vue';

View File

@ -1,5 +1,5 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div style="width: 100%">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
@ -28,13 +28,12 @@
<template #footer> </template>
<Look ref="posRef" :processId="processId" />
</a-modal>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDelegatePage } from '@/api/sys/WFTask';
import { Tag } from 'ant-design-vue';
import { Look } from './process/page';

View File

@ -1,22 +1,20 @@
<template>
<ScrollContainer>
<div ref="wrapperRef" :class="prefixCls">
<Tabs
tab-position="left"
:tabBarStyle="tabBarStyle"
v-model:activeKey="componentCode"
@change="changeKey"
>
<template v-for="item in settingList" :key="item.key">
<TabPane :tab="item.name">
<div :style="'display: flex; height:' + data.height">
<component :is="tabs[item.component]" />
</div>
</TabPane>
</template>
</Tabs>
</div>
</ScrollContainer>
<div ref="wrapperRef" :class="prefixCls">
<Tabs
tab-position="left"
:tabBarStyle="tabBarStyle"
v-model:activeKey="componentCode"
@change="changeKey"
>
<template v-for="item in settingList" :key="item.key">
<TabPane :tab="item.name">
<div :style="'display: flex; height:' + data.height">
<component :is="tabs[item.component]" />
</div>
</TabPane>
</template>
</Tabs>
</div>
</template>
<script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div style="width: 100%">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
@ -34,13 +34,12 @@
<template #footer> </template>
<Initiate ref="posRef" :processId="processId" @closeModel="closeModel" />
</a-modal>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDraftPage, deleteDraft } from '@/api/sys/WFProcess';
import { Initiate } from './process/page';
import { useMessage } from '@/hooks/web/useMessage';

View File

@ -1,5 +1,5 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div style="width: 100%">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
@ -38,13 +38,12 @@
<template #footer> </template>
<Look ref="posRef" :processId="processId" />
</a-modal>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyPage, urge, revoke, revokeAudit } from '@/api/sys/WFProcess';
import { Tag } from 'ant-design-vue';
import { useMessage } from '@/hooks/web/useMessage';

View File

@ -21,7 +21,7 @@
"
v-if="formVisble"
>
<div >
<div>
<FormViewer
ref="formBoxRef"
:formConfig="formConfig"
@ -166,14 +166,16 @@
>
<div class="l-from-body">
<a-form
ref="formRef"
ref="rejectFormRef"
:model="reject"
labelAlign="left"
:label-col="rejectLabelCol"
:wrapper-col="rejectWrapperCol"
:rules="rejectRules"
>
<a-form-item label="驳回到">
<a-form-item label="驳回到" name="nextId">
<a-select
v-model:value="NextId"
v-model:value="reject.nextId"
placeholder="驳回节点选择"
:field-names="{ label: 'unitName', value: 'unitId' }"
:options="rejectRelations"
@ -186,7 +188,7 @@
</template>
<script lang="ts" setup>
import { ref, reactive, onBeforeMount,watch,defineAsyncComponent } from 'vue';
import { ref, reactive, onBeforeMount, watch, defineAsyncComponent } from 'vue';
import { ProcessViewer } from '@/components/ProcessViewer';
import { PageWrapper } from '@/components/Page';
import { createAgain, signAudit, audit, ReadFlow } from '@/api/sys/WFProcess';
@ -229,7 +231,13 @@
const processVisble = ref(false);
const AsyncComponent = ref();
const pcForm = ref();
const NextId = ref('');
const reject = ref({
nextId: '',
});
const rejectFormRef = ref();
const rejectRules = reactive({
nextId: [{ required: true, message: '请选择驳回节点', trigger: 'blur' }],
});
const rejectRelations = ref([]);
const props = defineProps({
processId: String,
@ -340,7 +348,7 @@
let wfData = content.wfData;
const map = new Map();
const newArr = data.logs.filter((v) => !map.has(v.unitId) && map.set(v.unitId, v));
rejectRelations.value = newArr;
rejectRelations.value = newArr.filter((item) => item.taskType == 1);
const auditNode = wfData.find((t) => t.id == data.task.unitId);
if (auditNode.auditTitle) {
auditTitleVal.value = auditNode.auditTitle;
@ -366,6 +374,7 @@
mapConfig.value = currentMapNode.mapConfig;
footerStyle.value.width = mapConfig.value?.isShowMap ? '60%' : '100%';
}
if (currentNode.authFields.length > 0) {
formVisble.value = true;
} else if (currentNode.formUrl) {
@ -759,35 +768,32 @@
}
}
const chooseLayer = ref<string>("")
const geomfield = ref<string>("");
const chooseLayer = ref<string>('');
const geomfield = ref<string>('');
function findValue(obj, targetKey) {
for (var key in obj) {
if (typeof obj[key] === 'object') {
// findValue
var result = findValue(obj[key], targetKey);
if (result !== undefined && result == 'MapGeom') {
return result;
}
} else if (key === targetKey && obj[key] == 'MapGeom') {
//
chooseLayer.value = obj['mapSetData'].chooseLayer;
geomfield.value = obj["field"]
return obj[key];
}
for (var key in obj) {
if (typeof obj[key] === 'object') {
// findValue
var result = findValue(obj[key], targetKey);
if (result !== undefined && result == 'MapGeom') {
return result;
}
} else if (key === targetKey && obj[key] == 'MapGeom') {
//
chooseLayer.value = obj['mapSetData'].chooseLayer;
geomfield.value = obj['field'];
return obj[key];
}
}
}
function getFormSuccess(){
handlerShowGeomtrys(designerData.currentNode);
function getFormSuccess(formData) {
handlerShowGeomtrys(designerData.formCurrentNode, formData);
}
async function handlerShowGeomtrys(currentNode) {
findValue(currentNode.authFields,"component")
let info = currentNode.authFields?.find((item, index) => {
return item.component == 'MapGeom';
});
async function handlerShowGeomtrys(currentNode, formData) {
findValue(currentNode.authFields, 'component');
let layer: string = chooseLayer.value;
if (!layer) {
createMessage.error('图斑未绑定图层服务!');
@ -796,73 +802,77 @@
let geomfiledValue = geomfield.value;
let gids = '';
try {
await formBoxRef.value.getForm().then((res) => {
geomfiledValue = geomfiledValue.toLowerCase();
gids = res[geomfiledValue];
// ids
if (gids) {
try {
let getGeomPrams = {
TableName: layer,
FieldName: 'gid',
FieldValue: gids,
page: 1,
limit: 999,
key: null,
};
getGeom(getGeomPrams).then((res) => {
let geoms = [];
if (res) {
if (res.items?.length > 0) {
res.items.forEach((item, index) => {
let geom = {
key: item.gid,
mapgeom: item.geometry,
};
geoms.push(geom);
});
}
// MapboxComponent.value.handlerDraw(status,mapgemoList.value, false);
MapboxComponent.value.handlerDraw('Details', geoms, false);
} else {
createMessage.error('当前数据没有图斑!');
geomfiledValue = geomfiledValue.toLowerCase();
gids = formData[geomfiledValue];
// ids
if (gids) {
try {
let getGeomPrams = {
TableName: layer,
FieldName: 'gid',
FieldValue: gids,
page: 1,
limit: 999,
key: null,
};
getGeom(getGeomPrams).then((res) => {
let geoms = [];
if (res) {
if (res.items?.length > 0) {
res.items.forEach((item, index) => {
let geom = {
key: item.gid,
mapgeom: item.geometry,
};
geoms.push(geom);
});
}
});
} catch (e) {
createMessage.error('当前数据没有图斑!');
}
} else {
// MapboxComponent.value.handlerDraw(status,mapgemoList.value, false);
MapboxComponent.value.handlerDraw('Details', geoms, false);
} else {
createMessage.error('当前数据没有图斑!');
}
});
} catch (e) {
createMessage.error('当前数据没有图斑!');
}
});
} else {
createMessage.error('当前数据没有图斑!');
}
} catch {
createMessage.error('获取图斑数据失败!');
}
}
function onMapboxLoad() {
}
function onMapboxLoad() {}
//
async function rejectHandleOk() {
const data = await audit(props.taskId, {
code: designerData.currentBtn.code,
name: designerData.currentBtn.name,
des: formData.value.des,
NextId: NextId.value,
});
if (data) {
closePage();
return createMessage.success('成功');
} else {
return createMessage.error('失败');
let res = await rejectFormRef.value
.validate()
.then(() => {
return true;
})
.catch((error) => {
return false;
});
if (res) {
const data = await audit(props.taskId, {
code: designerData.currentBtn.code,
name: designerData.currentBtn.name,
des: formData.value.des,
NextId: reject.value.nextId,
});
if (data) {
closePage();
return createMessage.success('成功');
} else {
return createMessage.error('失败');
}
}
}
onBeforeMount(() => {
getTaskInfo();
});
</script>
<style lang="less" scoped>
::v-deep .ant-tabs-nav-wrap {

View File

@ -32,6 +32,7 @@
:instanceInfo="designerData.process.instanceInfo"
:issueId="designerData.formCurrentNode.issueId"
:isDetail="true"
@getFormSuccess="getFormSuccess"
v-if="formVisble"
/>
</div>
@ -427,29 +428,22 @@
}
}
async function handlerShowGeomtrys(currentNode) {
findValue(currentNode.value.schemas,"component")
function getFormSuccess(formData){
handlerShowGeomtrys(designerData.formCurrentNode,formData);
}
let info = currentNode.authFields?.find((item, index) => {
return item.component == 'MapGeom';
});
async function handlerShowGeomtrys(currentNode,formData) {
findValue(currentNode.authFields,"component");
let layer: string = chooseLayer.value;
// let layer:string="drone_shp_data";
// if (info) {
// layer = info?.mapSetData?.chooseLayer;
// }
if (!layer) {
createMessage.error('图斑未绑定图层服务!');
return;
}
let geomfiledValue = geomfield.value;
let gids = '';
try {
await formBoxRef.value.getForm().then((res) => {
gids = res[geomfiledValue];
geomfiledValue = geomfiledValue.toLowerCase();
gids = formData[geomfiledValue];
// ids
if (gids) {
try {
@ -485,13 +479,12 @@
} else {
createMessage.error('当前数据没有图斑!');
}
});
} catch {
createMessage.error('获取图斑数据失败!');
}
}
function onMapboxLoad() {
handlerShowGeomtrys(designerData.formCurrentNode);
}
onBeforeMount(() => {
getDetailInfo();

View File

@ -1,5 +1,5 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div style="width: 100%">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
@ -31,13 +31,12 @@
@closeModel="closeMolder"
/>
</a-modal>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyReadPage } from '@/api/sys/WFTask';
import { Tag } from 'ant-design-vue';
import { Audit } from './process/page';

View File

@ -1,5 +1,5 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div style="width: 100%">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
@ -49,13 +49,12 @@
@closeModel="closeMolder"
/>
</a-modal>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { reactive, h, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyUncompletedPage } from '@/api/sys/WFTask';
import { getDetail } from '@/api/sys/WFSchemeInfo';
import { Tag } from 'ant-design-vue';
@ -192,8 +191,7 @@
}
}
::v-deep .full-modal .ant-modal-body{
height:95%!important;
::v-deep .full-modal .ant-modal-body {
height: 95% !important;
}
</style>

View File

@ -64,12 +64,16 @@
<div class="show-search-title"></div>
<div class="show-search-content">
<div class="show-search-item" v-for="(item, index) in searchList" :key="index">
<div style="width:100%;color:#D3F1FF">
<div style="display:flex;justify-content: space-between;margin-bottom: 8px">
<div class="item-name">{{item.name}}</div>
<div class="item-person-name">{{item.personName}}</div>
<div style="width: 100%; color: #d3f1ff">
<div style="display: flex; justify-content: space-between; margin-bottom: 8px">
<div class="item-name">{{ item.name }}</div>
<div class="item-person-name">{{ item.personName }}</div>
</div>
<div class="item-address"><img :src="'dataScreen/address.svg'" style="margin-right: 10px"/>{{item.address}}</div>
<div class="item-address"
><img :src="'dataScreen/address.svg'" style="margin-right: 10px" />{{
item.address
}}</div
>
</div>
</div>
</div>
@ -78,11 +82,11 @@
<div class="show-enterprise-info" :style="`top:${infoPosition.top};left:${infoPosition.left}`">
<div class="title-div">
<div class="title-span">隆兴板材厂A</div>
<div class="title-close-button"><img :src="'dataScreen/info-close.svg'"/></div>
<div class="title-close-button"><img :src="'dataScreen/info-close.svg'" /></div>
</div>
<div v-for="(item, index) in enterpriseInfo" :key="index" class="show-info-item">
<div class="first-span">{{item.title}}</div>
<div class="last-span">{{showEnterpriseInfoData[item.key] }}</div>
<div class="first-span">{{ item.title }}</div>
<div class="last-span">{{ showEnterpriseInfoData[item.key] }}</div>
</div>
<div class="show-image">图片</div>
</div>
@ -91,9 +95,10 @@
<script setup lang="ts">
import * as echarts from 'echarts';
import { onMounted, ref, h } from 'vue';
import { onMounted, ref, h, onBeforeUnmount } from 'vue';
import { SearchOutlined } from '@ant-design/icons-vue';
import { enterpriseInfo } from './util';
const mapClick = (event) => {
let left = 0;
let top = 0;
@ -419,22 +424,34 @@
},
],
};
let enterpriseAreaBarChart = {};
let enterpriseIncomeBarChart = {};
let landAreaPieChart = {};
let realEstateAreaPieChart = {};
onMounted(() => {
let enterpriseAreaBarDom = document.getElementsByClassName('enterprise-area-bar')[0];
let enterpriseIncomeBarDom = document.getElementsByClassName('enterprise-income-bar')[0];
let landAreaPieDom = document.getElementsByClassName('land-area-pie')[0];
let realEstateAreaPieDom = document.getElementsByClassName('real-estate-area-pie')[0];
let enterpriseAreaBarChart = echarts.init(enterpriseAreaBarDom);
let enterpriseIncomeBarChart = echarts.init(enterpriseIncomeBarDom);
let landAreaPieChart = echarts.init(landAreaPieDom);
let realEstateAreaPieChart = echarts.init(realEstateAreaPieDom);
enterpriseAreaBarChart = echarts.init(enterpriseAreaBarDom);
enterpriseIncomeBarChart = echarts.init(enterpriseIncomeBarDom);
landAreaPieChart = echarts.init(landAreaPieDom);
realEstateAreaPieChart = echarts.init(realEstateAreaPieDom);
enterpriseAreaBarChart.setOption(enterpriseAreaBarChartOption);
enterpriseIncomeBarChart.setOption(enterpriseIncomeBarChartOption);
landAreaPieChart.setOption(landAreaPieChartOption);
realEstateAreaPieChart.setOption(realEstateAreaPieChartOption);
});
onBeforeUnmount(() => {
//
enterpriseAreaBarChart.dispose();
enterpriseIncomeBarChart.dispose();
landAreaPieChart.dispose();
realEstateAreaPieChart.dispose();
console.log('onBeforeUnmount>>>');
});
const value = ref('');
const showEnterpriseInfoData = ref({
legalPerson: '刘明',