|
|
|
import 'dart:convert';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:one_key/constant/constant.dart';
|
|
|
|
import 'package:one_key/models/get_reserve_type_field_model.dart';
|
|
|
|
import 'package:one_key/models/voice_welcome_config_model.dart';
|
|
|
|
import 'package:one_key/net/base_resp.dart';
|
|
|
|
import 'package:one_key/net/dio_util.dart';
|
|
|
|
import 'package:one_key/net/http_url.dart';
|
|
|
|
import 'package:one_key/provider/user_model.dart';
|
|
|
|
import 'package:one_key/res/colors.dart';
|
|
|
|
import 'package:one_key/utils/screen_util.dart';
|
|
|
|
import 'package:one_key/utils/utils.dart';
|
|
|
|
import 'package:one_key/widgets/MyDivider.dart';
|
|
|
|
import 'package:one_key/widgets/round_button.dart';
|
|
|
|
import 'package:one_key/widgets/system_app_bar.dart';
|
|
|
|
import 'package:one_key/widgets/v_empty_view.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
|
|
|
|
/***
|
|
|
|
* 语音欢迎致辞设置
|
|
|
|
*/
|
|
|
|
class VoiceWelcomeSettingPage extends StatefulWidget {
|
|
|
|
VoiceWelcomeSettingPage({Key? key}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
_VoiceWelcomeSettingPageState createState() =>
|
|
|
|
_VoiceWelcomeSettingPageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _VoiceWelcomeSettingPageState extends State<VoiceWelcomeSettingPage> {
|
|
|
|
bool addVoiceInfo = false; //预订安排中附加语音欢迎致辞
|
|
|
|
bool guestVoiceSame = true; //被请人语音播报与预订人一致
|
|
|
|
bool specialVoiceEnabled = false; //是否启用特殊用餐类型语音播报
|
|
|
|
|
|
|
|
TextEditingController voiceIncoC = TextEditingController(); //预订人语音播报
|
|
|
|
TextEditingController guestDefaultC = TextEditingController(); //被请人默认
|
|
|
|
TextEditingController guestSpecialC = TextEditingController(); //被请人特殊
|
|
|
|
|
|
|
|
FocusNode voiceIncoNode = FocusNode();
|
|
|
|
FocusNode guestDefaultNode = FocusNode();
|
|
|
|
FocusNode guestSpecialNode = FocusNode();
|
|
|
|
|
|
|
|
List<VoiceWelcomePlaceholderModel> changeFieldData = []; //可变字段标签
|
|
|
|
List<GetReserveTypeFieldsSunModel>? mealTypes = []; //用餐类型
|
|
|
|
bool mealTypesError = false; //用餐类型接口加载失败
|
|
|
|
|
|
|
|
static const String defaultVoiceText =
|
|
|
|
'尊敬的贵宾,您好!\n欢迎您选择本店。\n您的就餐安排在{预订日期},{餐段},坐席位于{桌位}。\n预祝您用餐愉快,期待您的光临!';
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
voiceIncoC.text = defaultVoiceText;
|
|
|
|
guestDefaultC.text = defaultVoiceText;
|
|
|
|
guestSpecialC.text = defaultVoiceText;
|
|
|
|
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
|
_getData();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
voiceIncoC.dispose();
|
|
|
|
guestDefaultC.dispose();
|
|
|
|
guestSpecialC.dispose();
|
|
|
|
voiceIncoNode.dispose();
|
|
|
|
guestDefaultNode.dispose();
|
|
|
|
guestSpecialNode.dispose();
|
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
_getData() async {
|
|
|
|
try {
|
|
|
|
String? sid =
|
|
|
|
Provider.of<UserModel>(context, listen: false).user?.sellerid;
|
|
|
|
BaseResp<dynamic> baseResp = await DioUtil().request<dynamic>(
|
|
|
|
context, Method.post, HttpUrl.get_voice_welcome_config,
|
|
|
|
data: {'sid': sid}, showLoading: false);
|
|
|
|
if (baseResp.code == Constant.status_success &&
|
|
|
|
baseResp.data != null &&
|
|
|
|
baseResp.data is Map) {
|
|
|
|
VoiceWelcomeConfigModel model = VoiceWelcomeConfigModel.fromJson(
|
|
|
|
baseResp.data as Map<String, dynamic>);
|
|
|
|
addVoiceInfo = model.isVoiceWelcome == '1' ? true : false;
|
|
|
|
guestVoiceSame =
|
|
|
|
model.inviteeSameAsReserver == '1' ? true : false;
|
|
|
|
voiceIncoC.text = (model.welcomeContent != null &&
|
|
|
|
model.welcomeContent!.isNotEmpty)
|
|
|
|
? model.welcomeContent!
|
|
|
|
: defaultVoiceText;
|
|
|
|
guestDefaultC.text = (model.inviteeDefaultContent != null &&
|
|
|
|
model.inviteeDefaultContent!.isNotEmpty)
|
|
|
|
? model.inviteeDefaultContent!
|
|
|
|
: defaultVoiceText;
|
|
|
|
guestSpecialC.text = (model.inviteeSpecialContent != null &&
|
|
|
|
model.inviteeSpecialContent!.isNotEmpty)
|
|
|
|
? model.inviteeSpecialContent!
|
|
|
|
: defaultVoiceText;
|
|
|
|
specialVoiceEnabled =
|
|
|
|
model.isInviteeSpecialEnabled == '1' ? true : false;
|
|
|
|
//可变字段按钮
|
|
|
|
changeFieldData = model.placeholderButtons ?? [];
|
|
|
|
//用餐类型及已选状态
|
|
|
|
mealTypes = [];
|
|
|
|
model.reserveTypeOptions?.forEach((v) {
|
|
|
|
GetReserveTypeFieldsSunModel temp =
|
|
|
|
GetReserveTypeFieldsSunModel(name: v, select: false);
|
|
|
|
if (model.specialReserveTypes != null &&
|
|
|
|
model.specialReserveTypes!.contains(v)) {
|
|
|
|
temp.select = true;
|
|
|
|
}
|
|
|
|
mealTypes!.add(temp);
|
|
|
|
});
|
|
|
|
mealTypesError = false;
|
|
|
|
} else {
|
|
|
|
mealTypesError = true;
|
|
|
|
if (baseResp.msg != null && baseResp.msg!.isNotEmpty) {
|
|
|
|
Utils.showToast(baseResp.msg!);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
print(error.toString());
|
|
|
|
mealTypesError = true;
|
|
|
|
}
|
|
|
|
if (mounted) {
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///在光标处插入可变字段
|
|
|
|
_insertField(
|
|
|
|
TextEditingController controller, VoiceWelcomePlaceholderModel field) {
|
|
|
|
FocusScope.of(context).requestFocus(FocusNode()); //隐藏键盘
|
|
|
|
int cursorPosition = controller.selection.baseOffset;
|
|
|
|
if (cursorPosition != -1) {
|
|
|
|
controller.text = controller.text.substring(0, cursorPosition) +
|
|
|
|
(field.placeholder ?? '') +
|
|
|
|
controller.text.substring(cursorPosition);
|
|
|
|
controller.selection = TextSelection.fromPosition(
|
|
|
|
TextPosition(
|
|
|
|
offset: cursorPosition + field.placeholder!.length,
|
|
|
|
affinity: TextAffinity.downstream));
|
|
|
|
} else {
|
|
|
|
controller.text += field.placeholder ?? '';
|
|
|
|
}
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
|
|
|
|
///可变字段标签(全部青绿实底白字)
|
|
|
|
Widget _fieldChip(
|
|
|
|
TextEditingController controller, VoiceWelcomePlaceholderModel field) {
|
|
|
|
return InkWell(
|
|
|
|
onTap: () {
|
|
|
|
_insertField(controller, field);
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
padding: EdgeInsets.symmetric(horizontal: w(8), vertical: w(5)),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: MyColours.color_529EA4,
|
|
|
|
borderRadius: BorderRadius.circular(r(5)),
|
|
|
|
),
|
|
|
|
child: Text(
|
|
|
|
field.name!,
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_ffffff,
|
|
|
|
fontSize: font(12),
|
|
|
|
fontWeight: FontWeight.bold),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _chipsWrap(
|
|
|
|
TextEditingController controller, List<VoiceWelcomePlaceholderModel> data) {
|
|
|
|
return Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(30)),
|
|
|
|
child: Wrap(
|
|
|
|
spacing: w(10),
|
|
|
|
runSpacing: w(10),
|
|
|
|
children:
|
|
|
|
data.map((e) => _fieldChip(controller, e)).toList(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _sectionHeader(String title, {double? left}) {
|
|
|
|
return Padding(
|
|
|
|
padding: EdgeInsets.only(left: left ?? w(16)),
|
|
|
|
child: Align(
|
|
|
|
alignment: Alignment.centerLeft,
|
|
|
|
child: Text(
|
|
|
|
title,
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_666666,
|
|
|
|
fontSize: font(12)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///特殊用餐类型标题行(右侧带启用复选框)
|
|
|
|
Widget _specialHeader() {
|
|
|
|
return InkWell(
|
|
|
|
onTap: () {
|
|
|
|
setState(() {
|
|
|
|
specialVoiceEnabled = !specialVoiceEnabled;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
child: Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(30), right: w(16)),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: Text(
|
|
|
|
'被请人语音播报设置(特殊用餐类型)',
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_666666, fontSize: font(12)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Image.asset(
|
|
|
|
Utils.getImgPath(
|
|
|
|
specialVoiceEnabled ? 'f_select' : 'f_select_not'),
|
|
|
|
width: w(22),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _divider() {
|
|
|
|
return Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(16), right: w(12)),
|
|
|
|
child: MyDivider(double.infinity, w(0.5),
|
|
|
|
color: MyColours.color_E7E7E7),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _textArea(TextEditingController controller, String hint) {
|
|
|
|
return Container(
|
|
|
|
width: double.infinity,
|
|
|
|
margin: EdgeInsets.symmetric(horizontal: w(30)),
|
|
|
|
padding: EdgeInsets.symmetric(horizontal: w(10), vertical: w(10)),
|
|
|
|
alignment: Alignment.topLeft,
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: MyColours.color_ffffff,
|
|
|
|
border: Border.all(color: MyColours.color_DBDBDB, width: w(1)),
|
|
|
|
borderRadius: BorderRadius.circular(r(10)),
|
|
|
|
),
|
|
|
|
child: TextField(
|
|
|
|
controller: controller,
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_777777,
|
|
|
|
fontSize: font(14),
|
|
|
|
textBaseline: TextBaseline.alphabetic),
|
|
|
|
textAlignVertical: TextAlignVertical.center,
|
|
|
|
maxLines: 7,
|
|
|
|
decoration: InputDecoration(
|
|
|
|
hintText: hint,
|
|
|
|
hintStyle: TextStyle(
|
|
|
|
color: MyColours.color_999999,
|
|
|
|
fontSize: font(14),
|
|
|
|
),
|
|
|
|
contentPadding: EdgeInsets.zero,
|
|
|
|
border: OutlineInputBorder(borderSide: BorderSide.none),
|
|
|
|
),
|
|
|
|
keyboardType: TextInputType.multiline,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _hintText() {
|
|
|
|
return Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(30)),
|
|
|
|
child: Align(
|
|
|
|
alignment: Alignment.centerLeft,
|
|
|
|
child: Text(
|
|
|
|
'*{预订日期}、{餐段}、{桌位}不能修改,可以删除。',
|
|
|
|
style: TextStyle(color: MyColours.color_B0B0B0, fontSize: font(12)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _radioRow(String title, bool selected, VoidCallback onTap) {
|
|
|
|
return InkWell(
|
|
|
|
onTap: onTap,
|
|
|
|
child: Container(
|
|
|
|
width: double.infinity,
|
|
|
|
padding: EdgeInsets.only(
|
|
|
|
left: w(16), right: w(16), top: w(20), bottom: w(20)),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: Text(
|
|
|
|
title,
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_666666, fontSize: font(14)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Image.asset(
|
|
|
|
Utils.getImgPath(selected ? 'f_radio_sel' : 'f_radio_un'),
|
|
|
|
width: w(20),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _mealChipsWrap() {
|
|
|
|
if (mealTypes == null || mealTypes!.isEmpty) {
|
|
|
|
return InkWell(
|
|
|
|
onTap: () {
|
|
|
|
_getData();
|
|
|
|
},
|
|
|
|
child: Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(30)),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
'暂无用餐类型数据,点击重试',
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_666666, fontSize: font(12)),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(30)),
|
|
|
|
child: Wrap(
|
|
|
|
spacing: w(10),
|
|
|
|
runSpacing: w(10),
|
|
|
|
children: mealTypes!.map((item) {
|
|
|
|
bool selected = item.select ?? false;
|
|
|
|
return InkWell(
|
|
|
|
onTap: () {
|
|
|
|
setState(() {
|
|
|
|
item.select = !selected;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
padding: EdgeInsets.symmetric(horizontal: w(10), vertical: w(5)),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: selected
|
|
|
|
? MyColours.color_529EA4
|
|
|
|
: MyColours.color_ffffff,
|
|
|
|
borderRadius: BorderRadius.circular(r(5)),
|
|
|
|
border: Border.all(
|
|
|
|
width: w(1),
|
|
|
|
color: selected
|
|
|
|
? MyColours.color_529EA4
|
|
|
|
: MyColours.color_B7B7B7),
|
|
|
|
),
|
|
|
|
child: Text(
|
|
|
|
item.name ?? '',
|
|
|
|
style: TextStyle(
|
|
|
|
color: selected
|
|
|
|
? MyColours.color_ffffff
|
|
|
|
: MyColours.color_B0B0B0,
|
|
|
|
fontSize: font(12),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}).toList(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
_save() async {
|
|
|
|
if (addVoiceInfo && voiceIncoC.text.trim().isEmpty) {
|
|
|
|
Utils.showToast('请输入语音欢迎致辞!');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
List<String> selectedMealTypes = [];
|
|
|
|
mealTypes?.forEach((item) {
|
|
|
|
if (item.select ?? false) {
|
|
|
|
selectedMealTypes.add(item.name ?? '');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Map<String, String?> params = {
|
|
|
|
'sid': Provider.of<UserModel>(context, listen: false).user?.sellerid,
|
|
|
|
'is_voice_welcome': addVoiceInfo ? '1' : '0',
|
|
|
|
'welcome_content': voiceIncoC.text,
|
|
|
|
'invitee_same_as_reserver': guestVoiceSame ? '1' : '0',
|
|
|
|
'invitee_default_content': guestDefaultC.text,
|
|
|
|
'invitee_special_content': guestSpecialC.text,
|
|
|
|
'special_reserve_types': json.encode(selectedMealTypes),
|
|
|
|
'is_invitee_special_enabled': specialVoiceEnabled ? '1' : '0',
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
BaseResp<dynamic> baseResp = await DioUtil().request<dynamic>(
|
|
|
|
context, Method.post, HttpUrl.save_voice_welcome_config,
|
|
|
|
data: params, showLoading: true);
|
|
|
|
if (baseResp.code == Constant.status_success) {
|
|
|
|
Utils.showToast('保存成功');
|
|
|
|
if (Navigator.canPop(context)) {
|
|
|
|
Navigator.pop(context);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (baseResp.msg != null && baseResp.msg!.isNotEmpty) {
|
|
|
|
Utils.showToast(baseResp.msg!);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
print(error.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
|
|
|
backgroundColor: MyColours.color_ffffff,
|
|
|
|
appBar: SystemAppBar('语音欢迎致辞设置'),
|
|
|
|
body: Column(
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: SingleChildScrollView(
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
//预订安排中附加语音欢迎致辞
|
|
|
|
InkWell(
|
|
|
|
onTap: () {
|
|
|
|
setState(() {
|
|
|
|
addVoiceInfo = !addVoiceInfo;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
width: double.infinity,
|
|
|
|
margin: EdgeInsets.only(left: w(16), right: w(16)),
|
|
|
|
padding:
|
|
|
|
EdgeInsets.symmetric(vertical: w(24)),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
'预订安排中附加语音欢迎致辞',
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_666666,
|
|
|
|
fontSize: font(16)),
|
|
|
|
),
|
|
|
|
Spacer(),
|
|
|
|
Image.asset(
|
|
|
|
Utils.getImgPath(
|
|
|
|
addVoiceInfo ? 'swich_on' : 'swich_off'),
|
|
|
|
width: w(44),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
_divider(),
|
|
|
|
if (addVoiceInfo) ...[
|
|
|
|
VEmptyView(8),
|
|
|
|
_sectionHeader('预订人语音播报设置'),
|
|
|
|
VEmptyView(16),
|
|
|
|
_textArea(voiceIncoC, '点击录入语音欢迎致辞'),
|
|
|
|
VEmptyView(16),
|
|
|
|
_hintText(),
|
|
|
|
VEmptyView(16),
|
|
|
|
_chipsWrap(voiceIncoC, changeFieldData),
|
|
|
|
VEmptyView(24),
|
|
|
|
_divider(),
|
|
|
|
VEmptyView(24),
|
|
|
|
_sectionHeader('被请人语音播报设置'),
|
|
|
|
VEmptyView(24),
|
|
|
|
_radioRow('被请人语音播报与预订人一致', guestVoiceSame, () {
|
|
|
|
setState(() {
|
|
|
|
guestVoiceSame = true;
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
_divider(),
|
|
|
|
_radioRow('被请人语音播报与预订人不一致', !guestVoiceSame, () {
|
|
|
|
setState(() {
|
|
|
|
guestVoiceSame = false;
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
if (!guestVoiceSame) ...[
|
|
|
|
_divider(),
|
|
|
|
VEmptyView(16),
|
|
|
|
_sectionHeader('被请人语音播报设置(默认)', left: w(30)),
|
|
|
|
VEmptyView(16),
|
|
|
|
_textArea(guestDefaultC, '点击录入被请人语音播报'),
|
|
|
|
VEmptyView(16),
|
|
|
|
_hintText(),
|
|
|
|
VEmptyView(16),
|
|
|
|
_chipsWrap(guestDefaultC, changeFieldData),
|
|
|
|
VEmptyView(24),
|
|
|
|
_specialHeader(),
|
|
|
|
if (specialVoiceEnabled) ...[
|
|
|
|
VEmptyView(16),
|
|
|
|
_textArea(guestSpecialC, '点击录入特殊用餐类型语音播报'),
|
|
|
|
VEmptyView(16),
|
|
|
|
_hintText(),
|
|
|
|
VEmptyView(16),
|
|
|
|
_chipsWrap(guestSpecialC, changeFieldData),
|
|
|
|
VEmptyView(24),
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsets.only(left: w(30)),
|
|
|
|
child: Text(
|
|
|
|
'请选择该语音播报适用的用餐类型',
|
|
|
|
style: TextStyle(
|
|
|
|
color: MyColours.color_666666,
|
|
|
|
fontSize: font(12)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
VEmptyView(16),
|
|
|
|
_mealChipsWrap(),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
VEmptyView(32),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Container(
|
|
|
|
color: MyColours.color_ffffff,
|
|
|
|
padding: EdgeInsets.only(
|
|
|
|
left: w(24), right: w(24), top: w(12), bottom: w(25)),
|
|
|
|
child: RoundButton(
|
|
|
|
text: '保存',
|
|
|
|
gradientStart: MyColours.color_529EA4,
|
|
|
|
gradientEnd: MyColours.color_529EA4,
|
|
|
|
radius: r(5),
|
|
|
|
fontSize: 34,
|
|
|
|
height: w(40),
|
|
|
|
isBold: true,
|
|
|
|
onPressed: () {
|
|
|
|
_save();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} |
...
|
...
|
|