需求说明:根据JSON数据来配置页面中的组件
数据部分:
[{"formId":"titleInput","genre":"schemeName","value":"高蛋白减重饮食方案","label":"名称","placeholder":"请输入方案名称","max":"","min":""},{"formId":"assignTime","genre":"executionTime","type":"2","value":"0"},{"formId":"checkBox","genre":"feedbackMode","label":"反馈方式","value":[],"options":[{"title":"打卡反馈","value":"clockInFeedback","enable":1,"checked":1},{"title":"图片反馈","value":"pictureFeedback","enable":1,"checked":1},{"title":"文字反馈","value":"textFeedback","enable":1,"checked":1},{"title":"视频反馈","value":"videoFeedback","enable":1,"checked":1},{"title":"记录饮食","value":"dietFeedback","enable":1,"checked":1},{"title":"记录运动","value":"exerciseFeedback","enable":0,"checked":0},{"title":"记录血糖","value":"sugarFeedback","enable":0,"checked":0},{"title":"记录血压/心率","value":"pressureFeedback","enable":0,"checked":0},{"title":"记录体重","value":"weightFeedback","enable":0,"checked":0},{"title":"记录睡眠","value":"sleepFeedback","enable":0,"checked":0},{"title":"记录用药","value":"drugFeedback","enable":0,"checked":0},{"title":"记录体温","value":"animalHeatFeedback","enable":0,"checked":0},{"title":"提交问卷","value":"questionnaireFeedback","enable":0,"checked":0}]},{"formId":"dietAdvice","genre":"dietAdvice","options":[{"itemName":"早餐","advice":"饮食要求:xxx","enable":1,"checked":1,"foodList":[{"foodName":"乳清蛋白粉","foodCount":"10","foodUnit":"克"},{"foodName":"可溶性膳食纤维","foodCount":"10","foodUnit":"克"},{"foodName":"温水","foodCount":"200","foodUnit":"毫升"},{"foodName":"多种营养素制剂","foodCount":"1","foodUnit":"粒"},{"foodName":"鱼油胶囊(1克)","foodCount":"1","foodUnit":"粒"}]},{"itemName":"午餐","advice":"饮食要求:xxx ","enable":1,"checked":1,"foodList":[{"foodName":"主食(粗细搭配)","foodCount":"50","foodUnit":"克"},{"foodName":"蛋白质类食物(瘦肉50克=1个鸡蛋或豆腐100克或豆干50克)","foodCount":"50","foodUnit":"克"},{"foodName":"蔬菜(合计)","foodCount":"100","foodUnit":"克"},{"foodName":"新鲜叶类蔬菜","foodCount":"50","foodUnit":"克"},{"foodName":"新鲜菇类","foodCount":"50","foodUnit":"克"}]},{"itemName":"晚餐","advice":"饮食要求:xxx ","enable":1,"checked":1,"foodList":[{"foodName":"主食(粗细搭配)","foodCount":"50","foodUnit":"克"},{"foodName":"蛋白质类食物(瘦肉50克=1个鸡蛋或豆腐100克或豆干50克)","foodCount":"50","foodUnit":"克"},{"foodName":"蔬菜(合计)","foodCount":"100","foodUnit":"克"},{"foodName":"新鲜叶类蔬菜","foodCount":"50","foodUnit":"克"},{"foodName":"新鲜菇类","foodCount":"50","foodUnit":"克"},{"foodName":"多种营养素制剂","foodCount":"1","foodUnit":"粒"},{"foodName":"鱼油胶囊(1克)","foodCount":"1","foodUnit":"粒"}]}]},{"formId":"upload","genre":"imageTask","label":"图片任务","value":["https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fs1.sinaimg.cn%2Forignal%2F48ae37a6285f3d6e96840&refer=http%3A%2F%2Fs1.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621837959&t=0bb081b98fe8ecaa89f3037dfcdbfa9b","https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13446502320%2F1000&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621838030&t=5e89a1bbbb62e2a491a64c9a0df4dcf9"],"uploadType":"image","minCount":"","maxCount":"","minSize":"","maxSize":""},{"formId":"upload","genre":"videoTask","label":"视频任务","value":["https://vod.pule.com/6c992c3bvodcq1500003583/4b4fd9cc5285890813365762540/f0.mp4"],"uploadType":"video","minCount":"","maxCount":"","minSize":"","maxSize":""},{"formId":"messageNotice","genre":"messageNotice","label":"消息通知","timeLabel":"发送时间","messageValue":"","timeValue":"","placeholder":"请输入通知内容","maxLine":"","maxCount":""}]
组件工厂:
import 'package:doctor_admin/pages/group/carePlan/schemeComponents/assignTime.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/checkBox.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/checkBoxWrap.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/dietAdvice.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/drugArray.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/itemArray.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/messageNotice.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/radioBox.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/textarea.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/timePeriod.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/titleInput.dart';import 'package:doctor_admin/pages/group/carePlan/schemeComponents/upload.dart';import 'package:flutter/material.dart';componentFactor (config) {if(config['formId'] == 'titleInput') {var _key = GlobalKey<TitleInputState>();return {'widget': TitleInput(key: _key, config: config,),'widgetName': 'titleInput','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'assignTime') {var _key = GlobalKey<AssignTimeState>();return {'widget': AssignTime(key: _key, config: config,),'widgetName': 'assignTime','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'checkBox') {var _key = GlobalKey<CheckBoxState>();return {'widget': CheckBox(key: _key, config: config,),'widgetName': 'checkBox','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'checkBoxWrap') {var _key = GlobalKey<CheckBoxWrapState>();return {'widget': CheckBoxWrap(key: _key, config: config,),'widgetName': 'checkBoxWrap','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'radio') {var _key = GlobalKey<RadioBoxState>();return {'widget': RadioBox(key: _key, config: config,),'widgetName': 'radio','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'dietAdvice') {var _key = GlobalKey<DietAdviceState>();return {'widget': DietAdvice(key: _key, config: config,),'widgetName': 'checkBox','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'textarea') {var _key = GlobalKey<TextareaState>();return {'widget': Textarea(key: _key, config: config,),'widgetName': 'textarea','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'messageNotice') {var _key = GlobalKey<MessageNoticeState>();return {'widget': MessageNotice(key: _key, config: config,),'widgetName': 'messageNotice','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'upload') {var _key = GlobalKey<UploadState>();return {'widget': Upload(key: _key, config: config,),'widgetName': 'upload','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'itemArray') {var _key = GlobalKey<ItemArrayState>();return {'widget': ItemArray(key: _key, config: config,),'widgetName': 'itemArray','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'drugArray') {var _key = GlobalKey<DrugArrayState>();return {'widget': DrugArray(key: _key, config: config,),'widgetName': 'drugArray','getResult': () => _key.currentState.result,};} else if (config['formId'] == 'timePeriod') {var _key = GlobalKey<TimePeriodState>();return {'widget': TimePeriod(key: _key, config: config,),'widgetName': 'timePeriod','getResult': () => _key.currentState.result,};}else {return {'widget': Center(child: Text('暂无对应组件', style: TextStyle(fontSize: 18, color: Color(0xff666666)),),),};}}
根据数据生成组件:
workComponents(configJson) {components = [];configJson.forEach((value) {components.add(componentFactor(value));});setState(() {});}
渲染组件:
Column(children: <Widget>[for(int i = 0; i < components.length; i++) components[i]['widget'],])
获取组件中的表单数据:
var result = [];for(int i = 0; i < components.length; i++) {if(components[i]['getResult'] != null) {var value = components[i]['getResult']();var tip = checkParams(value); // 检查数据是否完整if(tip != 'success') {showMsg(context, tip);return;}result.add(value);}}
组件内容,这里例举其中1个:
import 'dart:convert';import 'package:doctor_admin/config/common.dart';import 'package:flutter/material.dart';class TitleInput extends StatefulWidget {final config;TitleInput({Key key, @required this.config}):super(key: key);TitleInputState createState() => TitleInputState();}class TitleInputState extends State<TitleInput> {TextEditingController _ctrl =TextEditingController(text: '');FocusNode _node = FocusNode();var result;@overridevoid initState() {super.initState();_ctrl = TextEditingController(text: widget.config['value']??'');setState(() {result = jsonDecode(jsonEncode(widget.config));});}@overrideWidget build(BuildContext context) {return result == null ? SizedBox() : Container(color: Color(0xffffffff),margin: EdgeInsets.only(bottom: setSize(20)),padding: EdgeInsets.fromLTRB(setSize(36), setSize(40), setSize(36), setSize(40)),child: Row(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[result['label'].isEmpty ? SizedBox() : Container(padding: EdgeInsets.symmetric(vertical: setSize(20)),child: Text.rich(TextSpan(children: [// TextSpan(text: '* ', style: TextStyle(color: Color(0xffF76565))),TextSpan(text: result['label'], style: TextStyle(color: Color(0xff4c4c4c))),]),style: TextStyle(fontSize: setFont(28)),),),SizedBox(width: setSize(40)),Expanded(child: Container(height: setSize(80),decoration: BoxDecoration(border: Border(bottom: BorderSide(width: setSize(1), color: Color(0xffe2e2e2))),),alignment: Alignment.centerLeft,child: TextField(style: TextStyle(fontSize: setFont(28), color: Color(0xff222222), fontWeight: FontWeight.w400, height: 1, textBaseline: TextBaseline.alphabetic),scrollPadding: EdgeInsets.zero,decoration: InputDecoration(contentPadding: EdgeInsets.zero,isDense: true,border: InputBorder.none,hintText: result['placeholder']??'',hintStyle: TextStyle(fontSize: setFont(28), color: Color(0xffCCCCCC), height: 1, textBaseline: TextBaseline.alphabetic),counterText: '',),controller: _ctrl,focusNode: _node,keyboardType: TextInputType.text,autocorrect: false,maxLength: ('${result['max']??''}').isEmpty ? 10000 : result['max'],maxLines: 1,textInputAction: TextInputAction.done,onChanged: (value) => {result['value'] = value},),),)],),);}}
