You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
5.9 KiB
157 lines
5.9 KiB
1 year ago
|
import 'dart:ffi';
|
||
|
|
||
|
import 'package:flutter/cupertino.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_html/flutter_html.dart';
|
||
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||
|
import 'package:medicine_app/request_util.dart';
|
||
|
import 'package:medicine_app/slide_page_route.dart';
|
||
|
|
||
|
import 'medicine_detail_page.dart';
|
||
|
|
||
|
class SearchMedicinePage extends StatefulWidget {
|
||
|
SearchMedicinePage({Key? key}) : super(key: key);
|
||
|
|
||
|
@override
|
||
|
_SearchMedicinePageState createState() => _SearchMedicinePageState();
|
||
|
}
|
||
|
|
||
|
class _SearchMedicinePageState extends State<SearchMedicinePage> {
|
||
|
Future? _responseFuture = Future.value();
|
||
|
final _textEditingController = TextEditingController();
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Scaffold(
|
||
|
appBar: AppBar(
|
||
|
leading: IconButton(
|
||
|
color: Colors.black,
|
||
|
icon: Icon(Icons.arrow_back_ios),
|
||
|
iconSize: 18,
|
||
|
onPressed: () => Navigator.of(context).pop(),
|
||
|
),
|
||
|
backgroundColor: Colors.white,
|
||
|
elevation: 0.4,
|
||
|
titleSpacing: 0,
|
||
|
toolbarHeight: 55,
|
||
|
title: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||
|
children: [
|
||
|
Expanded(
|
||
|
child: Container(
|
||
|
height: 32,
|
||
|
child: TextField(
|
||
|
autofocus: false,
|
||
|
controller: _textEditingController,
|
||
|
style: TextStyle(fontSize: 15),
|
||
|
cursorColor: Theme.of(context).primaryColor,
|
||
|
decoration: InputDecoration(
|
||
|
suffixIcon: IconButton(
|
||
|
icon: Icon(Icons.close_rounded, size: 17),
|
||
|
color: Theme.of(context).primaryColor,
|
||
|
onPressed: () => _textEditingController.clear(),
|
||
|
),
|
||
|
contentPadding: EdgeInsets.zero,
|
||
|
focusColor: Theme.of(context).primaryColor,
|
||
|
border: OutlineInputBorder(
|
||
|
borderRadius: BorderRadius.circular(15),
|
||
|
borderSide: BorderSide(
|
||
|
color: Theme.of(context).primaryColor,
|
||
|
width: 1,
|
||
|
)),
|
||
|
focusedBorder: OutlineInputBorder(
|
||
|
borderRadius: BorderRadius.circular(15),
|
||
|
borderSide: BorderSide(
|
||
|
color: Theme.of(context).primaryColor,
|
||
|
width: 1,
|
||
|
)),
|
||
|
enabledBorder: OutlineInputBorder(
|
||
|
borderRadius: BorderRadius.circular(15),
|
||
|
borderSide: BorderSide(
|
||
|
color: Theme.of(context).primaryColor,
|
||
|
width: 1,
|
||
|
)),
|
||
|
prefixIcon: Icon(
|
||
|
Icons.search_rounded,
|
||
|
color: Theme.of(context).primaryColor,
|
||
|
),
|
||
|
hintText: "请输入中药名",
|
||
|
hintStyle: TextStyle(fontSize: 14, color: Colors.grey.shade500),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
flex: 5,
|
||
|
),
|
||
|
Expanded(
|
||
|
child: TextButton(
|
||
|
onPressed: () async {
|
||
|
var response = await Request.getDio()
|
||
|
.get('/medicine/details', queryParameters: {'keyword': _textEditingController.text});
|
||
|
var data = response.data['data'] as List<dynamic>;
|
||
|
setState(() {
|
||
|
_responseFuture = Future.value(data);
|
||
|
});
|
||
|
},
|
||
|
child: Text('搜索'),
|
||
|
style: ButtonStyle(
|
||
|
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||
|
foregroundColor: MaterialStateProperty.all(Theme.of(context).primaryColor)),
|
||
|
),
|
||
|
flex: 1,
|
||
|
)
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
body: FutureBuilder(
|
||
|
future: _responseFuture ?? null,
|
||
|
builder: (BuildContext context, snapshot) {
|
||
|
if (snapshot.connectionState == ConnectionState.done) {
|
||
|
List? data = snapshot.data as List?;
|
||
|
if (data == null || data.length == 0) {
|
||
|
return Center(
|
||
|
child: Text('暂无结果'),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return ListView.separated(
|
||
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||
|
itemBuilder: (BuildContext context, int index) {
|
||
|
var item = data[index];
|
||
|
var medicineItem =
|
||
|
item.entries.where((element) => (element.key != 'name' && element.key != 'nameSource')).toList();
|
||
|
return GestureDetector(
|
||
|
onTap: () {
|
||
|
Navigator.of(context).push(SlidePageRoute(
|
||
|
builder: MedicineDetailPage(name: "${item['nameSource']}"),
|
||
|
));
|
||
|
},
|
||
|
child: Html(
|
||
|
data: '''<div>
|
||
|
<h4>${item['nameSource']}</h4>
|
||
|
<ul>
|
||
|
${medicineItem.map((e) {
|
||
|
return "<li><p>${e.key}</p><p>${e.value}</p></li>";
|
||
|
}).join()}
|
||
|
</ul>
|
||
|
<!--You can pretty much put any html in here!-->
|
||
|
</div>''',
|
||
|
),
|
||
|
);
|
||
|
},
|
||
|
separatorBuilder: (BuildContext context, int index) {
|
||
|
return Divider(
|
||
|
indent: 10, endIndent: 10, height: 0.8, color: Theme.of(context).primaryColor.withAlpha(80));
|
||
|
},
|
||
|
itemCount: data.length,
|
||
|
);
|
||
|
} else {
|
||
|
return SpinKitFadingCircle(
|
||
|
color: Theme.of(context).primaryColor,
|
||
|
size: 32,
|
||
|
);
|
||
|
}
|
||
|
}),
|
||
|
);
|
||
|
}
|
||
|
}
|