feat(X-Pack): 数据填报批量上传数据

This commit is contained in:
ulleo 2024-08-13 14:46:39 +08:00
parent b045ad9b35
commit ab6b49791a
17 changed files with 241 additions and 251 deletions

View File

@ -1,7 +1,7 @@
package io.dataease.config;
import com.fit2cloud.autoconfigure.QuartzAutoConfiguration;
import io.dataease.commons.utils.CommonThreadPool;
import io.dataease.utils.CommonThreadPool;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@ -1,7 +1,6 @@
package io.dataease.datasource.provider;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.dataease.commons.utils.CommonThreadPool;
import io.dataease.dataset.utils.FieldUtils;
import io.dataease.datasource.dao.auto.entity.CoreDatasource;
import io.dataease.datasource.dao.auto.entity.CoreDriver;
@ -16,10 +15,7 @@ import io.dataease.extensions.datasource.provider.ExtendedJdbcClassLoader;
import io.dataease.extensions.datasource.provider.Provider;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import io.dataease.i18n.Translator;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.CommonBeanFactory;
import io.dataease.utils.JsonUtil;
import io.dataease.utils.LogUtil;
import io.dataease.utils.*;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.apache.calcite.adapter.jdbc.JdbcSchema;

View File

@ -14,7 +14,6 @@ import io.dataease.api.ds.vo.CoreDatasourceTaskLogDTO;
import io.dataease.api.ds.vo.ExcelFileData;
import io.dataease.api.ds.vo.ExcelSheetData;
import io.dataease.commons.constants.TaskStatus;
import io.dataease.commons.utils.CommonThreadPool;
import io.dataease.constant.LogOT;
import io.dataease.constant.LogST;
import io.dataease.dataset.manage.DatasetDataManage;

View File

@ -1,226 +0,0 @@
import request from '@/config/axios'
import dayjs from 'dayjs'
export function formatDate(value, dateType) {
if (!value) {
return value
}
switch (dateType) {
case 'year':
return dayjs(value).format('YYYY')
case 'month':
case 'monthrange':
return dayjs(value).format('YYYY-MM')
case 'datetime':
case 'datetimerange':
return dayjs(value).format('YYYY-MM-DD HH:mm:ss')
default:
return dayjs(value).format('YYYY-MM-DD')
}
}
export interface ColumnItem {
props: string
label: string
date: boolean
dateType?: string
type: string
multiple: boolean
rangeIndex?: number
disabled?: boolean
}
export interface DataFillingOrFolder {
name: string
action?: string
id?: number | string
pid?: number | string
nodeType: 'folder' | 'data-filling'
union?: Array<{}>
allFields?: Array<{}>
}
export interface Tree {
name: string
value?: string | number
id: string | number
nodeType: string
createBy?: string
level: number
leaf?: boolean
pid: string | number
type?: string
createTime: number
children?: Tree[]
request: any
}
export interface DfFormSetting {
id?: string
name?: string
pid?: string
datasource?: string
tableName?: string
forms: Array<DfFormItem>
createIndex: boolean
tableIndexes: Array<any>
creator?: string
updater?: string
createTime?: number
updateTime?: number
weight?: number
}
export interface DfFormItem {
type: string
typeName: string
icon: string
order?: number
value?: any
id?: string
settings: FormItemSetting
old?: boolean
removed?: boolean
}
export interface FormItemSetting {
name?: string
placeholder?: string
required?: boolean
unique?: boolean
inputType?: string
optionSourceType?: 1 | 2
optionDatasource?: number
optionTable?: string
optionColumn?: string
optionOrder?: string
multiple?: boolean
dateType?: 'date' | 'daterange'
rangeSeparator?: string
startPlaceholder?: string
endPlaceholder?: string
options?: Array<FormItemSettingOptions>
mapping: {
columnName?: string
columnName1?: string
columnName2?: string
type?: string
}
}
export interface FormItemSettingOptions {
name: string
value: string
}
export interface SimpleDatasource {
id: string
pid: string
name: string
type: string
typeAlias: string
status: string
enableDataFill: boolean
}
export const listDataFillingForms = async (data): Promise<any> => {
return request
.post({ url: '/data-filling/tree', data: { ...data, ...{ busiFlag: 'data-filling' } } })
.then(res => {
return res?.data
})
}
export const createFolder = (data = {}): Promise<any> => {
return request
.post({ url: '/data-filling/save', data: { ...data, nodeType: 'folder' } })
.then(res => {
return res?.data
})
}
export const save = (data = {}): Promise<any> => {
return request.post({ url: '/data-filling/save', data }).then(res => {
return res?.data
})
}
export const move = (data = {}): Promise<any> => {
return request.post({ url: '/data-filling/move', data }).then(res => {
return res?.data
})
}
export const reName = (data = {}): Promise<any> => {
return request.post({ url: '/data-filling/rename', data }).then(res => {
return res?.data
})
}
export const listDatasourceList = (): Promise<Array<SimpleDatasource>> => {
return request.get({ url: '/data-filling/datasource/list' }).then(res => {
return res?.data
})
}
export const getDataFilling = async (id: string): Promise<any> => {
return request.get({ url: `/data-filling/get/${id}` }).then(res => {
return res?.data
})
}
export const deleteById = (id: string): Promise<any> => {
return request.get({ url: '/data-filling/delete/' + id })
}
export const deleteRowData = (formId: string, id: number): Promise<any> => {
return request.get({ url: `/data-filling/form/${formId}/delete/${id}` })
}
export const batchDeleteRowData = (formId: string, data: Array<any>): Promise<any> => {
return request.post({ url: `/data-filling/form/${formId}/batch-delete`, data })
}
export const getTableColumnData = (
optionDatasource,
optionTable,
optionColumn,
optionOrder
): Promise<any> => {
return request.post({
url: `/data-filling/form/${optionDatasource}/options`,
data: {
optionTable: optionTable,
optionColumn: optionColumn,
optionOrder: optionOrder
}
})
}
export const searchTable = (id, data): Promise<any> => {
return request.post({
url: '/data-filling/form/' + id + '/tableData',
data
})
}
export const saveFormRowData = (formId, data): Promise<any> => {
return request
.post({
url: '/data-filling/form/' + formId + '/rowData/save',
data
})
.then(res => {
return res?.data
})
}
export const saveTask = (data): Promise<any> => {
return request.post({
url: `/data-filling/task/save`,
data
})
}
export const getTaskInfo = (taskId): Promise<any> => {
return request.get({
url: `/data-filling/task/info/${taskId}`
})
}

