Compare commits

..

21 Commits

Author SHA1 Message Date
Zhufu 8248c5b51b Merge branch 'main' into hc_zhufu 2024-06-04 09:43:04 +08:00
徐景良 c7dddbd5be Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-04 08:27:02 +08:00
徐景良 7211095458 merge 2024-06-04 08:26:56 +08:00
刘妍 562b5a8733 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-03 17:37:52 +08:00
刘妍 859d586b29 优化 2024-06-03 17:37:48 +08:00
zzq bfa1c35647 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-03 16:37:40 +08:00
zzq 843acc3415 表单设计选项卡添加其他表单选项(一层),表单发布调用重新解析数据 2024-06-03 16:37:33 +08:00
滕嵩 37f22d3544 表单调用-脚本调用和脚本规则、使用方法 2024-06-03 16:29:24 +08:00
刘妍 9d56205714 流程审核节点,审核人员设置增加执行SQL功能 2024-06-03 14:48:09 +08:00
刘妍 2e377e4991 优化 2024-06-03 14:06:42 +08:00
刘妍 19d1bff08f 1 2024-06-03 10:24:42 +08:00
徐景良 345feabcbb Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-06-03 10:22:19 +08:00
徐景良 bebef7ed4c merge 2024-06-03 10:22:15 +08:00
刘妍 0665363eb9 优化 2024-06-03 10:19:53 +08:00
徐景良 b4c2219682 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-05-31 17:04:36 +08:00
徐景良 880c5a49bc 文件图片视频上传,获取经纬度 2024-05-31 17:04:30 +08:00
徐景良 249319edc9 文件、图片、视频上传,获取经纬度 2024-05-31 17:02:53 +08:00
徐景良 1c450a231e Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-05-31 14:55:58 +08:00
徐景良 daf515cd63 地图测量工具、图斑定位 2024-05-31 14:55:55 +08:00
徐景良 0abdaf9bf9 Merge branch 'main' of http://123.132.248.154:10000/HC_YFZX/CaiYuanYiTiHua 2024-05-30 10:14:01 +08:00
徐景良 ae4477e596 合并 2024-05-30 10:13:56 +08:00
46 changed files with 2375 additions and 358 deletions

View File

@ -7,9 +7,9 @@ VITE_PUBLIC_PATH = /
# Basic interface address SPA
#VITE_GLOB_API_URL=/basic-api
#财源
VITE_GLOB_API_URL=http://192.168.10.102:9500
# 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://192.168.10.102:9023

View File

@ -12,9 +12,9 @@ VITE_BUILD_COMPRESS = 'none'
# Basic interface address SPA
#财源
VITE_GLOB_API_URL=http://192.168.10.102:9500
#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://192.168.10.102:9023
# File upload address optional
# It can be forwarded by nginx or write the actual address directly

View File

@ -102,7 +102,10 @@
"mapbox-gl-utils": "^0.44.0",
"@mapbox/mapbox-gl-draw": "^1.4.1",
"mapbox-gl-draw-snap-mode": "^0.2.0",
"mapbox-extensions":"^1.3.38",
"terraformer-wkt-parser": "^1.2.1",
"ceel-json-editor":"^0.0.3",
"@originjs/vite-plugin-commonjs":"^1.0.3",
"mars3d": "^3.7.0",
"mars3d-cesium": "^1.113.0",
"min-dash": "^4.2.1",

View File

@ -22,3 +22,14 @@ export function uploadApi(
params,
);
}
export function fileUploadApi(params: UploadFileParams,url:string,onUploadProgress: (progressEvent: AxiosProgressEvent) => void,) {
return defHttp.uploadFile<UploadApiResult>(
{
url: url,
onUploadProgress,
},
params,
);
}

View File

@ -28,7 +28,8 @@ import ApiTree from './components/ApiTree.vue';
import ApiTreeSelect from './components/ApiTreeSelect.vue';
import ApiCascader from './components/ApiCascader.vue';
import ApiTransfer from './components/ApiTransfer.vue';
import { BasicUpload, ImageUpload } from '@/components/Upload';
import { BasicUpload, ImageUpload,VideoUpload,FileUpload } from '@/components/Upload';
import {Location } from '@/components/Map'
import { StrengthMeter } from '@/components/StrengthMeter';
import { IconPicker } from '@/components/Icon';
import { CountdownInput } from '@/components/CountDown';
@ -45,6 +46,9 @@ componentMap.set('InputTextArea', Input.TextArea);
componentMap.set('InputNumber', InputNumber);
componentMap.set('AutoComplete', AutoComplete);
componentMap.set('ImageUpload', ImageUpload);
componentMap.set("VideoUpload",VideoUpload);
componentMap.set("FileUpload",FileUpload);
componentMap.set("Location",Location);
componentMap.set('Select', Select);
componentMap.set('ApiSelect', ApiSelect);
componentMap.set('ApiTree', ApiTree);

View File

@ -111,7 +111,16 @@
const keyValue = ref('');
const FieldsValue = ref({});
const [registerForm, { getFieldsValue, setFieldsValue, updateSchema, resetFields, validate }] =
useForm({
labelWidth: 100,
schemas: formColumns,
showActionButtonGroup: false,
baseColProps: { lg: 24, md: 24 },
});
async function getFormHistory() {
console.log('getFormHistory');
const data = await LoadFormScheme({
schemeId: props.formVerison,
});
@ -119,12 +128,15 @@
const scheme = JSON.parse(data.scheme);
console.log(scheme);
console.log(props.formConfig);
console.log("subTableColumns",subTableColumns)
subTableDB.value = scheme.db;
let disDetail = false;
scheme.formInfo.tabList.forEach((tabElement, index) => {
tabElement.schemas.forEach((element) => {
if (element.field == props.formRelationId) {
keyValue.value = element.componentProps.fieldName;
getFormDetail();
disDetail = true;
}
//
props.formConfig.forEach((configElement) => {
@ -211,11 +223,22 @@
}
});
formModalVisible.value = true;
resetFields();
setTimeout(() => {
resetFields();
console.log(props.flowFormData);
if (!disDetail) {
console.log('赋值赋值');
if (props.flowFormData) {
setFieldsValue(props.flowFormData);
}
}
}, 10);
scrollValue.value = { x: (subTableColumns.value.length - 1) * 140, y: 400 };
}
}
async function tabsChange(e) {
console.log('tabsChange');
formColumns.forEach((element) => {
element.show = false;
if (element.parentValue == e) {
@ -225,7 +248,6 @@
//
const values = await validate();
console.log(values);
console.log(Object.keys(FieldsValue.value));
if (Object.keys(FieldsValue.value).length == 0) {
FieldsValue.value = values;
}
@ -245,14 +267,9 @@
});
console.log(FieldsValue.value);
}
const [registerForm, { getFieldsValue, setFieldsValue, updateSchema, resetFields, validate }] =
useForm({
labelWidth: 100,
schemas: formColumns,
showActionButtonGroup: false,
baseColProps: { lg: 24, md: 24 },
});
async function getFormDetail() {
console.log('getFormDetail');
var instance = JSON.parse(props.instanceInfo);
const querys = {
id: props.formVerison,
@ -281,28 +298,18 @@
}
async function getForm() {
try {
console.log(getFieldsValue());
const values = await validate();
console.log(values);
console.log(FieldsValue.value);
for (const key in values) {
for (const fieKey in FieldsValue.value) {
if (key == fieKey) {
if (values[key] != undefined) {
FieldsValue.value[key] = values[key];
values[key] = FieldsValue.value[key];
}
}
}
}
console.log(values);
console.log(FieldsValue.value);
let saveSubTableList = [];
let query;
if (Object.keys(FieldsValue.value).length == 0) {
query = values;
} else {
query = FieldsValue.value;
}
let query = values;
console.log(query);
subTableList.value.forEach((item) => {
let emptyObj = {};
@ -325,12 +332,11 @@
getForm,
});
onMounted(() => {
if (props.flowFormData) {
FieldsValue.value = props.flowFormData;
}
if (props.formVerison) {
getFormHistory();
} else {
setFieldsValue({
...props.flowFormData,
});
}
});
const addListItem = () => {

View File

@ -0,0 +1,4 @@
import { withInstall } from '@/utils';
import getLocation from './src/components/Location.vue'
export const Location = withInstall(getLocation);

View File

@ -0,0 +1,287 @@
<template>
<div>
<div class="mapContainer" :id="'mapContainer'+mapRandom">
<div class="refresh-button">
<ReloadOutlined @click="onrefresh"/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import mapboxgl, { Map, Popup } from 'mapbox-gl';
import { ref, toRefs, watch,onMounted } from 'vue';
import { ReloadOutlined } from '@ant-design/icons-vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
import { Modal, Upload } from 'ant-design-vue';
import { on } from '@/utils/domUtils';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { useMessage } from '@/hooks/web/useMessage';
import { isArray, isFunction, isObject, isString } from '@/utils/is';
import { warn } from '@/utils/log';
import { useI18n } from '@/hooks/web/useI18n';
import { useUploadType } from '../hooks/useUpload';
import { uploadContainerProps } from '../props';
import { isImgTypeByName } from '../helper';
import { UploadResultStatus } from '@/components/Upload/src/types/typing';
import { parse } from 'path';
defineOptions({ name: 'ImageUpload' });
const mapRandom = ref(parseInt(Math.random()*100000).toString())
const emit = defineEmits(['change', 'update:value', 'delete']);
const props = defineProps({
...uploadContainerProps,
});
const { t } = useI18n();
const { createMessage } = useMessage();
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
const isInnerOperate = ref<boolean>(false);
const { getStringAccept } = useUploadType({
acceptRef: accept,
helpTextRef: helpText,
maxNumberRef: maxNumber,
maxSizeRef: maxSize,
});
const previewOpen = ref<boolean>(false);
const previewImage = ref<string>('');
const previewTitle = ref<string>('');
const fileList = ref<UploadProps['fileList']>([]);
const isLtMsg = ref<boolean>(true);
const isActMsg = ref<boolean>(true);
let map:Map;
onMounted(() => {
mapboxgl.accessToken = "pk.eyJ1Ijoic2hpY2hhbzEyMyIsImEiOiJja3FobnI1aDEwNGF6Mm9vOXVhNnBzZmFhIn0.2fZKiMqCQHxVY74QShMEGQ"
map = initMap();
map.on("load",function(){
refreshLocation();
})
})
watch(
() => props.value,
(v) => {
if (isInnerOperate.value) {
isInnerOperate.value = false;
return;
}
if (v) {
let value: string[] = [];
if (isArray(v)) {
value = v;
} else {
value.push(v);
}
fileList.value = value.map((item, i) => {
if (item && isString(item)) {
return {
uid: -i + '',
name: item.substring(item.lastIndexOf('/') + 1),
status: 'done',
url: item,
};
} else if (item && isObject(item)) {
return item;
} else {
return;
}
}) as UploadProps['fileList'];
}
},
);
const initMap = () => {
return new mapboxgl.Map({
container: 'mapContainer'+mapRandom.value,
language: 'zh-cmn',
projection: 'equirectangular', // wgs84
style: {
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
'raster-tiles': {
type: 'raster',
tiles: [
`https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=b6585bc41ee16251dbe6b1af64f375d9`,
],
tileSize: 256,
},
},
layers: [
{
id: 'tdt-img-tiles',
type: 'raster',
source: 'raster-tiles',
minzoom: 0,
maxzoom: 18,
},
],
},
maxZoom: 22,
minZoom: 6,
zoom: 15,
center: [118.298906,35.135013],
});
};
const refreshLocation = () => {
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': [118.298906,35.135013]
}
}
]
}
});
// Add a circle layer
map.addLayer({
'id': 'circle',
'type': 'circle',
'source': 'points',
'paint': {
'circle-color': '#409EFF',
'circle-radius': 6,
'circle-stroke-width': 3,
'circle-stroke-color': '#ffffff'
}
});
};
const onrefresh = () => {
createMessage.success(t('component.map.refreshSuccess'));
}
function getBase64<T extends string | ArrayBuffer | null>(file: File) {
return new Promise<T>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result as T);
};
reader.onerror = (error) => reject(error);
});
}
const handlePreview = async (file: UploadFile) => {
console.log("fileEEEEE",file);
if (!file.url && !file.preview) {
file.preview = await getBase64<string>(file.originFileObj!);
}
previewImage.value = file.url || file.preview || '';
previewOpen.value = true;
previewTitle.value =
file.name || previewImage.value.substring(previewImage.value.lastIndexOf('/') + 1);
};
const handleRemove = async (file: UploadFile) => {
if (fileList.value) {
const index = fileList.value.findIndex((item) => item.uid === file.uid);
index !== -1 && fileList.value.splice(index, 1);
const value = getValue();
isInnerOperate.value = true;
emit('change', value);
emit('delete', file);
}
};
const handleCancel = () => {
previewOpen.value = false;
previewTitle.value = '';
};
const beforeUpload = (file: File) => {
const { maxSize, accept } = props;
const { name } = file;
const isAct = isImgTypeByName(name);
if (!isAct) {
createMessage.error(t('component.upload.acceptUpload', [accept]));
isActMsg.value = false;
//
setTimeout(() => (isActMsg.value = true), 1000);
}
const isLt = file.size / 1024 / 1024 > maxSize;
if (isLt) {
createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
isLtMsg.value = false;
//
setTimeout(() => (isLtMsg.value = true), 1000);
}
return (isAct && !isLt) || Upload.LIST_IGNORE;
};
async function customRequest(info: UploadRequestOption<any>) {
const { api } = props;
if (!api || !isFunction(api)) {
return warn('upload api must exist and be a function');
}
try {
const res = await props.api?.({
data: {
...(props.uploadParams || {}),
},
file: info.file,
name: props.name,
filename: props.filename,
});
info.onSuccess!(res.data);
const value = getValue();
isInnerOperate.value = true;
emit('change', value);
} catch (e: any) {
console.log(e);
info.onError!(e);
}
}
function getValue() {
const list = (fileList.value || [])
.filter((item) => item?.status === UploadResultStatus.DONE)
.map((item: any) => {
return item?.url || item?.response?.url;
});
return props.multiple ? list : list.length > 0 ? list[0] : '';
}
</script>
<style lang="less">
.ant-upload-select-picture-card i {
color: #999;
font-size: 32px;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
.mapContainer{
width:100%;
height:280px;
border-radius: 6px;
}
.refresh-button{
position:absolute;
top:6px;
right:6px;
width:30px;
height:30px;
border-radius: 4px;
background:#fff;
line-height: 30px;
text-align: center;
}
</style>

View File

@ -0,0 +1,139 @@
import type { BasicColumn, ActionItem } from '@/components/Table';
import { FileBasicColumn, FileItem, PreviewFileItem, UploadResultStatus } from '../types/typing';
import { isImgTypeByName } from '../helper';
import { Progress, Tag } from 'ant-design-vue';
import TableAction from '@/components/Table/src/components/TableAction.vue';
import ThumbUrl from './ThumbUrl.vue';
import { useI18n } from '@/hooks/web/useI18n';
const { t } = useI18n();
// 文件上传列表
export function createTableColumns(): FileBasicColumn[] {
return [
{
dataIndex: 'thumbUrl',
title: t('component.upload.legend'),
width: 100,
customRender: ({ record }) => {
const { thumbUrl } = (record as FileItem) || {};
return thumbUrl && <ThumbUrl fileUrl={thumbUrl} />;
},
},
{
dataIndex: 'name',
title: t('component.upload.fileName'),
align: 'left',
customRender: ({ text, record }) => {
const { percent, status: uploadStatus } = (record as FileItem) || {};
let status: 'normal' | 'exception' | 'active' | 'success' = 'normal';
if (uploadStatus === UploadResultStatus.ERROR) {
status = 'exception';
} else if (uploadStatus === UploadResultStatus.UPLOADING) {
status = 'active';
} else if (uploadStatus === UploadResultStatus.SUCCESS) {
status = 'success';
}
return (
<div>
<p class="truncate mb-1 max-w-[280px]" title={text}>
{text}
</p>
<Progress percent={percent} size="small" status={status} />
</div>
);
},
},
{
dataIndex: 'size',
title: t('component.upload.fileSize'),
width: 100,
customRender: ({ text = 0 }) => {
return text && (text / 1024).toFixed(2) + 'KB';
},
},
{
dataIndex: 'status',
title: t('component.upload.fileStatue'),
width: 100,
customRender: ({ text }) => {
if (text === UploadResultStatus.SUCCESS) {
return <Tag color="green">{() => t('component.upload.uploadSuccess')}</Tag>;
} else if (text === UploadResultStatus.ERROR) {
return <Tag color="red">{() => t('component.upload.uploadError')}</Tag>;
} else if (text === UploadResultStatus.UPLOADING) {
return <Tag color="blue">{() => t('component.upload.uploading')}</Tag>;
}
return text || t('component.upload.pending');
},
},
];
}
export function createActionColumn(handleRemove: Function): FileBasicColumn {
return {
width: 120,
title: t('component.upload.operating'),
dataIndex: 'action',
fixed: false,
customRender: ({ record }) => {
const actions: ActionItem[] = [
{
label: t('component.upload.del'),
color: 'error',
onClick: handleRemove.bind(null, record),
},
];
return <TableAction actions={actions} outside={true} />;
},
};
}
// 文件预览列表
export function createPreviewColumns(): BasicColumn[] {
return [
{
dataIndex: 'url',
title: t('component.upload.legend'),
width: 100,
customRender: ({ record }) => {
const { url } = (record as PreviewFileItem) || {};
return isImgTypeByName(url) && <ThumbUrl fileUrl={url} />;
},
},
{
dataIndex: 'name',
title: t('component.upload.fileName'),
align: 'left',
},
];
}
export function createPreviewActionColumn({
handleRemove,
handleDownload,
}: {
handleRemove: Fn;
handleDownload: Fn;
}): BasicColumn {
return {
width: 160,
title: t('component.upload.operating'),
dataIndex: 'action',
fixed: false,
customRender: ({ record }) => {
const actions: ActionItem[] = [
{
label: t('component.upload.del'),
color: 'error',
onClick: handleRemove.bind(null, record),
},
{
label: t('component.upload.download'),
onClick: handleDownload.bind(null, record),
},
];
return <TableAction actions={actions} outside={true} />;
},
};
}

View File

@ -0,0 +1,32 @@
export function checkFileType(file: File, accepts: string[]) {
const newTypes = accepts.join('|');
// const reg = /\.(jpg|jpeg|png|gif|txt|doc|docx|xls|xlsx|xml)$/i;
const reg = new RegExp('\\.(' + newTypes + ')$', 'i');
return reg.test(file.name);
}
export function checkImgType(file: File) {
return isImgTypeByName(file.name);
}
export function isImgTypeByName(name: string) {
return /\.(jpg|jpeg|png|gif|webp)$/i.test(name);
}
export function isVideoTypeByName(name: string) {
return /\.(mp4|mov|avi)$/i.test(name);
}
export function getBase64WithFile(file: File) {
return new Promise<{
result: string;
file: File;
}>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve({ result: reader.result as string, file });
reader.onerror = (error) => reject(error);
});
}

