mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-18 09:35:29 +08:00
支持表单提交
This commit is contained in:
parent
0f6366a2b4
commit
76694a4f8a
@ -138,7 +138,15 @@
|
|||||||
|
|
||||||
## 表单需求
|
## 表单需求
|
||||||
帮我理一下这个表单需求,然后帮我合理设计一下表结构和技术选型,再实现表单提交接口和表单提交过的数据查询接口等等,有遗漏的记得帮我补上,在h5在线编辑中,可以新建个表单,表单可以自定义提交项,这种自定义表单,如何设计表结构,是用mongo还是mysql,
|
帮我理一下这个表单需求,然后帮我合理设计一下表结构和技术选型,再实现表单提交接口和表单提交过的数据查询接口等等,有遗漏的记得帮我补上,在h5在线编辑中,可以新建个表单,表单可以自定义提交项,这种自定义表单,如何设计表结构,是用mongo还是mysql,
|
||||||
然后我看其他平台是这样提交表单内容的:
|
1、其他平台是这样提交表单内容的:
|
||||||
{"templet_form_id":450055,"form_id":"461709","form_data":{"19fef684-b6ef-4bfb-8d68-603c99444ac5":"文本内容","6cbf9138-a20d-428c-b635-291246da3926":"13255556645","14154ccc-c2b3-4d27-8eb2-e3e422af294f":"1713322582323@qq.com"}}
|
{"templet_form_id":450055,"form_id":"461709","form_data":{"19fef684-b6ef-4bfb-8d68-603c99444ac5":"文本内容","6cbf9138-a20d-428c-b635-291246da3926":"13255556645","14154ccc-c2b3-4d27-8eb2-e3e422af294f":"1713322582323@qq.com"}}
|
||||||
表单的结构是保存在 H5ProjectContent 下的 Element(type=form时)->formItems 中的,formItems 的结构是如下:
|
2、表单的结构是保存在 H5ProjectContent 下的 Element(type=form时)->formItems 中的,formItems 的结构是如下:
|
||||||
{"formItems": [ { "prop": "cf1d1fd1-9df9-44b4-ba73-3c553784aeab", "widget": "input", "verify": { "enable": false, "hint": "请输入文本内容" } }, { "prop": "56d54498-7d9d-4055-badd-09596fc9a43c", "widget": "input", "verify": { "enable": false, "hint": "请输入文本内容" } }, { "prop": "073f7b1f-afb9-4810-8896-d760197f5d02", "widget": "input", "verify": { "enable": true, "hint": "请输入正确的手机号码" } }, { "prop": "155ed883-93e5-4509-88db-ace73caac0d2", "widget": "input", "verify": { "enable": false, "hint": "请输入文本内容" } } ]}
|
{"formItems": [ { "prop": "cf1d1fd1-9df9-44b4-ba73-3c553784aeab", "widget": "input", "verify": { "enable": false, "hint": "请输入文本内容" } }, { "prop": "56d54498-7d9d-4055-badd-09596fc9a43c", "widget": "input", "verify": { "enable": false, "hint": "请输入文本内容" } }, { "prop": "073f7b1f-afb9-4810-8896-d760197f5d02", "widget": "input", "verify": { "enable": true, "hint": "请输入正确的手机号码" } }, { "prop": "155ed883-93e5-4509-88db-ace73caac0d2", "widget": "input", "verify": { "enable": false, "hint": "请输入文本内容" } } ]}
|
||||||
|
|
||||||
|
然后完善一下 H5ProjectContent 中的Element,目前有这几种类型,对应的内容有:image、 text、 svg、 group、 form、 map这几个,对应的内容结构如下:
|
||||||
|
image: { "uuid": "0.241109143257637336", "type": "image", "title": "4", "category": "", "opacity": 1, "padding": [ 0, 0, 0, 0 ], "width": 143, "height": 139, "left": 621, "top": -24, "transform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "animations": [ { "type": "enter", "order": 0, "keyframes": { "opacity": [ 0, 1 ], "transform": [ "translate(0%, -82.73381294964028%) matrix(1, 0, 0, 1, 0, 0)", "translate(0, 0) scale(1) matrix(1, 0, 0, 1, 0, 0)" ] }, "delay": 0, "duration": 1000, "fill": "both", "name": "渐变和移动", "easing": " cubic-bezier(0.31, 0.21, 0.20, 1)", "customValues": { "direction": 0 }, "groupOrder": 1 } ], "boxShadow": null, "resize": 7, "dragable": true, "rotatable": true, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": { "contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0 }, "watermarkEnable": false, "metaInfo": { "materials": [ { "id": 48218352, "type": "image" } ] }, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": "blendNormal", "maskInfo": { "enable": false, "showSelf": false, "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "top": 0 } }, "suspension": { "enable": false, "top": null, "left": null, "right": null, "bottom": null }, "url": "https://st-gdx.dancf.com/odyssey/uxms/20211022-190216-5ef3.png", "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "right": 0, "top": 0 }, "imageEffects": [], "aggregatedColors": [], "mainColor": null, "effectScale": 1, "imageTransform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "filterInfo": null, "naturalWidth": 143, "naturalHeight": 139, "resourceType": "image", "naturalDuration": 0, "enableDragToMask": true, "loop": true, "canDownload": false, "version": "7.1.71", "events": [] }
|
||||||
|
text: { "uuid": "0.291946162773902226", "type": "text", "title": "地址导航", "category": "", "opacity": 1, "padding": [ 0, 0, 0, 0 ], "width": 186.541, "height": 40, "left": 79.72950000000003, "top": 3, "transform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "animations": [], "boxShadow": null, "resize": 5, "dragable": false, "rotatable": false, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": { "contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0 }, "watermarkEnable": false, "metaInfo": null, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": null, "maskInfo": { "enable": false, "showSelf": false, "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "top": 0 } }, "suspension": { "enable": false, "top": null, "left": null, "right": null, "bottom": null }, "color": "#570002ff", "fontFamily": "SourceHanSansSC-Regular", "fontStyle": "normal", "fontWeight": 400, "fontSize": 33, "lineHeight": 1.2, "letterSpacing": 0, "textDecoration": "none", "writingMode": "horizontal-tb", "textAlign": "center", "verticalAlign": "top", "content": "地址导航", "contents": null, "effectScale": 1, "textShadow": null, "autoScale": true, "textEffects": [], "aggregatedColors": [ "#570002ff" ], "mainColor": null, "listStyle": "", "autoAdaptive": 1, "adjustsFontSize": false, "version": "6.1.71", "bindDataKey": "", "events": [] }
|
||||||
|
svg: { "uuid": "0.970693030997296142", "type": "svg", "title": "形状 2", "category": "", "opacity": 0.0784313725490196, "padding": [ 0, 0, 0, 0 ], "width": 3.000537872314453, "height": 668.0000002384186, "left": 26.999731063842773, "top": 0, "transform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "animations": [], "boxShadow": null, "resize": 7, "dragable": false, "rotatable": false, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": { "contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0 }, "watermarkEnable": false, "metaInfo": { "materials": [] }, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": null, "maskInfo": { "enable": false, "showSelf": false, "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "top": 0 } }, "suspension": { "enable": false, "top": null, "left": null, "right": null, "bottom": null }, "url": "https://st-gdx.dancf.com/odyssey/uxms/20211022-190216-bb71.svg", "content": "", "colors": [ "#e9d196ff", "#fff1cfff", "#e9d196ff" ], "containerTransform": null, "version": "7.1.71", "events": [] }
|
||||||
|
group: { "uuid": "0.5223160352186436538", "type": "group", "title": "", "category": "", "opacity": 1, "padding": [ 0, 0, 0, 0 ], "width": 351.43835616438355, "height": 90.86839294433594, "left": 345.2801802125696, "top": 1209.7794354248047, "transform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "animations": [ { "type": "enter", "order": 3, "keyframes": { "opacity": [ 0, 1 ], "transform": [ "translate(115.16096996485061%, 0%) matrix(1, 0, 0, 1, 0, 0)", "translate(0, 0) scale(1) matrix(1, 0, 0, 1, 0, 0)" ] }, "delay": 250, "duration": 1000, "fill": "both", "name": "渐变和移动", "easing": " cubic-bezier(0.31, 0.21, 0.20, 1)", "customValues": { "direction": 1 }, "groupOrder": 1 } ], "boxShadow": null, "resize": 1, "dragable": true, "rotatable": true, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": { "contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0 }, "watermarkEnable": false, "metaInfo": null, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": null, "maskInfo": { "enable": false, "showSelf": false, "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "top": 0 } }, "suspension": { "enable": false, "top": null, "left": null, "right": null, "bottom": null }, "elements": [ { "uuid": "0.4198633247682788452", "type": "text", "title": "中国·厦门", "category": "", "opacity": 1, "padding": [ 0, 0, 0, 0 ], "width": 252.629, "height": 43, "left": 98.80935616438364, "top": 47.86839294433594, "transform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "animations": [], "boxShadow": null, "resize": 5, "dragable": false, "rotatable": false, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": { "contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0 }, "watermarkEnable": false, "metaInfo": null, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": null, "maskInfo": { "enable": false, "showSelf": false, "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "top": 0 } }, "suspension": { "enable": false, "top": null, "left": null, "right": null, "bottom": null }, "color": "#fff4d5ff", "fontFamily": "SourceHanSansSC-Regular", "fontStyle": "normal", "fontWeight": 400, "fontSize": 36, "lineHeight": 1.2, "letterSpacing": 0, "textDecoration": "none", "writingMode": "horizontal-tb", "textAlign": "right", "verticalAlign": "top", "content": "中国·厦门", "contents": null, "effectScale": 1, "textShadow": null, "autoScale": true, "textEffects": [], "aggregatedColors": [ "#fff4d5ff" ], "mainColor": null, "listStyle": "", "autoAdaptive": 1, "adjustsFontSize": false, "version": "6.1.71", "events": [], "bindDataKey": "" } ], "splitenable": true, "autoGrow": false, "version": "7.1.71", "events": [] }
|
||||||
|
form: {"uuid": "0.6779576535240048515", "type": "form", "title": "", "category": "", "opacity": 1, "padding": [0, 0, 0, 0], "width": 510.5, "height": 779, "left": 119.75000000000001, "top": 415.7632093933465, "transform": {"a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0}, "animations": [{"type": "enter", "order": 3, "keyframes": {"opacity": [0, 1], "transform": ["scale(0.7) matrix(1, 0, 0, 1, 0, 0)", "translate(0, 0) scale(1) matrix(1, 0, 0, 1, 0, 0)"]}, "delay": 0, "duration": 1000, "fill": "both", "name": "渐变和缩放", "easing": "ease-in-out", "groupOrder": 3}], "boxShadow": null, "resize": 14, "dragable": true, "rotatable": true, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": {"contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0}, "watermarkEnable": false, "metaInfo": null, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": null, "maskInfo": {"enable": false, "showSelf": false, "imageUrl": "", "effectedResult": {"width": 0, "height": 0, "left": 0, "top": 0}}, "suspension": {"enable": false, "top": null, "left": null, "right": null, "bottom": null}, "formData": {"cf1d1fd1-9df9-44b4-ba73-3c553784aeab": "", "073f7b1f-afb9-4810-8896-d760197f5d02": "", "56d54498-7d9d-4055-badd-09596fc9a43c": "", "155ed883-93e5-4509-88db-ace73caac0d2": ""}, "formOptions": {"id": "ee0c7225-cc60-4a16-9cf3-e2d313dd1309", "started_at": "", "finished_at": "", "auth": {"wechat": false}}, "formSchema": {"type": "object", "required": ["cf1d1fd1-9df9-44b4-ba73-3c553784aeab", "073f7b1f-afb9-4810-8896-d760197f5d02", "155ed883-93e5-4509-88db-ace73caac0d2"], "properties": {"cf1d1fd1-9df9-44b4-ba73-3c553784aeab": {"type": "string", "title": "姓名", "format": "string", "pattern": ".+", "description": ""}, "073f7b1f-afb9-4810-8896-d760197f5d02": {"type": "string", "title": "请输入手机号", "default": "", "format": "string", "pattern": "^([+\\d\\s/-]+)?([1]([3-9])[0-9]{9})$", "description": ""}, "56d54498-7d9d-4055-badd-09596fc9a43c": {"type": "string", "title": "人数", "format": "string", "pattern": ".+", "description": ""}, "155ed883-93e5-4509-88db-ace73caac0d2": {"type": "string", "title": "备注", "format": "string", "pattern": ".+", "description": ""}}}, "formTheme": {"colors": ["#ffe8a3ff", "#ffffffff", "#ffe8a3ff", "#ffe8a3ff", "#ffffff00"], "common": {"verticalPadding": 27}, "question": {"space": 20}, "image": {"column": 2, "width": 285, "height": 285}, "border": {"width": 1, "radius": 40}, "hintColors": ["#de415c", "#de415c", "#fdf7f8"], "text": {"submitText": "提交"}}, "formItems": [{"prop": "cf1d1fd1-9df9-44b4-ba73-3c553784aeab", "widget": "input", "verify": {"enable": false, "hint": "请输入文本内容"}}, {"prop": "56d54498-7d9d-4055-badd-09596fc9a43c", "widget": "input", "verify": {"enable": false, "hint": "请输入文本内容"}}, {"prop": "073f7b1f-afb9-4810-8896-d760197f5d02", "widget": "input", "verify": {"enable": true, "hint": "请输入正确的手机号码"}}, {"prop": "155ed883-93e5-4509-88db-ace73caac0d2", "widget": "input", "verify": {"enable": false, "hint": "请输入文本内容"}}], "fontFamily": "SourceHanSansSC-Regular", "fontStyle": "normal", "fontWeight": 400, "fontSize": 25, "textDecoration": "", "content": "-0123456789:交人入号名备姓年手择提数日月机注请输选", "contents": [{"color": "", "fontFamily": "SourceHanSansSC-Regular", "fontSize": 25, "fontStyle": "normal", "fontWeight": 400, "textDecoration": "", "content": "-0123456789:交人入号名备姓年手择提数日月机注请输选"}], "minWidth": 400, "maxWidth": 750, "minHeight": 509, "maxHeight": 5000, "version": "7.1.71", "events": [], "color": ""}
|
||||||
|
map: { "uuid": "0.548034526304074540", "type": "map", "title": "", "category": "", "opacity": 1, "padding": [ 0, 0, 0, 0 ], "width": 522.6666666666666, "height": 392, "left": 117, "top": 436, "transform": { "a": 1, "b": 0, "c": 0, "d": 1, "tx": 0, "ty": 0 }, "animations": [ { "type": "enter", "order": 4, "keyframes": { "opacity": [ 0, 1 ], "transform": [ "scale(0.7) matrix(1, 0, 0, 1, 0, 0)", "translate(0, 0) scale(1) matrix(1, 0, 0, 1, 0, 0)" ] }, "delay": 0, "duration": 1000, "fill": "both", "name": "渐变和缩放", "easing": "ease-in-out", "groupOrder": 0 } ], "boxShadow": null, "resize": 7, "dragable": true, "rotatable": true, "editable": true, "frozen": false, "hidden": false, "lock": false, "borderRadius": 0, "filter": { "contrast": 0, "sharpness": 0, "hueRotate": 0, "saturate": 0, "brightness": 0, "gaussianBlur": 0, "temperature": 0, "tint": 0 }, "watermarkEnable": false, "metaInfo": null, "linkId": "", "groupable": true, "flex": null, "backgroundColor": null, "backgroundEffect": null, "border": null, "blendMode": null, "maskInfo": { "enable": false, "showSelf": false, "imageUrl": "", "effectedResult": { "width": 0, "height": 0, "left": 0, "top": 0 } }, "suspension": { "enable": false, "top": null, "left": null, "right": null, "bottom": null }, "longitude": 118.186395, "latitude": 24.50876, "address": "厦门稿定科技", "zoom": 17, "borderWidth": [ 0, 0, 0, 0 ], "fontSize": 32, "borderRadiusX": 0, "borderRadiusY": 0, "borderColor": "#E0E5EA", "color": "#ffffffff", "version": "7.1.71", "imageDataUrl": "https://st-gdx.dancf.com/odyssey/uxms/20211026-111338-d7dd.png" }
|
||||||
|
|||||||
@ -22,11 +22,14 @@ import java.time.format.DateTimeFormatter;
|
|||||||
public class JsonConfig {
|
public class JsonConfig {
|
||||||
@Bean
|
@Bean
|
||||||
public ObjectMapper mapperObject() {
|
public ObjectMapper mapperObject() {
|
||||||
JavaTimeModule module = new JavaTimeModule();
|
JavaTimeModule timeModule = new JavaTimeModule();
|
||||||
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||||
module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||||
module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
timeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||||
return new ObjectMapper().registerModule(module);
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.registerModule(timeModule);
|
||||||
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,170 @@
|
|||||||
|
package com.luban.api.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.luban.api.entity.FormSubmission;
|
||||||
|
import com.luban.api.mongo.entity.FormData;
|
||||||
|
import com.luban.api.service.FormService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 表单控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author your-name
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/form")
|
||||||
|
@Tag(name = "表单管理", description = "表单提交与查询")
|
||||||
|
@Slf4j
|
||||||
|
public class FormController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FormService formService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交表单数据
|
||||||
|
*
|
||||||
|
* @param request 请求体包含表单数据
|
||||||
|
* @return 是否提交成功
|
||||||
|
*/
|
||||||
|
@Operation(summary = "提交表单数据")
|
||||||
|
@PostMapping("/submit")
|
||||||
|
public Boolean submitForm(@RequestBody SubmitFormRequest request, HttpServletRequest httpRequest) {
|
||||||
|
// 获取客户端IP地址
|
||||||
|
String ipAddress = getClientIpAddress(httpRequest);
|
||||||
|
// 获取User-Agent
|
||||||
|
String userAgent = httpRequest.getHeader("User-Agent");
|
||||||
|
|
||||||
|
return formService.submitFormData(
|
||||||
|
request.getTemplateFormId(),
|
||||||
|
request.getFormId(),
|
||||||
|
request.getFormData(),
|
||||||
|
ipAddress,
|
||||||
|
userAgent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板表单ID分页查询表单提交记录
|
||||||
|
*
|
||||||
|
* @param templateFormId 模板表单ID
|
||||||
|
* @param pageNum 页码
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 表单提交记录分页数据
|
||||||
|
*/
|
||||||
|
@Operation(summary = "根据模板表单ID分页查询表单提交记录")
|
||||||
|
@GetMapping("/page/template/{templateFormId}")
|
||||||
|
public IPage<FormSubmission> pageByTemplateFormId(
|
||||||
|
@PathVariable Long templateFormId,
|
||||||
|
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
|
return formService.pageFormSubmissionsByTemplateFormId(templateFormId, pageNum, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据表单ID分页查询表单提交记录
|
||||||
|
*
|
||||||
|
* @param formId 表单ID
|
||||||
|
* @param pageNum 页码
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 表单提交记录分页数据
|
||||||
|
*/
|
||||||
|
@Operation(summary = "根据表单ID分页查询表单提交记录")
|
||||||
|
@GetMapping("/page/form/{formId}")
|
||||||
|
public IPage<FormSubmission> pageByFormId(
|
||||||
|
@PathVariable String formId,
|
||||||
|
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
|
return formService.pageFormSubmissionsByFormId(formId, pageNum, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据提交记录ID获取表单数据详情
|
||||||
|
*
|
||||||
|
* @param submissionId 提交记录ID
|
||||||
|
* @return 表单数据详情
|
||||||
|
*/
|
||||||
|
@Operation(summary = "根据提交记录ID获取表单数据详情")
|
||||||
|
@GetMapping("/detail/{submissionId}")
|
||||||
|
public FormData getFormDataDetail(@PathVariable Long submissionId) {
|
||||||
|
return formService.getFormDataDetail(submissionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板表单ID获取所有表单数据
|
||||||
|
*
|
||||||
|
* @param templateFormId 模板表单ID
|
||||||
|
* @return 表单数据列表
|
||||||
|
*/
|
||||||
|
@Operation(summary = "根据模板表单ID获取所有表单数据")
|
||||||
|
@GetMapping("/list/template/{templateFormId}")
|
||||||
|
public List<FormData> listByTemplateFormId(@PathVariable Long templateFormId) {
|
||||||
|
return formService.listFormDataByTemplateFormId(templateFormId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据表单ID获取所有表单数据
|
||||||
|
*
|
||||||
|
* @param formId 表单ID
|
||||||
|
* @return 表单数据列表
|
||||||
|
*/
|
||||||
|
@Operation(summary = "根据表单ID获取所有表单数据")
|
||||||
|
@GetMapping("/list/form/{formId}")
|
||||||
|
public List<FormData> listByFormId(@PathVariable String formId) {
|
||||||
|
return formService.listFormDataByFormId(formId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端IP地址
|
||||||
|
*
|
||||||
|
* @param request HTTP请求
|
||||||
|
* @return 客户端IP地址
|
||||||
|
*/
|
||||||
|
private String getClientIpAddress(HttpServletRequest request) {
|
||||||
|
String ipAddress = request.getHeader("X-Forwarded-For");
|
||||||
|
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||||
|
ipAddress = request.getHeader("Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||||
|
ipAddress = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||||
|
ipAddress = request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
return ipAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交表单请求类
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public static class SubmitFormRequest {
|
||||||
|
/**
|
||||||
|
* 模板表单ID
|
||||||
|
*/
|
||||||
|
private Long templateFormId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单ID
|
||||||
|
*/
|
||||||
|
private String formId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单数据
|
||||||
|
*/
|
||||||
|
private Map<String, Object> formData;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.luban.api.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.luban.api.entity.FormSubmission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 表单提交记录 Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author your-name
|
||||||
|
*/
|
||||||
|
public interface FormSubmissionDao extends BaseMapper<FormSubmission> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package com.luban.api.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单提交记录实体类
|
||||||
|
*
|
||||||
|
* @author your-name
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("h5_form_submission")
|
||||||
|
@Schema(title = "表单提交记录")
|
||||||
|
public class FormSubmission implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板表单ID(对应H5Project的ID)
|
||||||
|
*/
|
||||||
|
private Long templateFormId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单ID(实例ID)
|
||||||
|
*/
|
||||||
|
private String formId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交时间戳
|
||||||
|
*/
|
||||||
|
private Long submitTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交者IP地址
|
||||||
|
*/
|
||||||
|
private String ipAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户代理信息
|
||||||
|
*/
|
||||||
|
private String userAgent;
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.luban.api.mongo.dao;
|
||||||
|
|
||||||
|
import com.luban.api.mongo.entity.FormData;
|
||||||
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单数据 Repository
|
||||||
|
*
|
||||||
|
* @author lizhw
|
||||||
|
*/
|
||||||
|
public interface FormDataRepository extends MongoRepository<FormData, Long> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板表单ID查询表单数据列表
|
||||||
|
*
|
||||||
|
* @param templateFormId 模板表单ID
|
||||||
|
* @return 表单数据列表
|
||||||
|
*/
|
||||||
|
List<FormData> findByTemplateFormId(Long templateFormId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据表单ID查询表单数据列表
|
||||||
|
*
|
||||||
|
* @param formId 表单ID
|
||||||
|
* @return 表单数据列表
|
||||||
|
*/
|
||||||
|
List<FormData> findByFormId(String formId);
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
package com.luban.api.mongo.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单数据实体类 (存储在MongoDB中)
|
||||||
|
*
|
||||||
|
* @author your-name
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Document(collection = "h5_form_data")
|
||||||
|
public class FormData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交记录ID(对应MySQL中FormSubmission的ID)
|
||||||
|
*/
|
||||||
|
private Long submissionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板表单ID(对应H5Project的ID)
|
||||||
|
*/
|
||||||
|
private Long templateFormId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单ID(实例ID)
|
||||||
|
*/
|
||||||
|
private String formId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单数据(key为formItem的prop,value为用户填写的内容)
|
||||||
|
*/
|
||||||
|
private Map<String, Object> formData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交时间戳
|
||||||
|
*/
|
||||||
|
private Long submitTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交者IP地址
|
||||||
|
*/
|
||||||
|
private String ipAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户代理信息
|
||||||
|
*/
|
||||||
|
private String userAgent;
|
||||||
|
}
|
||||||
@ -1,6 +1,11 @@
|
|||||||
package com.luban.api.mongo.entity;
|
package com.luban.api.mongo.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
@ -159,11 +164,56 @@ public class H5ProjectContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 元素类
|
* 元素类型枚举
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum ElementType {
|
||||||
|
IMAGE("image"),
|
||||||
|
TEXT("text"),
|
||||||
|
SVG("svg"),
|
||||||
|
GROUP("group"),
|
||||||
|
FORM("form"),
|
||||||
|
MAP("map");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
ElementType(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ElementType fromValue(String value) {
|
||||||
|
for (ElementType type : ElementType.values()) {
|
||||||
|
if (type.getValue().equals(value)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown element type: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 元素基类
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@JsonTypeInfo(
|
||||||
|
use = JsonTypeInfo.Id.NAME,
|
||||||
|
include = JsonTypeInfo.As.PROPERTY,
|
||||||
|
property = "type",
|
||||||
|
defaultImpl = Element.class
|
||||||
|
)
|
||||||
|
@JsonSubTypes({
|
||||||
|
@JsonSubTypes.Type(value = ImageElement.class, name = "image"),
|
||||||
|
@JsonSubTypes.Type(value = TextElement.class, name = "text"),
|
||||||
|
@JsonSubTypes.Type(value = SvgElement.class, name = "svg"),
|
||||||
|
@JsonSubTypes.Type(value = GroupElement.class, name = "group"),
|
||||||
|
@JsonSubTypes.Type(value = FormElement.class, name = "form"),
|
||||||
|
@JsonSubTypes.Type(value = MapElement.class, name = "map")
|
||||||
|
})
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public static class Element {
|
public static class Element {
|
||||||
private String type;
|
private String uuid;
|
||||||
|
private ElementType type;
|
||||||
|
private String title;
|
||||||
private String category;
|
private String category;
|
||||||
private Double opacity;
|
private Double opacity;
|
||||||
private List<Integer> padding;
|
private List<Integer> padding;
|
||||||
@ -186,6 +236,24 @@ public class H5ProjectContent {
|
|||||||
private Map<String, Object> metaInfo;
|
private Map<String, Object> metaInfo;
|
||||||
private String linkId;
|
private String linkId;
|
||||||
private Boolean groupable;
|
private Boolean groupable;
|
||||||
|
private Object flex;
|
||||||
|
private Object backgroundColor;
|
||||||
|
private Object backgroundEffect;
|
||||||
|
private Object border;
|
||||||
|
private Object blendMode;
|
||||||
|
private MaskInfo maskInfo;
|
||||||
|
private Suspension suspension;
|
||||||
|
private String version;
|
||||||
|
private List<Animation> animations;
|
||||||
|
private List<Object> events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片元素类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class ImageElement extends Element {
|
||||||
private String url;
|
private String url;
|
||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
private Integer effectedImageWidth;
|
private Integer effectedImageWidth;
|
||||||
@ -200,19 +268,275 @@ public class H5ProjectContent {
|
|||||||
private FilterInfo filterInfo;
|
private FilterInfo filterInfo;
|
||||||
private Integer naturalWidth;
|
private Integer naturalWidth;
|
||||||
private Integer naturalHeight;
|
private Integer naturalHeight;
|
||||||
private String version;
|
private String resourceType;
|
||||||
private List<Animation> animations;
|
private Integer naturalDuration;
|
||||||
|
private Boolean enableDragToMask;
|
||||||
|
private Boolean loop;
|
||||||
|
private Boolean canDownload;
|
||||||
|
|
||||||
|
public ImageElement() {
|
||||||
|
this.setType(ElementType.IMAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本元素类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class TextElement extends Element {
|
||||||
|
private String color;
|
||||||
|
private String fontFamily;
|
||||||
|
private String fontStyle;
|
||||||
|
private Integer fontWeight;
|
||||||
|
private Integer fontSize;
|
||||||
|
private Double lineHeight;
|
||||||
|
private Integer letterSpacing;
|
||||||
|
private Object textDecoration;
|
||||||
|
private String writingMode;
|
||||||
|
private String textAlign;
|
||||||
|
private String verticalAlign;
|
||||||
private String content;
|
private String content;
|
||||||
private List<Object> contents;
|
private List<Object> contents;
|
||||||
private Boolean autoScale;
|
private Boolean autoScale;
|
||||||
private List<Object> textEffects;
|
private List<Object> textEffects;
|
||||||
private String listStyle;
|
private String listStyle;
|
||||||
private Integer autoAdaptive;
|
private Integer autoAdaptive;
|
||||||
|
private Boolean adjustsFontSize;
|
||||||
|
private Object textShadow;
|
||||||
|
private String bindDataKey;
|
||||||
|
|
||||||
|
public TextElement() {
|
||||||
|
this.setType(ElementType.TEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SVG元素类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class SvgElement extends Element {
|
||||||
|
private String url;
|
||||||
|
private String content;
|
||||||
|
private List<String> colors;
|
||||||
|
private Object containerTransform;
|
||||||
|
|
||||||
|
public SvgElement() {
|
||||||
|
this.setType(ElementType.SVG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组元素类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class GroupElement extends Element {
|
||||||
|
private List<Element> elements;
|
||||||
|
private Boolean splitenable;
|
||||||
|
private Boolean autoGrow;
|
||||||
|
|
||||||
|
public GroupElement() {
|
||||||
|
this.setType(ElementType.GROUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单元素类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class FormElement extends Element {
|
||||||
|
private Map<String, Object> formData;
|
||||||
|
private FormOptions formOptions;
|
||||||
|
private FormSchema formSchema;
|
||||||
|
private FormTheme formTheme;
|
||||||
|
private List<FormItem> formItems;
|
||||||
|
private String fontFamily;
|
||||||
|
private String fontStyle;
|
||||||
|
private Integer fontWeight;
|
||||||
|
private Integer fontSize;
|
||||||
private Object textDecoration;
|
private Object textDecoration;
|
||||||
private String writingMode;
|
private String content;
|
||||||
private String textAlign;
|
private List<Object> contents;
|
||||||
private String verticalAlign;
|
private Integer minWidth;
|
||||||
private List<Object> parents;
|
private Integer maxWidth;
|
||||||
|
private Integer minHeight;
|
||||||
|
private Integer maxHeight;
|
||||||
|
|
||||||
|
public FormElement() {
|
||||||
|
this.setType(ElementType.FORM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地图元素类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class MapElement extends Element {
|
||||||
|
// Map类型的具体字段可以根据需要添加
|
||||||
|
|
||||||
|
public MapElement() {
|
||||||
|
this.setType(ElementType.MAP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遮罩信息类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class MaskInfo {
|
||||||
|
private Boolean enable;
|
||||||
|
private Boolean showSelf;
|
||||||
|
private String imageUrl;
|
||||||
|
private EffectedResult effectedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生效结果类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class EffectedResult {
|
||||||
|
private Integer width;
|
||||||
|
private Integer height;
|
||||||
|
private Integer left;
|
||||||
|
private Integer top;
|
||||||
|
private Integer right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮设置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Suspension {
|
||||||
|
private Boolean enable;
|
||||||
|
private Object top;
|
||||||
|
private Object left;
|
||||||
|
private Object right;
|
||||||
|
private Object bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单选项类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class FormOptions {
|
||||||
|
private String id;
|
||||||
|
private String started_at;
|
||||||
|
private String finished_at;
|
||||||
|
private Auth auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Auth {
|
||||||
|
private Boolean wechat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单结构类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class FormSchema {
|
||||||
|
private String type;
|
||||||
|
private List<String> required;
|
||||||
|
private Map<String, Property> properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Property {
|
||||||
|
private String type;
|
||||||
|
private String title;
|
||||||
|
private String format;
|
||||||
|
private String pattern;
|
||||||
|
private String description;
|
||||||
|
private String defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单主题类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class FormTheme {
|
||||||
|
private List<String> colors;
|
||||||
|
private Common common;
|
||||||
|
private Question question;
|
||||||
|
private Image image;
|
||||||
|
private Border border;
|
||||||
|
private List<String> hintColors;
|
||||||
|
private Text text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用设置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Common {
|
||||||
|
private Integer verticalPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 问题设置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Question {
|
||||||
|
private Integer space;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片设置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Image {
|
||||||
|
private Integer column;
|
||||||
|
private Integer width;
|
||||||
|
private Integer height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 边框设置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Border {
|
||||||
|
private Integer width;
|
||||||
|
private Integer radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本设置类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Text {
|
||||||
|
private String submitText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单项类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class FormItem {
|
||||||
|
private String prop;
|
||||||
|
private String widget;
|
||||||
|
private Verify verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Verify {
|
||||||
|
private Boolean enable;
|
||||||
|
private String hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,15 +558,11 @@ public class H5ProjectContent {
|
|||||||
private String type;
|
private String type;
|
||||||
private Integer order;
|
private Integer order;
|
||||||
private Map<String, Object> keyframes;
|
private Map<String, Object> keyframes;
|
||||||
private List<String> easing;
|
|
||||||
private List<Double> offset;
|
|
||||||
private Integer delay;
|
private Integer delay;
|
||||||
private Integer duration;
|
private Integer duration;
|
||||||
private String fill;
|
private String fill;
|
||||||
private String name;
|
private String name;
|
||||||
private Object customValues;
|
private String easing;
|
||||||
private Integer groupOrder;
|
private Integer groupOrder;
|
||||||
private List<Object> excludeScale;
|
|
||||||
private String method;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,75 @@
|
|||||||
|
package com.luban.api.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.luban.api.entity.FormSubmission;
|
||||||
|
import com.luban.api.mongo.entity.FormData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 表单服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author lizhw
|
||||||
|
*/
|
||||||
|
public interface FormService extends IService<FormSubmission> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交表单数据
|
||||||
|
*
|
||||||
|
* @param templateFormId 模板表单ID
|
||||||
|
* @param formId 表单ID
|
||||||
|
* @param formData 表单数据
|
||||||
|
* @param ipAddress IP地址
|
||||||
|
* @param userAgent 用户代理
|
||||||
|
* @return 是否提交成功
|
||||||
|
*/
|
||||||
|
boolean submitFormData(Long templateFormId, String formId, Map<String, Object> formData, String ipAddress, String userAgent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板表单ID分页查询表单提交记录
|
||||||
|
*
|
||||||
|
* @param templateFormId 模板表单ID
|
||||||
|
* @param pageNum 页码
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 表单提交记录分页数据
|
||||||
|
*/
|
||||||
|
IPage<FormSubmission> pageFormSubmissionsByTemplateFormId(Long templateFormId, Integer pageNum, Integer pageSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据表单ID分页查询表单提交记录
|
||||||
|
*
|
||||||
|
* @param formId 表单ID
|
||||||
|
* @param pageNum 页码
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 表单提交记录分页数据
|
||||||
|
*/
|
||||||
|
IPage<FormSubmission> pageFormSubmissionsByFormId(String formId, Integer pageNum, Integer pageSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据提交记录ID获取表单数据详情
|
||||||
|
*
|
||||||
|
* @param submissionId 提交记录ID
|
||||||
|
* @return 表单数据详情
|
||||||
|
*/
|
||||||
|
FormData getFormDataDetail(Long submissionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板表单ID获取所有表单数据
|
||||||
|
*
|
||||||
|
* @param templateFormId 模板表单ID
|
||||||
|
* @return 表单数据列表
|
||||||
|
*/
|
||||||
|
List<FormData> listFormDataByTemplateFormId(Long templateFormId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据表单ID获取所有表单数据
|
||||||
|
*
|
||||||
|
* @param formId 表单ID
|
||||||
|
* @return 表单数据列表
|
||||||
|
*/
|
||||||
|
List<FormData> listFormDataByFormId(String formId);
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.luban.api.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.luban.api.dao.FormSubmissionDao;
|
||||||
|
import com.luban.api.entity.FormSubmission;
|
||||||
|
import com.luban.api.mongo.dao.FormDataRepository;
|
||||||
|
import com.luban.api.mongo.entity.FormData;
|
||||||
|
import com.luban.api.service.FormService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 表单服务实现类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author lizhw
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FormServiceImpl extends ServiceImpl<FormSubmissionDao, FormSubmission> implements FormService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FormDataRepository formDataRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public boolean submitFormData(Long templateFormId, String formId, Map<String, Object> formData, String ipAddress, String userAgent) {
|
||||||
|
// 保存到MySQL
|
||||||
|
FormSubmission formSubmission = new FormSubmission();
|
||||||
|
formSubmission.setTemplateFormId(templateFormId);
|
||||||
|
formSubmission.setFormId(formId);
|
||||||
|
long currentTime = System.currentTimeMillis() / 1000;
|
||||||
|
formSubmission.setSubmitTime(currentTime);
|
||||||
|
formSubmission.setIpAddress(ipAddress);
|
||||||
|
formSubmission.setUserAgent(userAgent);
|
||||||
|
this.save(formSubmission);
|
||||||
|
|
||||||
|
// 保存到MongoDB
|
||||||
|
FormData formDataEntity = new FormData();
|
||||||
|
formDataEntity.setSubmissionId(formSubmission.getId());
|
||||||
|
formDataEntity.setTemplateFormId(templateFormId);
|
||||||
|
formDataEntity.setFormId(formId);
|
||||||
|
formDataEntity.setFormData(formData);
|
||||||
|
formDataEntity.setSubmitTime(currentTime);
|
||||||
|
formDataEntity.setIpAddress(ipAddress);
|
||||||
|
formDataEntity.setUserAgent(userAgent);
|
||||||
|
formDataRepository.save(formDataEntity);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPage<FormSubmission> pageFormSubmissionsByTemplateFormId(Long templateFormId, Integer pageNum, Integer pageSize) {
|
||||||
|
LambdaQueryWrapper<FormSubmission> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(FormSubmission::getTemplateFormId, templateFormId);
|
||||||
|
queryWrapper.orderByDesc(FormSubmission::getSubmitTime);
|
||||||
|
|
||||||
|
IPage<FormSubmission> page = new Page<>(pageNum, pageSize);
|
||||||
|
return this.page(page, queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPage<FormSubmission> pageFormSubmissionsByFormId(String formId, Integer pageNum, Integer pageSize) {
|
||||||
|
LambdaQueryWrapper<FormSubmission> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(FormSubmission::getFormId, formId);
|
||||||
|
queryWrapper.orderByDesc(FormSubmission::getSubmitTime);
|
||||||
|
|
||||||
|
IPage<FormSubmission> page = new Page<>(pageNum, pageSize);
|
||||||
|
return this.page(page, queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FormData getFormDataDetail(Long submissionId) {
|
||||||
|
return formDataRepository.findById(submissionId).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FormData> listFormDataByTemplateFormId(Long templateFormId) {
|
||||||
|
return formDataRepository.findByTemplateFormId(templateFormId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FormData> listFormDataByFormId(String formId) {
|
||||||
|
return formDataRepository.findByFormId(formId);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user