View File

@ -376,6 +376,7 @@ export default {
commit_time: 'Commit Time',
confirm_delete: 'Confirm delete?',
add_data: 'Add Data',
batch_upload: 'Upload Data',
download_template: 'Download Template',
insert_data: 'Insert Data',
update_data: 'Update Data',

View File

@ -277,6 +277,7 @@ export default {
commit_time: '提交時間',
confirm_delete: '確認刪除?',
add_data: '添加數據',
batch_upload: '批量上傳',
download_template: '下載模板',
insert_data: '插入數據',
update_data: '更新數據',

View File

@ -2707,6 +2707,7 @@ export default {
commit_time: '提交时间',
confirm_delete: '确认删除?',
add_data: '添加数据',
batch_upload: '批量上传',
download_template: '下载模板',
insert_data: '插入数据',
update_data: '更新数据',

View File

@ -7,7 +7,6 @@ import type { BusiTreeRequest, BusiTreeNode } from '@/models/tree/TreeNode'
import { pathValid } from '@/store/modules/permission'
import { useCache } from '@/hooks/web/useCache'
import { useAppStoreWithOut } from '@/store/modules/app'
import { listDataFillingForms } from '@/api/data-filling'
const appStore = useAppStoreWithOut()
const { wsCache } = useCache()
export interface InnerInteractive {
@ -22,9 +21,9 @@ interface InteractiveState {
data: Record<number, InnerInteractive>
}
const apiMap = [queryTreeApi, queryTreeApi, getDatasetTree, listDatasources, listDataFillingForms]
const apiMap = [queryTreeApi, queryTreeApi, getDatasetTree, listDatasources]
const busiFlagMap = ['dashboard', 'dataV', 'dataset', 'datasource', 'data-filling']
const busiFlagMap = ['dashboard', 'dataV', 'dataset', 'datasource']
export const interactiveStore = defineStore('interactive', {
state: (): InteractiveState => ({

View File

@ -1,10 +1,16 @@
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
defineProps({
name: propTypes.string.def(''),
size: propTypes.number.def(0),
showDel: propTypes.bool.def(false)
})
const props = withDefaults(
defineProps<{
name?: string
size?: number
showDel?: boolean
}>(),
{
name: '',
size: 0,
showDel: false
}
)
const emits = defineEmits(['del'])
const del = () => {

@ -1 +1 @@
Subproject commit f02fc6a6f62bad5b32f2ac70111ea66dcf6c9dd9
Subproject commit 02f340953f92c485ea48229baf5ae73e59033301

View File

@ -12,10 +12,8 @@ import io.dataease.extensions.datasource.dto.SimpleDatasourceDTO;
import io.dataease.model.BusiNodeRequest;
import io.dataease.model.BusiNodeVO;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
@ -110,4 +108,12 @@ public interface DataFillingApi {
IPage<DfCommitLog> taskPager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody DfCommitLogRequest request);
@PostMapping("/form/{formId}/uploadFile")
DfExcelData excelUpload(@RequestParam("file") MultipartFile file, @PathVariable("formId") Long formId) throws Exception;
@GetMapping("/form/{formId}/excelTemplate")
void excelTemplate(@PathVariable("formId") Long formId);
@PostMapping("/form/{formId}/confirmUpload")
void confirmUpload(@PathVariable("formId") Long formId, @RequestBody Map<String, String> data);
}

View File

@ -1,8 +1,10 @@
package io.dataease.api.xpack.dataFilling.dto;
import lombok.Getter;
import lombok.Data;
import lombok.experimental.Accessors;
@Getter
@Data
@Accessors(chain = true)
public class DatasourceOptionsRequest {
private String optionTable;

View File

@ -0,0 +1,26 @@
package io.dataease.api.xpack.dataFilling.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
public class DfExcelData implements Serializable {
@Serial
private static final long serialVersionUID = 1162581256875641808L;
private List<ExtTableField> formFields;
private List<RowDataDatum> dataList;
private String id;
private String excelName;
private String path;
private String suffix;
}

View File

@ -0,0 +1,155 @@
package io.dataease.api.xpack.dataFilling.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExtTableField implements Serializable {
@Serial
private static final long serialVersionUID = 9021129395822053871L;
private String type;
private String typeName;
private String icon;
private String id;
private ExtTableFieldSetting settings;
private boolean removed;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ExtTableFieldSetting implements Serializable {
@Serial
private static final long serialVersionUID = 8776508642526681125L;
private String name;
private boolean required;
private ExtTableFieldMapping mapping;
private String rangeSeparator;
private boolean unique;
private String inputType;
private String dateType;
private String placeholder;
private String startPlaceholder;
private String endPlaceholder;
private Integer optionSourceType;
@JsonSerialize(using = ToStringSerializer.class)
private Long optionDatasource;
private String optionTable;
private String optionColumn;
private String optionOrder;
private boolean multiple;
private boolean updateRuleCheck;
private List<Option> options;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class Option implements Serializable {
@Serial
private static final long serialVersionUID = -1681618296840344071L;
private String name;
private Object value;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ExtTableFieldMapping implements Serializable {
@Serial
private static final long serialVersionUID = 4233066732126872840L;
private String columnName;
//dateRange下对应两个字段
private String columnName1;
private String columnName2;
private String oldColumnName;
private String oldColumnName1;
private String oldColumnName2;
private BaseType type;
//长度
private Integer size;
//精度
private Integer accuracy;
}
public enum BaseType {
nvarchar, //字符串
text, //长文本
number, //整型数字
decimal, //小数数字
datetime //日期
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class TableField implements Serializable {
@Serial
private static final long serialVersionUID = 85092190247927362L;
private String columnName;
private String oldColumnName;
private BaseType type;
private boolean required;
private boolean primaryKey;
//长度
private Integer size;
//精度
private Integer accuracy;
private String comment;
}
}

View File

@ -0,0 +1,23 @@
package io.dataease.api.xpack.dataFilling.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.util.Map;
@Data
@Accessors(chain = true)
public class RowDataDatum implements Serializable {
@Serial
private static final long serialVersionUID = -2838784450721979776L;
private Long id;
private Map<String, Object> data;
private boolean insert;
}

View File

@ -2,8 +2,10 @@ package io.dataease.exception;
import io.dataease.result.ResultCode;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class DEException extends RuntimeException {
private int code;

View File

@ -1,6 +1,5 @@
package io.dataease.commons.utils;
package io.dataease.utils;
import io.dataease.utils.LogUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;