View File

@ -0,0 +1,61 @@
import { Ref, unref, computed } from 'vue';
import { useI18n } from '@/hooks/web/useI18n';
const { t } = useI18n();
export function useUploadType({
acceptRef,
helpTextRef,
maxNumberRef,
maxSizeRef,
}: {
acceptRef: Ref<string[]>;
helpTextRef: Ref<string>;
maxNumberRef: Ref<number>;
maxSizeRef: Ref<number>;
}) {
// 文件类型限制
const getAccept = computed(() => {
const accept = unref(acceptRef);
if (accept && accept.length > 0) {
return accept;
}
return [];
});
const getStringAccept = computed(() => {
return unref(getAccept)
.map((item) => {
if (item.indexOf('/') > 0 || item.startsWith('.')) {
return item;
} else {
return `.${item}`;
}
})
.join(',');
});
// 支持jpg、jpeg、png格式不超过2M最多可选择10张图片
const getHelpText = computed(() => {
const helpText = unref(helpTextRef);
if (helpText) {
return helpText;
}
const helpTexts: string[] = [];
const accept = unref(acceptRef);
if (accept.length > 0) {
helpTexts.push(t('component.upload.accept', [accept.join(',')]));
}
const maxSize = unref(maxSizeRef);
if (maxSize) {
helpTexts.push(t('component.upload.maxSize', [maxSize]));
}
const maxNumber = unref(maxNumberRef);
if (maxNumber && maxNumber !== Infinity) {
helpTexts.push(t('component.upload.maxNumber', [maxNumber]));
}
return helpTexts.join('');
});
return { getAccept, getStringAccept, getHelpText };
}

View File

@ -0,0 +1,118 @@
import type { PropType } from 'vue';
import { FileBasicColumn } from './types/typing';
import type { Options } from 'sortablejs';
import { Merge } from '@/utils/types';
type SortableOptions = Merge<
Omit<Options, 'onEnd'>,
{
onAfterEnd?: <T = any, R = any>(params: T) => R;
// ...可扩展
}
>;
type ListType = 'text' | 'picture' | 'picture-card';
export const basicProps = {
listType: {
type: String as PropType<ListType>,
default: 'picture-card',
},
helpText: {
type: String as PropType<string>,
default: '',
},
// 文件最大多少MB
maxSize: {
type: Number as PropType<number>,
default: 2,
},
// 最大数量的文件Infinity不限制
maxNumber: {
type: Number as PropType<number>,
default: 1,
},
// 根据后缀,或者其他
accept: {
type: Array as PropType<string[]>,
default: () => [],
},
multiple: {
type: Boolean as PropType<boolean>,
default: false,
},
uploadParams: {
type: Object as PropType<any>,
default: () => ({}),
},
api: {
type: Function as PropType<PromiseFn>,
default: null,
required: true,
},
name: {
type: String as PropType<string>,
default: 'file',
},
filename: {
type: String as PropType<string>,
default: null,
},
fileListOpenDrag: {
type: Boolean,
default: true,
},
fileListDragOptions: {
type: Object as PropType<SortableOptions>,
default: () => ({}),
},
};
export const uploadContainerProps = {
value: {
type: Array as PropType<string[]>,
default: () => [],
},
...basicProps,
showPreviewNumber: {
type: Boolean as PropType<boolean>,
default: true,
},
emptyHidePreview: {
type: Boolean as PropType<boolean>,
default: false,
},
};
export const previewProps = {
value: {
type: Array as PropType<string[]>,
default: () => [],
},
};
export const fileListProps = {
columns: {
type: Array as PropType<FileBasicColumn[]>,
default: null,
},
actionColumn: {
type: Object as PropType<FileBasicColumn>,
default: null,
},
dataSource: {
type: Array as PropType<any[]>,
default: null,
},
openDrag: {
type: Boolean,
default: false,
},
dragOptions: {
type: Object as PropType<SortableOptions>,
default: () => ({}),
},
};

View File

@ -0,0 +1,46 @@
import { BasicColumn } from '@/components/Table';
import { UploadApiResult } from '@/api/sys/model/uploadModel';
export enum UploadResultStatus {
DONE = 'done',
SUCCESS = 'success',
ERROR = 'error',
UPLOADING = 'uploading',
}
export interface FileItem {
thumbUrl?: string;
name: string;
size: string | number;
type?: string;
percent: number;
file: File;
status?: UploadResultStatus;
response?: UploadApiResult;
uuid: string;
}
export interface PreviewFileItem {
url: string;
name: string;
type: string;
}
export interface FileBasicColumn extends Omit<BasicColumn, 'customRender'> {
/**
* Renderer of the table cell. The return value should be a VNode, or an object for colSpan/rowSpan config
* @type Function | ScopedSlot
*/
customRender?: Function;
/**
* Title of this column
* @type any (string | slot)
*/
title: string;
/**
* Display field of the data record, could be set like a.b.c
* @type string
*/
dataIndex: string;
}

View File

@ -9,7 +9,7 @@
<template #closeIcon>
<CloseCircleOutlined />
</template>
<div class="title">上传shp</div>
<div class="title">上传数据</div>
<div class="content">
<a-steps
class="steps"
@ -45,6 +45,7 @@
</div>
</div>
<div class="upload-form">
<a-form
ref="formRef"
:model="uploadFrom"
@ -55,26 +56,74 @@
<a-form-item label="服务名称" name="serverName">
<a-input v-model:value="uploadFrom.serverName" placeholder="请输入服务名称" />
</a-form-item>
<a-form-item label="空间参考" name="spaceType">
<!-- <a-input v-model:value="uploadFrom.spaceType" /> -->
<a-select v-model:value="uploadFrom.spaceType" placeholder="请选择空间参考">
<a-select-option value="EPSG:4326">EPSG:4326</a-select-option>
<a-select-option value="EPSG:3857">EPSG:3857</a-select-option>
<a-select-option value="EPSG:900913">EPSG:900913</a-select-option>
<!-- 显示条件文件类型为Excel时 -->
<a-form-item label="图斑数据" name="hasFeature" v-if="!isShp">
<a-select v-model:value="uploadFrom.hasFeature" placeholder="请选择是否具有图斑数据">
<a-select-option value="1"></a-select-option>
<a-select-option value="0"></a-select-option>
</a-select>
</a-form-item>
<a-form-item label="表名" name="tableName">
<a-input v-model:value="uploadFrom.tableName" placeholder="请输入表名" />
<!-- 显示条件文件类型为shp 或者 类型为Excel时有图斑数据 -->
<a-form-item label="空间参考" name="spaceType" v-if="isShp || (!isShp && uploadFrom.hasFeature == '1')">
<a-select v-model:value="uploadFrom.spaceType" placeholder="请选择空间参考">
<a-select-option value="EPSG:4326">EPSG:4326</a-select-option>
<a-select-option value="3857">EPSG:3857</a-select-option>
<a-select-option value="900913">EPSG:900913</a-select-option>
</a-select>
</a-form-item>
<!-- 显示条件文件类型为Excel有图斑时 -->
<a-form-item label="数据类型" name="spaceType" v-if="!isShp && uploadFrom.hasFeature == '1'">
<a-select v-model:value="uploadFrom.layerType" placeholder="请选择数据类型">
<a-select-option value="point"></a-select-option>
<a-select-option value="linestring">线</a-select-option>
<a-select-option value="polygon"></a-select-option>
</a-select>
</a-form-item>
<a-form-item label="数据表名" name="tableName">
<a-row :gutter="12">
<a-col :span="20">
<a-input v-model:value="uploadFrom.tableName" placeholder="请输入表名" />
</a-col>
<a-col :span="4">
<!-- <a-tooltip title="从现有数据表中选择">
<a-button type="primary" :icon="h(PlusOutlined)" @click="handlerGetExistsTableList"/>
</a-tooltip> -->
<a-popover placement="topLeft">
<template #content>
<a-table :dataSource="dataSource" :columns="columns" :size="'small'" >
<template #bodyCell="{ column,record }">
<template v-if="column.key === 'operation'">
<a-button type="" :icon="h(PlusOutlined)" @click="handlerGetExistsTableList(record)" />
</template>
</template>
</a-table>
</template>
<template #title>
<span>从现有数据表中选择</span>
</template>
<a-button type="primary" :icon="h(PlusOutlined)" />
</a-popover>
</a-col>
</a-row>
</a-form-item>
</a-form>
<div class="upload-span-button">
<a-button type="primary" :icon="h(PlusOutlined)" @click="submitShp"></a-button>
<a-button type="primary" :icon="h(CloudUploadOutlined)" @click="submitShp"></a-button>
</div>
</div>
</div>
<div class="edit-info-div" v-show="current === 1">
<a-table
:columns="columns"
:columns="tablecolumns"
:data-source="dataList"
:pagination="false"
:bordered="true"
@ -112,6 +161,7 @@
>
</div>
</div>
<div class="submit-success" v-show="current === 2">
<div class="success-content">
<CheckCircleOutlined style="font-size: 100px; color: #1fd286; margin-bottom: 30px" />
@ -119,6 +169,11 @@
<div><a-button type="primary">查看数据</a-button></div>
</div>
</div>
<!-- 已有数据表 -->
<div class="exist-table-list" v-if="showExistTableList">
</div>
</div>
</a-modal>
</template>
@ -132,29 +187,54 @@
CheckCircleOutlined,
} from '@ant-design/icons-vue';
import './index.scss';
import { InboxOutlined } from '@ant-design/icons-vue';
import { InboxOutlined,CloudUploadOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import type { UploadChangeParam } from 'ant-design-vue';
import type { UploadProps } from 'ant-design-vue';
// import { uploadShp } from '@/api/sys/analysis.ts'
import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import { FILETYPE } from '../util'
import { FILETYPE } from '../util'
import {ObjectToUrl} from '../src/tool'
const dataSource = reactive([
{
"tablename":"monitor"
},
{
"tablename":"monitor0527"
},
])
const columns = reactive([
{
title: '数据表名称',
dataIndex: 'tablename',
key: 'tablename',
},{
title: '选择数据表',
dataIndex: 'operation',
key: 'operation',
}
])
const current = ref(0);
const fileList = ref<UploadProps['fileList']>([]);
const props = defineProps(['openModal']);
const emits = defineEmits(['update:openModal']);
const uploadFrom = reactive({
serverName: '',
serverName: null,
hasFeature:null,
spaceType: null,
tableName: '',
layerType:null,
tableName: null,
});
const formRef = ref();
const dataList = ref([]);
const isShp = ref(false);
const isShp = ref<Boolean>(true);
const showExistTableList = ref<Boolean>(false)
// todo
const columns = [
const tablecolumns = [
{ title: 'Shp原始字段', dataIndex: 'name', key: 'name' },
{ title: '数据类型', dataIndex: 'type', key: 'type' },
{ title: '数据长度', dataIndex: 'length', key: 'length' },
@ -162,44 +242,146 @@ import { FILETYPE } from '../util'
{ title: '中文名称', dataIndex: 'initName', key: 'initName' },
{ title: '操作', dataIndex: 'operation', key: 'operation' },
];
const uploadFormRules = {
serverName: [{ required: true, message: '请输入服务名称', trigger: 'blur' }],
spaceType: [{ required: true, message: '请选择参考系', trigger: 'blur' }],
tableName: [{ required: true, message: '请输入表名', trigger: 'blur' }],
};
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
console.log('beforeUpload',file)
file.type === FILETYPE.ZIP? isShp.value = true: isShp.value = false
const uploadFormRules = reactive({
serverName: [{ required: true, message: '请输入服务名称', trigger: 'blur' }],
hasFeature: [{ required: true, message: '请选择是否有图斑数据', trigger: 'blur' }],
spaceType: [{ required: true, message: '请选择参考系', trigger: 'blur' }],
layerType: [{ required: true, message: '请选数据类型', trigger: 'blur' }],
tableName: [{ required: true, message: '请输入表名', trigger: 'blur' }],
});
const beforeUpload:UploadProps['beforeUpload'] = (file) => {
file.type === FILETYPE.ZIP ? isShp.value = true: isShp.value = false
fileList.value = [file];
return false;
};
const handlerUploadFile = ()=>{
let url = "http://192.168.10.102:9500/api/Files/Upload"
const [proxyFile] = fileList.value
let file = proxyFile.originFileObj
let formData = new FormData();
formData.append('files', file)
// formData.append('serverName',uploadFrom.serverName)
// formData.append('spaceType',uploadFrom.spaceType)
// formData.append('tableName',uploadFrom.tableName)
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)
})
}
const handlerCreateLayer =(filePath)=>{
// upload 20240528\\2024052814563161320172.zip 20240528/2024052814563161320172.zip
filePath = filePath.replace(/\\/,'/');
let addForm = {
filePath:filePath,
tableName:uploadFrom.tableName,
srid:uploadFrom.spaceType
}
let params = ObjectToUrl(addForm);
axios.post("http://192.168.10.102:9500/api/PolygonalShape/CreateGISLayer"+params,{},{headers:{'Content-Type': 'multipart/form-data;charset=UTF-8','X-Token':"95a1a7a8"}}).then(res=>{
console.log("helloworld",res);
})
}
const submitShp = () => {
formRef.value.validate().then(() => {
if(fileList.value?.length < 1){
message.warning('请选择shp文件')
message.warning('请选择需要上传的文件')
return
}
// FormData()
let formData = new FormData();
const [proxyFile] = fileList.value
let file = proxyFile.originFileObj
const [proxyFile] = fileList.value
let file = proxyFile.originFileObj
formData.append('file', file)
formData.append('serverName',uploadFrom.serverName)
formData.append('spaceType',uploadFrom.spaceType)
formData.append('tableName',uploadFrom.tableName)
let url = ""
isShp.value? url = 'http://221.2.83.254:9006/geoserver/uploadFile': url = 'http://221.2.83.254:9006/geoserver/uploadExcelFile'
axios.post(url,formData,{headers: {'Content-Type': 'multipart/form-data;charset=UTF-8'}}).then(res => {
// isShp.value ? url = "http://192.168.10.102:9500/api/Files/Upload" : url = "http://192.168.10.102:9500/api/Files/Upload"
// let data = [
// {
// "length": 1024,
// "name": "name",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "num",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "type",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "shebeiid",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "forestryty",
// "type": "varchar"
// },
// {
// "length": "",
// "name": "geom",
// "type": "geometry"
// },
// {
// "length": 1024,
// "name": "road",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "checksite",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "lng",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "lat",
// "type": "varchar"
// }
// ]
axios.post(url,formData,{headers: {'Content-Type': 'multipart/form-data;charset=UTF-8'}}).then(res => {
let data = res.data.data.heads
let showData = data.map(item => {
return {...item,refName:item.name.toLowerCase(),initName:item.name,key:uuidv4()}
})
dataList.value = showData
current.value++
}).catch(err => {
console.log(err)
})
@ -214,6 +396,7 @@ const closeModal = () => {
fileList.value = []
current.value = 0
}
const deleteListItem = (record) => {
dataList.value = dataList.value.filter(item => item.key !== record.key)
}
@ -230,22 +413,27 @@ const insertListItem = () => {
const submitDataList = () => {
let refRelation = {}
// let refRelation = {}
dataList.value.forEach((item,index)=>{
refRelation[item.refName] = item.initName;
})
// dataList.value.forEach((item,index)=>{
// refRelation[item.refName] = item.initName;
// })
console.log("refRelation",refRelation);
// console.log("refRelation",refRelation);
let exportForm = {
"newHeads": dataList.value,
"refRelation": JSON.stringify(refRelation),
}
// let exportForm = {
// "newHeads": dataList.value,
// "refRelation": JSON.stringify(refRelation),
// }
// console.log(dataList.value)
// current.value++
current.value++
}
//
const handlerGetExistsTableList = (record )=>{
uploadFrom.tableName = record.tablename
}
</script>
@ -336,5 +524,14 @@ const submitDataList = () => {
flex-direction: column;
}
}
.exist-table-list{
width:100%;
height: calc( 100% - 60px);
position:absolute;
top:60px;
left:0px;
background:#fff;
border-radius: 12px;
}
}
</style>

View File

@ -36,7 +36,13 @@
//
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import { generateUUID,getGeometryCenter } from './src/tool'
//
import { SwitchLayerControl,MeasureControl } from 'mapbox-extensions'
import 'mapbox-extensions/dist/index.css'
import U from 'mapbox-gl-utils';
import 'mapbox-gl/dist/mapbox-gl.css';
import './src/index.less';
@ -156,6 +162,23 @@
});
window.handlerCopyFeature = handlerCopyFeature;
map.addControl(new MeasureControl({
horizontal : true, //default false
btnBgColor : '#ffffff', //default '#ffffff'
btnActiveColor:'#ddd', //default '#ddd'
geometryClick:true, //defualt false
enableModes:['Point','LineString','Polygon'],//default all
onStart:()=>{},
onStop:()=>{},
measurePointOptions:{
},
measureLineStringOptions:{
},
measurePolygonOptions:{
}
}),"top-left")
});
});
//
@ -242,57 +265,66 @@
//
const handlerInitDrawTool = (feature, bool) => {
if (feature.features.length > 0) {
feature.features.forEach((item) => {
if (item.geometry.type == 'MultiPolygon') {
let arr: any = ref([]);
item.geometry.coordinates.forEach((val) => {
arr.value.push(val[0]);
});
item.geometry.coordinates = arr.value;
item.geometry.type = 'Polygon';
}
});
}
// if (feature.features.length > 0) {
// feature.features.forEach((item) => {
// if (item.geometry.type == 'MultiPolygon') {
// let arr: any = ref([]);
// item.geometry.coordinates.forEach((val) => {
// arr.value.push(val[0]);
// });
// item.geometry.coordinates = arr.value;
// item.geometry.type = 'Polygon';
// }
// });
// }
geojson.geojson = feature;
console.log('drawTool', drawTool);
console.log('feature', feature);
if (drawTool) {
drawTool.deleteAll();
if (feature.features) {
drawTool.set(geojson.geojson);
geojson.geojson = feature;
if (drawTool) {
drawTool.deleteAll();
if (feature.features) {
drawTool.set(geojson.geojson);
}
} else {
drawTool = new MapboxDraw({
modes: {
...MapboxDraw.modes,
draw_point: SnapPointMode,
draw_polygon: SnapPolygonMode,
draw_line_string: SnapLineMode,
direct_select: SnapDirectSelect,
},
styles: customDrawStyles,
userProperties: true,
snap: true,
snapOptions: {
snapPx: 12, // defaults to 15
snapToMidPoints: true, // defaults to false
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
},
guides: false,
});
map.addControl(drawTool, 'top-right');
if (feature.features) {
drawTool.set(geojson.geojson);
}
}
} else {
drawTool = new MapboxDraw({
modes: {
...MapboxDraw.modes,
draw_point: SnapPointMode,
draw_polygon: SnapPolygonMode,
draw_line_string: SnapLineMode,
direct_select: SnapDirectSelect,
},
styles: customDrawStyles,
userProperties: true,
snap: true,
snapOptions: {
snapPx: 12, // defaults to 15
snapToMidPoints: true, // defaults to false
snapVertexPriorityDistance: 0.0025, // defaults to 1.25
},
guides: false,
});
map.addControl(drawTool, 'top-right');
if (feature.features) {
drawTool.set(geojson.geojson);
}
}
//
if (bool) {
//
// if (bool) {
// drawing.value = true;
// } else {
// drawing.value = false;
// }
drawing.value = true;
} else {
drawing.value = false;
}
};
//
@ -386,7 +418,7 @@
const handlerLocation = (lngLat) => {
map.flyTo({
center: lngLat,
zoom: 16,
zoom: 17,
speed: 10, //
curve: 1, // 线
easing(t) {
@ -476,42 +508,40 @@
const handlerDraw = (features = null, bool = false) => {
console.log("features",features);
let geo = {
type: 'FeatureCollection',
features: [],
};
console.log('features', features);
console.log('bool', bool);
if (features == null) {
bool = true;
} else {
if (features.length > 0) {
for (let i = 0; i < features.length; i++) {
try {
let featureTemp = WktToGeojson(features[i].value);
let feature = {
id: 'cd1d93c0e4a6747ff597f' + parseInt(1000000000 * Math.random()).toString(),
type: 'Feature',
properties: {},
geometry: featureTemp,
id: generateUUID(),
type: 'Feature',
properties: {},
geometry: featureTemp,
};
geo.features.push(feature);
//
if(i == 0){
let lngLat = getGeometryCenter(feature);
handlerLocation(lngLat);
}
} catch (e) {
console.log('WKT解析错误请检查WKT数据格式是否有误');
}
}
}
}
handlerInitDrawTool(geo, bool);
};
defineExpose({
@ -519,6 +549,7 @@
handlerLocation,
handlerCancleDraw,
});
</script>
<style>
@ -526,10 +557,12 @@
width: 100%;
height: 100%;
}
.map-box {
width: 100%;
height: 100%;
}
.layer-control-center {
position: absolute;
padding: 10px;
@ -538,20 +571,23 @@
background: #ffffff;
border-radius: 12px;
}
.layer-control-center p {
margin: 0px;
}
.draw-control-center {
position: absolute;
padding: 7px;
padding: 8px;
top: 15px;
right: 15px;
background: #ffffff;
border-radius: 12px;
}
.draw-control-center .draw-btn {
float: left;
margin: 0px 6px;
margin: 0px 7px;
padding: 5px;
border-radius: 5px;
}
@ -560,9 +596,11 @@
background-color: rgb(0 0 0/5%);
cursor: pointer;
}
.mapboxgl-ctrl-group:not(:empty) {
box-shadow: none;
}
.mapboxgl-ctrl-group {
padding: 10px;
border-radius: 12px;
@ -575,17 +613,20 @@
height: 20px !important;
float: left;
}
.mapboxgl-ctrl-top-right {
}
.mapboxgl-ctrl-group button + button {
border: 0px;
margin: 0px 10px;
margin: 0px 6px;
}
.mapbox-gl-draw_ctrl-draw-btn:hover {
transform: scale(1.2);
}
.mapbox-gl-draw_polygon {
background-image: url(/polygon.png);
background-size: 100% 100%;
@ -603,7 +644,7 @@
background-size: 100% 100%;
width: 100px;
height: 100px;
margin: 0px 10px;
margin: 0px 6px;
}
.mapbox-gl-draw_trash {
@ -626,5 +667,15 @@
width: 100px;
height: 100px;
}
.jas-ctrl-measure{
position:relative;
top:6px;
left:190px;
}
.jas-ctrl-measure-item{
height:22px;
}
</style>

View File

@ -225,70 +225,91 @@
popup.remove();
createMessage.success('复制成功!');
};
</script>
<style>
.mapboxgl-ctrl-group:not(:empty) {
box-shadow: none;
}
.mapboxgl-ctrl-group {
background: none !important;
}
.mapbox-gl-draw_ctrl-draw-btn {
width: 40px !important;
height: 40px !important;
float: left;
border-radius: 50%;
}
.mapboxgl-ctrl-top-right {
}
.mapboxgl-ctrl-group button + button {
border: 0px;
margin: 0px 3px;
}
.mapbox-gl-draw_ctrl-draw-btn:hover {
transform: scale(1.2);
}
.mapbox-gl-draw_polygon {
background-image: url(/polygon.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_point {
background-image: url(/point.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_line {
background-image: url(/line.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_trash {
background-image: url(/del.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_combine {
background-image: url(/combine.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_uncombine {
background-image: url(/uncombine.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.draw-control-center .draw-btn {
float: left;
margin: 0px 6px;
padding: 5px;
border-radius: 5px;
}
.draw-control-center .draw-btn:hover {
background-color: rgb(0 0 0/5%);
cursor: pointer;
}
.mapboxgl-ctrl-group:not(:empty) {
box-shadow: none;
}
.mapboxgl-ctrl-group {
padding: 10px;
border-radius: 12px;
position: relative;
right: 140px;
top: 5px;
}
.mapbox-gl-draw_ctrl-draw-btn {
width: 20px !important;
height: 20px !important;
float: left;
}
.mapboxgl-ctrl-top-right {
}
.mapboxgl-ctrl-group button + button {
border: 0px;
margin: 0px 6px;
}
.mapbox-gl-draw_ctrl-draw-btn:hover {
transform: scale(1.2);
}
.mapbox-gl-draw_polygon {
background-image: url(/polygon.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_point {
background-image: url(/point.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_line {
background-image: url(/line.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
margin: 0px 6px;
}
.mapbox-gl-draw_trash {
background-image: url(/del.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_combine {
background-image: url(/combine.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
.mapbox-gl-draw_uncombine {
background-image: url(/uncombine.png);
background-size: 100% 100%;
width: 100px;
height: 100px;
}
</style>

View File

@ -42,6 +42,7 @@
</a-button>
<a-button type="primary" @click="handlerAddToLayerList">
=======
</a-button> -->
<a-button type="primary">
<template #icon>
@ -86,14 +87,19 @@
</template>
<script setup lang="ts">
import { PlusOutlined } from '@ant-design/icons-vue'
import { errorImage } from '../../util.js'
import { ref,defineEmits } from "vue"
import { ref,defineEmits,reactive } from "vue"
import MapboxMap from '@/components/MapboxMaps/index.vue'
import { DrawingType } from '@/enums/mapEnum';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const emits = defineEmits(["handlerAddToLayerList"])
const data = ref('vector-data')
const sort = ref('default')

View File

@ -8,4 +8,5 @@ const GeojsonToWkt = (geojsonData)=> {
return WKT.convert(geojsonData)
}
export {WktToGeojson,GeojsonToWkt}

View File

@ -1,11 +1,11 @@
// 生成UUID
import { ControlOutlined } from '@ant-design/icons-vue';
import * as turf from '@turf/turf'
// js生成UUID
const generateUUID = ()=>{
var d = new Date().getTime(); //Timestamp
var d2 = (performance && performance.now && (performance.now()*1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16;
if(d > 0) {
@ -19,4 +19,42 @@ const generateUUID = ()=>{
});
}
export { generateUUID }
// js 针对后端post接口参数拼接到url的情况 将json参数转换为 ?key1=value1&key2=value2
const ObjectToUrl = (obj)=>{
let params = "?";
for(let item in obj){
params+=item+"="+obj[item]+"&"
}
return params;
}
// turf获取几何图形的中心
const getGeometryCenter = (geometry)=>{
let coordinates = [];
switch(geometry.geometry.type.toUpperCase()){
case "POINT":
break;
case "MULTIPOINT":
break;
case "LINESTRING":
break;
case "MULTILINESTRING":
break;
case "POLYGON":
coordinates = geometry.geometry.coordinates
break;
case "MULTIPOLYGON":
coordinates = geometry.geometry.coordinates[0]
break;
}
let polygon = turf.polygon(coordinates);
let center = turf.centerOfMass(polygon);
return center.geometry.coordinates;
}
export { generateUUID,ObjectToUrl,getGeometryCenter }

View File

@ -71,13 +71,14 @@
<a-radio-button value="1" @click="handlePostClick(false)"></a-radio-button>
<a-radio-button value="2" @click="handleRoleClick(false)"></a-radio-button>
<a-radio-button value="3" @click="handleAccountClick(false)"></a-radio-button>
<a-radio-button value="3" @click="handleLevelClick(false)"></a-radio-button>
<a-radio-button value="3" @click="handleNodeAuditorClick(false)"
<a-radio-button value="4" @click="handleLevelClick(false)"></a-radio-button>
<a-radio-button value="5" @click="handleNodeAuditorClick(false)"
>节点执行人</a-radio-button
>
<a-radio-button value="3" @click="handleAuditorSqlClick(false)"
<a-radio-button value="6" @click="handleAuditorSqlClick(false)"
>表字段</a-radio-button
>
<a-radio-button value="7" @click="handleSQLClick(false)">SQL</a-radio-button>
</a-radio-group>
</a-space>
<a-table
@ -486,6 +487,15 @@
>
<SelectForm ref="formRef" />
</a-modal>
<a-modal
width="40%"
v-model:open="data.SQLOpen"
title="添加SQL"
@ok="executeSQLHandleOk"
:destroyOnClose="true"
>
<ExecuteSQL ref="executeSQLRef" />
</a-modal>
</div>
</template>
@ -494,7 +504,7 @@
import { SelectPos } from '@/components/SelectPos/index';
import { SelectRole } from '@/components/SelectRole/index';
import { SelectAccount } from '@/components/SelectAccount/index';
import { AuditorLevel, AuditorSql, AuditorNode } from './page';
import { AuditorLevel, AuditorSql, AuditorNode, ExecuteSQL } from './page';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
import { flowStore } from '@/store/modules/flow';
import { SelectForm } from '@/components/SelectForm/index';
@ -601,6 +611,7 @@
formOpen: false,
formVerisons: [],
formName: '',
SQLOpen: false,
});
watch(
@ -642,6 +653,8 @@
return '节点';
case '6':
return '表字段';
case '7':
return 'SQL';
}
}
@ -669,10 +682,14 @@
node.value.lookUsers = node.value.lookUsers.concat(addData2);
updateWfData('lookUsers');
} else {
let addData = selectData.filter(
(t) => node.value.auditUsers.findIndex((t2) => t2.id == t.id && t2.type == t.type) == -1,
);
node.value.auditUsers = node.value.auditUsers.concat(addData);
if (selectData.type == 7) {
node.value.auditUsers.push(selectData);
} else {
let addData = selectData.filter(
(t) => node.value.auditUsers.findIndex((t2) => t2.id == t.id && t2.type == t.type) == -1,
);
node.value.auditUsers = node.value.auditUsers.concat(addData);
}
updateWfData('auditUsers');
}
}
@ -739,6 +756,22 @@
data.nodeOpen = false;
}
}
// SQL
const executeSQLRef = ref<any>();
function handleSQLClick(isLooker) {
nodeId.value = node.value.id;
data.isLooker = isLooker;
data.SQLOpen = true;
}
function executeSQLHandleOk() {
executeSQLRef.value.validateForm();
let obj = executeSQLRef.value.getForm();
if (obj.Sql != '') {
addTableData(obj);
data.SQLOpen = false;
}
}
//
const sqlRef = ref<any>();
@ -889,7 +922,6 @@
obj.fieldName = element.componentProps.fieldName;
fields.push(obj);
} else if (['Grid'].includes(element.component) || element.type == 'subTable') {
console.log('gridtable');
fields.push({
field: `${element.field}_add`,
label: `${element.label || '表格'}-添加按钮`,

View File

@ -1,3 +1,4 @@
export { default as AuditorLevel } from './src/auditorLevel.vue';
export { default as AuditorSql } from './src/auditorSql.vue';
export { default as AuditorNode } from './src/auditorNode.vue';
export { default as ExecuteSQL } from './src/executeSQL.vue';

View File

@ -0,0 +1,56 @@
<template>
<div class="l-from-body">
<a-form
ref="formRef"
:rules="data.rules"
:model="data.formData"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item label="SQL语句" name="Sql">
<a-textarea v-model:value="data.formData.Sql" placeholder="SQL语句" :rows="4" />
</a-form-item>
</a-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
const formRef = ref<any>();
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const data = reactive({
formData: {
Sql: '',
type: '7',
},
rules: {
Sql: [{ required: true, message: '请输入SQL语句' }],
},
});
function validateForm() {
formRef.value
.validate()
.then(async () => {
return true;
})
.catch(async () => {
return false;
});
}
function getForm() {
let rows = data.formData;
rows.name = data.formData.Sql;
return rows;
}
defineExpose({
getForm,
validateForm,
});
</script>
<style scoped>
.l-from-body {
padding: 10px;
}
</style>

View File

@ -1,6 +1,10 @@
import { withInstall } from '@/utils';
import basicUpload from './src/BasicUpload.vue';
import uploadImage from './src/components/ImageUpload.vue';
import uploadVideo from './src/components/VideoUpload.vue';
import uploadFile from './src/components/FileUpload.vue'
export const ImageUpload = withInstall(uploadImage);
export const BasicUpload = withInstall(basicUpload);
export const VideoUpload = withInstall(uploadVideo);
export const FileUpload = withInstall(uploadFile);

View File

@ -0,0 +1,216 @@
<template>
<div>
<UploadDragger
v-bind="$attrs"
:list-type="listType"
:accept="getStringAccept"
:multiple="multiple"
:maxCount="maxNumber"
:before-upload="beforeUpload"
:custom-request="customRequest"
@preview="handlePreview"
@remove="handleRemove"
>
<!-- <div v-if="fileList && fileList.length < maxNumber">
<plus-outlined />
<div style="margin-top: 8px">{{ t('component.upload.upload') }}</div>
</div> -->
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
<p class="ant-upload-hint">
支持单次或批量上传
</p>
</UploadDragger>
<Modal :open="previewOpen" :title="previewTitle" :footer="null" @cancel="handleCancel">
<img alt="" style="width: 100%" :src="previewImage" />
</Modal>
</div>
</template>
<script lang="ts" setup>
import { ref, toRefs, watch } from 'vue';
import { PlusOutlined,InboxOutlined } from '@ant-design/icons-vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
import { Modal, UploadDragger } from 'ant-design-vue';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { useMessage } from '@/hooks/web/useMessage';
import { isArray, isFunction, isObject, isString } from '@/utils/is';
import { warn } from '@/utils/log';
import { useI18n } from '@/hooks/web/useI18n';
import { useUploadType } from '../hooks/useUpload';
import { uploadContainerProps } from '../props';
import { isImgTypeByName } from '../helper';
import { UploadResultStatus } from '@/components/Upload/src/types/typing';
import { fileUploadApi } from '@/api/sys/upload';
defineOptions({ name: 'ImageUpload' });
const emit = defineEmits(['change', 'update:value', 'delete']);
const props = defineProps({
...uploadContainerProps,
});
const { t } = useI18n();
const { createMessage } = useMessage();
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
const isInnerOperate = ref<boolean>(false);
const { getStringAccept } = useUploadType({
acceptRef: accept,
helpTextRef: helpText,
maxNumberRef: maxNumber,
maxSizeRef: maxSize,
});
const previewOpen = ref<boolean>(false);
const previewImage = ref<string>('');
const previewTitle = ref<string>('');
const fileList = ref<UploadProps['fileList']>([]);
const isLtMsg = ref<boolean>(true);
const isActMsg = ref<boolean>(true);
watch(
() => props.value,
(v) => {
if (isInnerOperate.value) {
isInnerOperate.value = false;
return;
}
if (v) {
let value: string[] = [];
if (isArray(v)) {
value = v;
} else {
value.push(v);
}
fileList.value = value.map((item, i) => {
if (item && isString(item)) {
return {
uid: -i + '',
name: item.substring(item.lastIndexOf('/') + 1),
status: 'done',
url: item,
};
} else if (item && isObject(item)) {
return item;
} else {
return;
}
}) as UploadProps['fileList'];
}
},
);
function getBase64<T extends string | ArrayBuffer | null>(file: File) {
return new Promise<T>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result as T);
};
reader.onerror = (error) => reject(error);
});
}
const handlePreview = async (file: UploadFile) => {
console.log("fileEEEEE",file);
if (!file.url && !file.preview) {
file.preview = await getBase64<string>(file.originFileObj!);
}
previewImage.value = file.url || file.preview || '';
previewOpen.value = true;
previewTitle.value =
file.name || previewImage.value.substring(previewImage.value.lastIndexOf('/') + 1);
};
const handleRemove = async (file: UploadFile) => {
if (fileList.value) {
const index = fileList.value.findIndex((item) => item.uid === file.uid);
index !== -1 && fileList.value.splice(index, 1);
const value = getValue();
isInnerOperate.value = true;
emit('change', value);
emit('delete', file);
}
};
const handleCancel = () => {
previewOpen.value = false;
previewTitle.value = '';
};
const beforeUpload = (file: File) => {
const { maxSize, accept } = props;
const { name } = file;
const isAct = isImgTypeByName(name);
if (!isAct) {
createMessage.error(t('component.upload.acceptUpload', [accept]));
isActMsg.value = false;
//
setTimeout(() => (isActMsg.value = true), 1000);
}
const isLt = file.size / 1024 / 1024 > maxSize;
if (isLt) {
createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
isLtMsg.value = false;
//
setTimeout(() => (isLtMsg.value = true), 1000);
}
return (isAct && !isLt) || Upload.LIST_IGNORE;
};
async function customRequest(info: UploadRequestOption<any>) {
const { api,server,action } = props;
// if (!api || !isFunction(api)) {
// return warn('upload api must exist and be a function');
// }
try {
const res = await fileUploadApi?.({
data: {
...(props.uploadParams || {}),
},
file: info.file,
name: props.name,
filename: props.filename,
});
fileList.value?.push({
uid: '-1',
name: info.file.name,
status: 'done',
url: server+"/"+res.data.result[0].filePath,
})
// info.onSuccess!();
const value = getValue();
// isInnerOperate.value = true;
emit('change', value);
} catch (e: any) {
info.onError!(e);
}
console.log("fileList",fileList);
}
function getValue() {
let saveData = "";
fileList.value.forEach((item,index)=>{
item.url?.splice(server,"");
saveData+=item.url+","
})
return saveData;
}
</script>
<style lang="less">
.ant-upload-select-picture-card i {
color: #999;
font-size: 32px;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
</style>

View File

@ -1,11 +1,22 @@
<template>
<div>
<div class="video-item" v-for="(item,index) in fileList" :key="index">
<div class="video-delete-btn" @click="handlerDelete(index)">
<CloseOutlined/>
</div>
<a-image
width="100px"
:src="item.url"
></a-image>
</div>
<Upload
v-bind="$attrs"
v-model:file-list="fileList"
:list-type="listType"
:accept="getStringAccept"
:multiple="multiple"
:showUploadList="false"
:maxCount="maxNumber"
:before-upload="beforeUpload"
:custom-request="customRequest"
@ -17,16 +28,18 @@
<div style="margin-top: 8px">{{ t('component.upload.upload') }}</div>
</div>
</Upload>
<Modal :open="previewOpen" :title="previewTitle" :footer="null" @cancel="handleCancel">
<img alt="" style="width: 100%" :src="previewImage" />
</Modal>
</div>
</template>
<script lang="ts" setup>
import { ref, toRefs, watch } from 'vue';
import { PlusOutlined } from '@ant-design/icons-vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
import { ref, toRefs, watch,reactive, onMounted } from 'vue';
import { PlusOutlined,CloseOutlined } from '@ant-design/icons-vue';
import type { UploadFile, UploadProps,UploadChangeParam } from 'ant-design-vue';
import { Modal, Upload } from 'ant-design-vue';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { useMessage } from '@/hooks/web/useMessage';
@ -37,6 +50,8 @@
import { uploadContainerProps } from '../props';
import { isImgTypeByName } from '../helper';
import { UploadResultStatus } from '@/components/Upload/src/types/typing';
import { actions } from '@/views/demo/page/account/center/data';
import { fileUploadApi } from '@/api/sys/upload';
defineOptions({ name: 'ImageUpload' });
@ -46,29 +61,32 @@
});
const { t } = useI18n();
const { createMessage } = useMessage();
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
const { accept, helpText, maxNumber, maxSize} = toRefs(props);
const isInnerOperate = ref<boolean>(false);
const { getStringAccept } = useUploadType({
acceptRef: accept,
helpTextRef: helpText,
maxNumberRef: maxNumber,
maxSizeRef: maxSize,
maxSizeRef: maxSize
});
const previewOpen = ref<boolean>(false);
const previewImage = ref<string>('');
const previewTitle = ref<string>('');
const fileList = ref<UploadProps['fileList']>([]);
const imageList = reactive([])
const isLtMsg = ref<boolean>(true);
const isActMsg = ref<boolean>(true);
watch(
() => props.value,
(v) => {
() => props.value,(v) => {
if (isInnerOperate.value) {
isInnerOperate.value = false;
return;
}
if (v) {
let value: string[] = [];
if (isArray(v)) {
@ -76,6 +94,7 @@
} else {
value.push(v);
}
fileList.value = value.map((item, i) => {
if (item && isString(item)) {
return {
@ -90,35 +109,75 @@
return;
}
}) as UploadProps['fileList'];
}
let arr = props.value?.split(",") as [];
fileList.value = [];
const { server } = props
arr.forEach((item,index)=>{
if(item){
fileList.value?.push({
uid: '-1',
name: item,
status: 'done',
url: server+item
})
console.log("fileListItem",fileList.value)
}
})
console.log("ImagefileList",fileList.value);
},
);
function getBase64<T extends string | ArrayBuffer | null>(file: File) {
return new Promise<T>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result as T);
};
reader.onerror = (error) => reject(error);
});
}
// function getBase64<T extends string | ArrayBuffer | null>(file: File) {
// return new Promise<T>((resolve, reject) => {
// const reader = new FileReader();
// reader.readAsDataURL(file);
// reader.onload = () => {
// resolve(reader.result as T);
// };
// reader.onerror = (error) => reject(error);
// });
// }
const handlePreview = async (file: UploadFile) => {
const { server } = props
if (!file.url && !file.preview) {
file.preview = await getBase64<string>(file.originFileObj!);
// file.preview = await getBase64<string>(file.originFileObj!);
}
previewImage.value = file.url || file.preview || '';
console.log("file",file);
previewOpen.value = true;
previewTitle.value =
file.name || previewImage.value.substring(previewImage.value.lastIndexOf('/') + 1);
};
// const handleChange = (info: UploadChangeParam) => {
// if (info.file.status === 'uploading') {
// return;
// }
// if (info.file.status === 'done') {
// console.log("donw",info);
// }
// if (info.file.status === 'error') {
// }
// };
const handlerDelete = (index) => {
fileList.value.splice(index,1);
let value = getValue();
emit("change",value);
}
const handleRemove = async (file: UploadFile) => {
if (fileList.value) {
const index = fileList.value.findIndex((item) => item.uid === file.uid);
index !== -1 && fileList.value.splice(index, 1);
const value = getValue();
isInnerOperate.value = true;
emit('change', value);
@ -152,36 +211,58 @@
};
async function customRequest(info: UploadRequestOption<any>) {
const { api } = props;
if (!api || !isFunction(api)) {
return warn('upload api must exist and be a function');
}
const { api,server,action } = props;
// if (!api || !isFunction(api)) {
// return warn('upload api must exist and be a function');
// }
try {
const res = await props.api?.({
const res = await fileUploadApi?.({
data: {
...(props.uploadParams || {}),
},
file: info.file,
name: props.name,
filename: props.filename,
});
info.onSuccess!(res.data);
},server+action);
fileList.value?.push({
uid: '-1',
name: info.file.name,
status: 'done',
url: server+"/"+res.data.result[0].filePath,
})
info.onSuccess!();
const value = getValue();
isInnerOperate.value = true;
// isInnerOperate.value = true;
emit('change', value);
} catch (e: any) {
console.log(e);
info.onError!(e);
}
}
function getValue() {
const list = (fileList.value || [])
.filter((item) => item?.status === UploadResultStatus.DONE)
.map((item: any) => {
return item?.url || item?.response?.url;
});
return props.multiple ? list : list.length > 0 ? list[0] : '';
// fileList.value.forEach((item,index)=>{
// item.url?.splice(server,"");
// saveData+=item.url+","
// })
// return saveData;
let path = "";
const {server} = props;
fileList.value?.forEach((item,index)=>{
path+=item.url?.replace(server,"")+",";
})
return path;
// const list = (fileList.value || [])
// .filter((item) => item?.status === UploadResultStatus.DONE)
// .map((item: any) => {
// return item?.url || item?.response?.url;
// });
// return props.multiple ? list : list.length > 0 ? list[0] : '';
}
</script>
@ -195,4 +276,33 @@
margin-top: 8px;
color: #666;
}
.video-item{
position:relative;
width:100px;
height:100px;
margin-right:10px;
margin-bottom:10px;
float:left;
overflow: hidden;
border-radius: 6px;
background:#fff;
text-align: center;
cursor:pointer;
}
.video-delete-btn{
position:absolute;
top:-5px;
right:-5px;
width:30px;
height:30px;
border-bottom-left-radius: 80%;
background:rgb(0 0 0 / 20%);
color:#fff;
line-height: 30px;
text-align: center;
z-index:999999999999;
}
</style>

View File

@ -187,7 +187,7 @@
item.percent = complete;
},
);
let data = ret != undefined ? ret.data : {};
const { data } = ret;
item.status = UploadResultStatus.SUCCESS;
item.response = data;
return {
@ -206,7 +206,9 @@
//
async function handleStartUpload() {
const { maxNumber } = props;
const { maxNumber,action } = props;
alert(action);
if ((fileListRef.value.length + props.previewFileList?.length ?? 0) > maxNumber) {
return createMessage.warning(t('component.upload.maxNumber', [maxNumber]));
}

View File

@ -0,0 +1,300 @@
<template>
<div>
<div class="video-item" v-for="(item,index) in fileList" :key="index">
<div class="video-delete-btn" @click="handlerDelete(index)">
<CloseOutlined/>
</div>
<img src="./video.png" @click="handlePreview(item)" alt="">
<p>{{ item.name}}</p>
</div>
<Upload
v-bind="$attrs"
:list-type="listType"
:accept="getStringAccept"
:multiple="multiple"
:showUploadList="false"
:maxCount="maxNumber"
:before-upload="beforeUpload"
:custom-request="customRequest"
@preview="handlePreview"
@remove="handleRemove"
>
<div v-if="fileList && fileList.length < maxNumber">
<plus-outlined />
<div style="margin-top: 8px">{{ t('component.upload.upload') }}</div>
</div>
</Upload>
<Modal :open="previewOpen" :title="previewTitle" :footer="null" @cancel="handleCancel">
<!-- <img alt="" style="width: 100%" :src="previewImage" /> -->
<video :src="previewImage" class="video-player" controls muted autoplay></video>
</Modal>
</div>
</template>
<script lang="ts" setup>
import { ref, toRefs, watch,reactive, onMounted } from 'vue';
import { PlusOutlined,CloseOutlined } from '@ant-design/icons-vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
import { Modal, Upload } from 'ant-design-vue';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { useMessage } from '@/hooks/web/useMessage';
import { isArray, isFunction, isObject, isString } from '@/utils/is';
import { warn } from '@/utils/log';
import { useI18n } from '@/hooks/web/useI18n';
import { useUploadType } from '../hooks/useUpload';
import { uploadContainerProps } from '../props';
import { isVideoTypeByName } from '../helper';
import { UploadResultStatus } from '@/components/Upload/src/types/typing';
import { fileUploadApi } from '@/api/sys/upload';
defineOptions({ name: 'VideoUpload' });
const emit = defineEmits(['change', 'update:value', 'delete']);
const props = defineProps({
...uploadContainerProps,
});
const { t } = useI18n();
const { createMessage } = useMessage();
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
const isInnerOperate = ref<boolean>(false);
const { getStringAccept } = useUploadType({
acceptRef: accept,
helpTextRef: helpText,
maxNumberRef: maxNumber,
maxSizeRef: maxSize,
});
const previewOpen = ref<boolean>(false);
const previewImage = ref<string>('');
const previewTitle = ref<string>('');
const fileList = ref<UploadProps['fileList']>([]);
const isLtMsg = ref<boolean>(true);
const isActMsg = ref<boolean>(true);
const showUploadList = reactive({
showRemoveIcon: true,
showPreviewIcon: true
})
watch(
() => props.value,
(v) => {
if (isInnerOperate.value) {
isInnerOperate.value = false;
return;
}
if (v) {
let value: string[] = [];
if (isArray(v)) {
value = v;
} else {
value.push(v);
}
fileList.value = value.map((item, i) => {
if (item && isString(item)) {
return {
uid: -i + '',
name: item.substring(item.lastIndexOf('/') + 1),
status: 'done',
url: item,
};
} else if (item && isObject(item)) {
return item;
} else {
return;
}
}) as UploadProps['fileList'];
}
let arr = props.value?.split(",") as [];
fileList.value = [];
const { server } = props
arr.forEach((item,index)=>{
if(item){
fileList.value?.push({
uid: '-1',
name: item,
status: 'done',
url: server+item
})
console.log("fileListItem",fileList.value)
}
})
console.log("fileList",fileList.value);
},
);
onMounted(()=>{
})
function getBase64<T extends string | ArrayBuffer | null>(file: File) {
return new Promise<T>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result as T);
};
reader.onerror = (error) => reject(error);
});
}
const handlePreview = async (file: UploadFile) => {
previewImage.value = file.url || file.preview || '';
previewOpen.value = true;
previewTitle.value =
file.name || previewImage.value.substring(previewImage.value.lastIndexOf('/') + 1);
};
const handlerDelete = (index) => {
fileList.value.splice(index,1);
let value = getValue();
emit("change",value);
}
const handleRemove = async (file: UploadFile) => {
if (fileList.value) {
const index = fileList.value.findIndex((item) => item.uid === file.uid);
index !== -1 && fileList.value.splice(index, 1);
const value = getValue();
isInnerOperate.value = true;
emit('change', value);
emit('delete', file);
}
};
const handleCancel = () => {
previewOpen.value = false;
previewTitle.value = '';
};
const beforeUpload = (file: File) => {
const { maxSize, accept } = props;
const { name } = file;
const isAct = isVideoTypeByName(name);
if (!isAct) {
createMessage.error(t('component.upload.acceptUpload', [accept]));
isActMsg.value = false;
//
setTimeout(() => (isActMsg.value = true), 1000);
}
const isLt = file.size / 1024 / 1024 > maxSize;
if (isLt) {
createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
isLtMsg.value = false;
//
setTimeout(() => (isLtMsg.value = true), 1000);
}
return (isAct && !isLt) || Upload.LIST_IGNORE;
};
async function customRequest(info: UploadRequestOption<any>) {
const { api,action,server } = props;
// if (!api || !isFunction(api)) {
// return warn('upload api must exist and be a function');
// }
try {
const res = await fileUploadApi?.({
data: {
...(props.uploadParams || {}),
},
file: info.file,
name: props.name,
filename: props.filename,
},server+action);
fileList.value?.push({
uid: '-1',
name: info.file.name,
status: 'done',
url: server+"/"+res.data.result[0].filePath,
})
// info.onSuccess!();
const value = getValue();
isInnerOperate.value = true;
emit('change', value);
} catch (e: any) {
info.onError!(e);
}
}
function getValue() {
const { server } = props;
let saveData = "";
fileList.value.forEach((item,index)=>{
console.log("fileListItem",item);
saveData+=item.url?.replace(server,"")+","
})
return saveData;
}
</script>
<style lang="less" scoped>
.ant-upload-select-picture-card i {
color: #999;
font-size: 32px;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
.video-item{
position:relative;
width:100px;
height:100px;
margin-right:10px;
margin-bottom:10px;
float:left;
overflow: hidden;
border-radius: 6px;
background:#fff;
text-align: center;
cursor:pointer;
}
.video-delete-btn{
position:absolute;
top:-5px;
right:-5px;
width:30px;
height:30px;
border-bottom-left-radius: 80%;
background:rgb(0 0 0 / 20%);
color:#fff;
line-height: 30px;
text-align: center;
}
.video-item img{
width:80px;
height:80px;
}
.video-item p{
overflow: hidden;
color:#777!important;
font-size:12px;
text-overflow:ellipsis;
white-space: nowrap;
}
.ant-upload-wrapper {
width:100px!important;
}
.video-player{
width:500px;
margin:10px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -14,6 +14,11 @@ export function isImgTypeByName(name: string) {
return /\.(jpg|jpeg|png|gif|webp)$/i.test(name);
}
export function isVideoTypeByName(name: string) {
return /\.(mp4|mov|avi)$/i.test(name);
}
export function getBase64WithFile(file: File) {
return new Promise<{
result: string;

View File

@ -24,6 +24,14 @@ export const basicProps = {
type: String as PropType<string>,
default: '',
},
action: {
type: String as PropType<string>,
default: '',
},
server: {
type: String as PropType<string>,
default: '',
},
// 文件最大多少MB
maxSize: {
type: Number as PropType<number>,
@ -54,7 +62,7 @@ export const basicProps = {
},
name: {
type: String as PropType<string>,
default: 'file',
default: 'files',
},
filename: {
type: String as PropType<string>,
@ -64,7 +72,6 @@ export const basicProps = {
type: Boolean,
default: true,
},
fileListDragOptions: {
type: Object as PropType<SortableOptions>,
default: () => ({}),

View File

@ -124,5 +124,9 @@
"redoTip": "点击图片可刷新",
"dragText": "请按住滑块拖动",
"successText": "验证通过"
},
"map":{
"refreshSuccess":"获取位置成功!",
"refreshError":"获取位置失败!"
}
}

View File

@ -14,6 +14,7 @@
import MapboxMaps from '@/components/MapboxMaps/MapboxMap.vue';
// import MapboxMaps from '@/components/MapboxMaps/MapComponent.vue';
import {ref,reactive} from 'vue';
import { DrawingType } from '@/enums/mapEnum';
@ -27,7 +28,7 @@
const layers = reactive([
{
id:1,
name:"沂水县道路中心线1",
name:"沂水县道路中心线",
checked:false,
layer:{
'id': 'roadnetLine1',
@ -58,39 +59,6 @@
'line-width': 1
}
}
},{
id:2,
name:"沂水县道路中心线2",
checked:false,
layer:{
'id': 'roadnetLine2',
'type': 'line',
'source': {
type: 'vector',
tiles: [ 'http://192.168.10.102:9020/api/DroneCaseinfo/QueryVectorTileByTable?z={z}&x={x}&y={y}&table=yishuixian&X-Token=1ded3fe7'],
minzoom: 1,
maxzoom: 20
},
"source-layer": "yishuixian",
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': [
"case",
["==", ["get", "handle_status_id"], 0],
"#E6A23C",
["==", ["get", "handle_status_id"], 1],
"#409EFF",
["==", ["get", "handle_status_id"], 2],
"#67C23A",
//
"#E6A23C",
],
'line-width': 1
}
}
}
])
@ -104,12 +72,11 @@
// const feature ="LINESTRING (118.55483239594203 35.81329409678203, 118.54889167836416 35.806406839795216, 118.55647247134772 35.80285975465173, 118.56157492816281 35.803303140294986)"
// const feature = "POLYGON ((118.54774514802972 35.80786133598188, 118.54515277045988 35.79816597053564, 118.55919536113471 35.80085134034624, 118.56021460056033 35.80462789316549, 118.5595188628206 35.80695604583504, 118.5580066425723 35.80815336506183, 118.54774514802972 35.80786133598188))"
let drawFeatures = [
{
"columnName": "mapgeom",
"value": "POLYGON ((118.55901684631719 35.8045110934671, 118.55946931550466 35.80449259041045, 118.55946551324392 35.80463444717644, 118.559024450841 35.80464061486234, 118.55901684631719 35.8045110934671))"
"value": "MULTIPOLYGON (((118.55901684631719 35.8045110934671, 118.55946931550466 35.80449259041045, 118.55946551324392 35.80463444717644, 118.559024450841 35.80464061486234, 118.55901684631719 35.8045110934671)))"
}, {
"columnName": "mapgeom",
"value": "POLYGON ((118.5591119028685 35.804344565958516, 118.5594579087177 35.804344565958516, 118.55945410645693 35.80424279914757, 118.55910049608158 35.80423663146167, 118.5591119028685 35.804344565958516))"
@ -139,25 +106,21 @@ let drawFeatures = [
setTimeout(function(){
MapboxComponent.value.handlerDraw()
// MapboxComponent.value.handlerDraw()
},6000)
//
setTimeout(function(){
MapboxComponent.value.handlerLocation([118.556717,35.80391]);
},6000)
// setTimeout(function(){
// MapboxComponent.value.handlerLocation([118.556717,35.80391]);
// },6000)
const mapDrawControl: DrawingType[] = [DrawingType.Polygon, DrawingType.Line];
const mapOnLoad = (map) => {
//
// map
console.log('map::: ', map);
// mapU

View File

@ -162,12 +162,38 @@
let subTableId = ref(null);
let subTableData = ref([]);
let subTableList = ref([]);
const setSubTableData = (dataList) => {
dataList.forEach((item) => {
if (item.type === 'subTable') {
subTableId.value = item.field;
let tableData = [];
item.columns.forEach((itemColumn) => {
// if (props.formConfig.schemas) {
// props.formConfig.schemas.forEach((item) => {
// if (item.type === 'subTable') {
// subTableId.value = item.field;
// let tableData = [];
// item.columns.forEach((itemColumn) => {
// itemColumn.children.forEach((itemColumnChild) => {
// tableData.push(itemColumnChild);
// subTableColumns.value.push({
// key: itemColumnChild.field,
// title: itemColumnChild.label,
// dataIndex: itemColumnChild.field,
// width: 120,
// ...itemColumnChild,
// });
// });
// });
// scrollValue.value = { x: (subTableColumns.value.length - 1) * 140, y: 300 };
// subTableData.value = tableData;
// }else{
// }
// });
// }
console.log("props.schema",props.schema)
if (props.schema) {
if(props.schema.type === "subTable"){
subTableId.value = props.schema.field
let tableData = [];
props.schema.columns.forEach((itemColumn) => {
itemColumn.children.forEach((itemColumnChild) => {
tableData.push(itemColumnChild);
subTableColumns.value.push({
@ -181,14 +207,7 @@
});
scrollValue.value = { x: (subTableColumns.value.length - 1) * 140, y: 300 };
subTableData.value = tableData;
}else if(item.columns){
setSubTableData(item.columns[0].children)
}
})
}
if (props.formConfig.schemas) {
setSubTableData(props.formConfig.schemas)
}
}
const addListItem = () => {
@ -207,6 +226,9 @@
const delListItem = (column, record) => {
subTableList.value = subTableList.value.filter((item) => item.key != record.key);
};
</script>
<style>

View File

@ -94,7 +94,7 @@
/>
</FormItem>
<FormItem label="脚本" v-if="['Button'].includes(formConfig.currentItem.component)">
<a-button type="primary" size="mini" @click="handleButtonClick"> </a-button>
<a-button size="mini" @click="handleButtonClick"> </a-button>
</FormItem>
<FormItem
@ -283,9 +283,9 @@
watch(
() => formConfig.value.currentItem?.field,
(_newValue, oldValue) => {
currentIndex.value = formConfig.value.schemas.findIndex(
(element) => element.field === formConfig.value.currentItem.field,
);
// currentIndex.value = formConfig.value.schemas.findIndex(
// (element) => element.field === formConfig.value.currentItem.field,
// );
formConfig.value.schemas &&
formItemsForEach(formConfig.value.schemas, (item) => {
if (item.link) {
@ -310,9 +310,9 @@
() => formConfig.value.currentItem && formConfig.value.currentItem.component,
() => {
// console.log(formConfig.value);
currentIndex.value = formConfig.value.schemas.findIndex(
(element) => element.field === formConfig.value.currentItem.field,
);
// currentIndex.value = formConfig.value.schemas.findIndex(
// (element) => element.field === formConfig.value.currentItem.field,
// );
allOptions.value = [];
baseComponentControlAttrs.forEach((item) => {
item.category = 'control';
@ -378,7 +378,8 @@
let arr = allOptions.value.filter((item) => {
return item.category == 'input';
});
console.log(arr);
console.log(currentIndex.value);
arr.forEach((item) => {
if (item.name == 'dataTable') {
if (currentIndex.value == -1) {

View File

@ -76,7 +76,6 @@
<a-space direction="vertical">
<a-button
v-model:value="formConfig.beforeSetData"
type="primary"
size="mini"
@click="handleBtnClick('beforeSetData')"
>
@ -84,7 +83,6 @@
</a-button>
<a-button
v-model:value="formConfig.afterValidateForm"
type="primary"
size="mini"
@click="handleBtnClick('afterValidateForm')"
>
@ -92,7 +90,6 @@
</a-button>
<a-button
v-model:value="formConfig.afterSaveEvent"
type="primary"
size="mini"
@click="handleBtnClick('afterSaveEvent')"
>
@ -100,7 +97,6 @@
</a-button>
<a-button
v-model:value="formConfig.changeDataEvent"
type="primary"
size="mini"
@click="handleBtnClick('changeDataEvent')"
>
@ -209,11 +205,9 @@
}
//
function handleSubmit() {
if (formContent.value.indexOf('=>') != -1) {
//
message.warning('脚本没有更新为最新的版本!');
if (!checkChinese(formContent.value)) {
message.warning('脚本的代码部分不能含有中文字符!');
return;
// } else if() {
}
if (btnClickEvent_now) {
if (btnClickEvent_now == 'beforeSetData') {
@ -228,6 +222,33 @@
}
closeModal();
}
function checkChinese(str) {
//
const lines = str.split('\n');
let flag = true;
//
for (const line of lines) {
// console.log
const consoleIndex = line.indexOf('console.log');
let partToCheck = line;
if (consoleIndex !== -1) {
partToCheck = line.substring(0, consoleIndex).trim(); // console.log
}
// '//'
const commentIndex = partToCheck.indexOf('//');
// '//''//'
partToCheck =
commentIndex !== -1 ? partToCheck.substring(0, commentIndex).trim() : partToCheck;
//
if (!/[\u4e00-\u9fa5]/.test(partToCheck)) {
flag = false;
}
}
return flag;
}
</script>
<style scoped>

View File

@ -1146,6 +1146,57 @@ const componentAttrs: IBaseComponentProps = {
component: 'Input',
},
],
ImageUpload: [
{
name: 'server',
label: '文件服务器地址',
component: 'Input',
},
{
name: 'action',
label: '文件上传接口',
component: 'Input',
},
{
name: 'name',
label: '附件参数名',
component: 'Input',
},
],
VideoUpload: [
{
name: 'server',
label: '文件服务器地址',
component: 'Input',
},
{
name: 'action',
label: '文件上传接口',
component: 'Input',
},
{
name: 'name',
label: '附件参数名',
component: 'Input',
},
],
FileUpload: [
{
name: 'server',
label: '文件服务器地址',
component: 'Input',
},
{
name: 'action',
label: '文件上传接口',
component: 'Input',
},
{
name: 'name',
label: '附件参数名',
component: 'Input',
},
],
// ColorPicker: [
// {
// name: 'defaultValue',

View File

@ -64,6 +64,7 @@
* @param jsonData
*/
const showModal = (jsonData: IFormConfig) => {
console.log("formModel",state.formModel);
console.log('showModal-', jsonData);
formatRules(jsonData.schemas);
state.formConfig = jsonData as any;

View File

@ -5,7 +5,7 @@ import { IVFormComponent } from '../typings/v-form-component';
import { isArray } from 'lodash-es';
import { componentMap as VbenCmp, add } from '@/components/Form/src/componentMap';
import { ComponentType } from '@/components/Form/src/types';
import { uploadApi,fileUploadApi } from '@/api/sys/upload';
import { componentMap as Cmp } from '../components';
import { Component } from 'vue';
import { getDeptList, getAccountList, getPosGroupList } from '@/api/demo/system';
@ -532,7 +532,63 @@ export const baseComponents: IVFormComponent[] = [
colProps: { span: 24 },
field: '',
componentProps: {},
},
},{
component: 'FileUpload',
label: '文件上传',
icon: 'ant-design:file-add-outlined',
field: '',
colProps: { span: 24 },
componentProps: {
api:uploadApi,
maxNumber:10,
maxSize: 2,
name:"files",
action:"/api/Files/Upload",
server:"http://221.2.83.254:9001"
},
},{
component: 'ImageUpload',
label: '图片上传',
icon: 'ant-design:file-image-outlined',
field: '',
colProps: { span: 24 },
componentProps: {
api:fileUploadApi,
maxNumber:10,
accept: ['png', 'jpeg', 'jpg'],
maxSize: 2,
name:"files",
action:"/api/Files/Upload",
server:"http://192.168.10.102:9023"
},
},{
component: 'VideoUpload',
label: '视频上传',
icon: 'ant-design:video-camera-outlined',
field: '',
colProps: { span: 24 },
componentProps: {
api:fileUploadApi,
maxNumber:10,
accept: ['mp4', 'mov', 'avi'],
maxSize: 100,
name:"files",
action:"/api/Files/Upload",
server:"http://192.168.10.102:9023"
},
},{
component: 'Location',
label: '获取位置',
icon: 'ant-design:environment-outlined',
field: '',
colProps: { span: 24 },
componentProps: {
api:()=>1,
maxNumber:10,
accept: ['mp4', 'mov', 'avi'],
maxSize: 100,
},
}
];
// https://next.antdv.com/components/transfer-cn

View File

@ -14,7 +14,12 @@
<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" />
<BasicForm
ref="myDataBaseFormRef"
@register="registerForm"
@click="codeClickFunction('beforeSetData', beforeSetData)"
@change="codeClickFunction('changeDataEvent', changeDataEvent)"
/>
</a-tab-pane>
</a-tabs>
</template>
@ -23,6 +28,8 @@
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%">
@ -44,6 +51,20 @@
</a-col>
</a-row>
</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"
@ -86,6 +107,7 @@
import { v4 as uuidv4 } from 'uuid';
import FormItem from './ShowFormModal/FormItem/index.vue';
import CallModalFormItem from './CallModalFormItem/index.vue';
// import FormRender from '@/views/demo/form-design/components/VFormCreate/components/FormRender.vue';
const emit = defineEmits(['success']);
@ -112,8 +134,21 @@
const scrollValue = ref();
const cardLayout = ref([]);
const createOrModifyList = ref([]);
//
const buttonLayout = ref([]);
//
const beforeSetData = ref('');
const afterValidateForm = ref('');
const afterSaveEvent = ref('');
const changeDataEvent = ref('');
const [registerModal, { setModalProps, closeModal }] = useModalInner((data: any) => {
console.log('daaaaa', data);
//
beforeSetData.value = data?.beforeSetData;
afterValidateForm.value = data?.afterValidateForm;
afterSaveEvent.value = data?.afterSaveEvent;
changeDataEvent.value = data?.changeDataEvent;
isUpdate.value = !!data?.isUpdate;
isDetail.value = !!data?.isDetail;
const arr: FormSchema[] = [];
@ -133,6 +168,9 @@
if (opt.component === 'Card') {
cardLayout.value.push(opt);
}
if (opt.component === 'Button') {
buttonLayout.value.push(opt);
}
if (['createuser', 'createtime', 'modifyuser', 'modifytime'].includes(opt.type)) {
createOrModifyList.value.push(opt);
}
@ -163,6 +201,20 @@
scrollValue.value = { x: (subTableColumns.value.length - 1) * 140, y: 300 };
subTableData.value = tableData;
}
if (opt.columns) {
opt.columns.forEach((itemColumn) => {
itemColumn.children.forEach((itemColumnChild) => {
console.log('itemColumnChild', itemColumnChild);
itemColumnChild.itemProps.hidden = true;
if (index == 0) {
itemColumnChild.itemProps.hidden = false;
}
arr.push(itemColumnChild);
val.children.push(itemColumnChild);
});
});
}
opt.itemProps.hidden = true;
if (index == 0) {
opt.itemProps.hidden = false;
@ -173,6 +225,7 @@
});
tabsColumns.value = item.componentProps.options;
console.log('tabsColumns', tabsColumns.value);
console.log('formColumns', formColumns.value);
} else {
if (item.rules !== undefined) {
let myString = item.rules[0].pattern;
@ -188,6 +241,9 @@
if (item.component === 'Card') {
cardLayout.value.push(item);
}
if (item.component === 'Button') {
buttonLayout.value.push(item);
}
if (['createuser', 'createtime', 'modifyuser', 'modifytime'].includes(item.type)) {
createOrModifyList.value.push(item);
}
@ -272,14 +328,14 @@
console.log('eee', e);
console.log('tabsColumns', tabsColumns);
const columns: FormSchema[] = [];
// tabsColumns.value.forEach((item) => {
// item.children.forEach((val) => {
// val.itemProps.hidden = true;
// });
// });
// tabsColumns.value[e].children.forEach((item) => {
// item.itemProps.hidden = false;
// });
tabsColumns.value.forEach((item) => {
item.children.forEach((val) => {
val.itemProps.hidden = true;
});
});
tabsColumns.value[e].children.forEach((item) => {
item.itemProps.hidden = false;
});
tabsColumns.value.forEach((item) => {
item.children.forEach((val) => {
columns.push(val);
@ -287,10 +343,16 @@
});
console.log('columns', columns);
console.log('formColumns', formColumns);
const obj = getFieldsValue();
console.log('values', getFieldsValue());
// resetFields();
setTimeout(() => {
updateSchema(columns);
console.log('values', getFieldsValue());
resetFields();
}, 100);
setTimeout(() => {
setFieldsValue(obj);
}, 500);
}
function generateUniqueDigits(length: number): number[] {
const digits = new Set<number>();
@ -328,18 +390,20 @@
async function ModalSureClick() {
try {
const values = await validate();
//
codeClickFunction('afterValidateForm', afterValidateForm.value);
console.log('values', values);
let query = values;
let saveSubTableList = [];
// subTableList.value.forEach((item) => {
// let emptyObj = {};
// for (const key in item) {
// if (key === 'key') continue;
// emptyObj[key] = item[key];
// }
// saveSubTableList.push(emptyObj);
// });
// query[subTableId.value] = JSON.stringify(saveSubTableList);
subTableList.value.forEach((item) => {
let emptyObj = {};
for (const key in item) {
if (key === 'key') continue;
emptyObj[key] = item[key];
}
saveSubTableList.push(emptyObj);
});
query[subTableId.value] = JSON.stringify(saveSubTableList);
let params: any = {
schemeId: primaryQuery.value.id,
isUpdate: isUpdate.value,
@ -376,6 +440,9 @@
}
} finally {
setModalProps({ confirmLoading: false });
//
codeClickFunction('afterSaveEvent', afterSaveEvent.value);
closeFunc();
}
}
async function handleCreateFlow(processId) {
@ -399,7 +466,37 @@
return createMessage.error('保存草稿失败');
}
}
//
async function codeClickFunction(code, codeClick) {
try {
// utils
const { utils } = await import('./utils');
eval(codeClick);
} catch (e) {
switch (code) {
case 'codeClick':
createMessage.success('【按钮组件脚本】错误:' + e);
break;
case 'beforeSetData':
createMessage.success('【添加赋值前脚本】错误:' + e);
break;
case 'afterValidateForm':
createMessage.success('【添加校验后脚本】错误:' + e);
break;
case 'afterSaveEvent':
createMessage.success('【添加保存后脚本】错误:' + e);
break;
case 'changeDataEvent':
createMessage.success('【添加数据改变脚本】错误:' + e);
break;
default:
createMessage.success('【未知脚本】错误:' + e);
break;
}
}
}
const closeFunc = () => {
buttonLayout.value = [];
cardLayout.value = [];
createOrModifyList.value = [];
return true;

View File

@ -19,6 +19,7 @@
ref="formBoxRef"
:formConfig="formConfig"
:flowFormData="props.flowFormData"
:formVerison="designerData.formCurrentNode.formVerison"
v-if="formVisble"
/>
</a-tab-pane>
@ -257,10 +258,12 @@
});
if (data) {
const scheme = JSON.parse(data.scheme);
scheme.formInfo.schemas.forEach((element) => {
if (element.field == designerData.formCurrentNode.formRelationId) {
keyValue.value = element.componentProps.fieldName;
}
scheme.formInfo.tabList.forEach((tabElement) => {
tabElement.schemas.forEach((element) => {
if (element.field == designerData.formCurrentNode.formRelationId) {
keyValue.value = element.componentProps.fieldName;
}
});
});
}
}

View File

@ -186,6 +186,7 @@
getTitle.value = '新增';
data.btnList.forEach((element) => {
if (element.prop === 'Add' && element.isWFlow) {
alert("Add");
flowCode.value = element.wFlowCode;
}
});

View File

@ -321,7 +321,7 @@
let chlidKey: any = ref();
if (val.type === 'chlid') {
getOutKeyList(params).then((res: Recordable) => {
console.log('ressss', res)
console.log('ressss', res);
if (res[0]) {
res[0].db_codecolumnsList.forEach((item) => {
if (item.isPrimaryKey == 1) {
@ -332,9 +332,9 @@
});
}
setTimeout(() => {
console.log('chlidKey', chlidKey.value)
console.log('chlidKey', chlidKey.value);
}, 500);
if (rel.formInfo.schemas.length > 1) {
rel.formInfo.schemas.forEach((item) => {
if (
@ -408,6 +408,10 @@
},
activeKey: 1,
status: 'Add',
beforeSetData: '',
afterValidateForm: '',
afterSaveEvent: '',
changeDataEvent: '',
});
const handleClickForm = (status) => {
@ -431,7 +435,7 @@
if (rows.length > 0) {
query.value.keyValue = rows[0][str.value];
}
console.log('config', config)
console.log('config', config);
switch (status) {
case 'Add':
btnList.value.forEach((element) => {
@ -448,6 +452,10 @@
query: query.value,
addParams: addParamsArr.value,
btnList: btnList.value,
beforeSetData: config.beforeSetData,
afterValidateForm: config.afterValidateForm,
afterSaveEvent: config.afterSaveEvent,
changeDataEvent: config.changeDataEvent,
};
if (haveMap.value) {
showFormModalData.value = toProps;
@ -482,6 +490,10 @@
recordChildren: formData.value,
query: query.value,
btnList: btnList.value,
beforeSetData: config.beforeSetData,
afterValidateForm: config.afterValidateForm,
afterSaveEvent: config.afterSaveEvent,
changeDataEvent: config.changeDataEvent,
};
if (haveMap.value) {
showFormModalData.value = toProps;
@ -612,6 +624,7 @@
layerFields: {},
};
}
console.log('columnObj', columnObj)
paramsId.value = res.formScheme.id;
btnList.value = columnObj.table.btns;
if (columnObj.table.columns) {
@ -651,6 +664,11 @@
unref(asyncExpandTreeRef)?.expandAll(true);
});
formConfig.value.schemas = formObj.formInfo.schemas;
//
formConfig.value.beforeSetData = formObj.formInfo.beforeSetData;
formConfig.value.afterValidateForm = formObj.formInfo.afterValidateForm;
formConfig.value.afterSaveEvent = formObj.formInfo.afterSaveEvent;
formConfig.value.changeDataEvent = formObj.formInfo.changeDataEvent;
});
}
//

View File

@ -0,0 +1,9 @@
// utils.ts
export const utils = {
add: function add(a: number, b: number): number {
return a + b;
},
subtract: function subtract(a: number, b: number): number {
return a - b;
},
};

View File

@ -213,9 +213,19 @@
const arr: any = [];
formScheme.value.formInfo.tabList.forEach((item, index) => {
item.schemas.forEach((val) => {
arr.push(val);
if (val.type == 'subTable' && val.columns) {
console.log('val', val)
val.columns.forEach((col) => {
col.children.forEach((chil) => {
arr.push(chil);
});
});
} else {
arr.push(val);
}
});
});
console.log('item.columns', arr)
formScheme.value.formInfo.schemas = arr;
}
if (formScheme.value.formInfo.tabList && formScheme.value.formInfo.tabList.length == 1) {

View File

@ -154,6 +154,7 @@
let query: any = { keyValue: record.schemeId };
const preview: any = await functionGetPreviewForm(query);
let scheme = JSON.parse(preview.scheme);
console.log('scheme1111', scheme);
if (scheme.formInfo.tabList && scheme.formInfo.tabList.length > 1) {
const arr: any = [];
scheme.formInfo.tabList.forEach((item, index) => {

View File

@ -152,6 +152,7 @@
let tableData = await getTableColumnData(schems);
let tabArr: any = [];
let tabLabelArr: any = [];
console.log('beforedesignTab', designTab);
designTab.schemas.forEach((item) => {
if (item.component !== 'Tabs') {
if (item.componentProps.defaultValue) {
@ -193,7 +194,7 @@
}
// csType
if (list.type == 'subTable') {
list.columns = changeCloums(item.columns, tableData);
list.columns = changeCloums(list.columns, tableData);
}
tabArr.push(list.componentProps.fieldName);
if (!list.componentProps.fieldName) {