提交 00bf6349 authored 作者: Kevin's avatar Kevin

升级至flutter 2.0

上级 94fbf371
## [1.0.0]
* TODO: 升级至flutter 2.0
* TODO: 处理了空安全
## [0.6.3]
* TODO: 指定back_button_interceptor依赖
## [0.6.2]
* TODO: 指定back_button_interceptor依赖
## [0.6.1]
* TODO: CupertinoPopoverDirection添加了left和right
......
......@@ -6,6 +6,12 @@
Usage Add this to your package's pubspec.yaml file:
Flutter >=2.0
``` yaml
dependencies:
cool_ui: "^1.0.0"
```
Flutter >=1.17
``` yaml
dependencies:
......
......@@ -5,7 +5,9 @@ export "FLUTTER_APPLICATION_PATH=F:\TestCode\cool_ui\cool_ui\example"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build\ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
export "FLUTTER_FRAMEWORK_DIR=F:\flutter\bin\cache\artifacts\engine\ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"
......@@ -9,7 +9,7 @@ class TestKeyboard extends StatelessWidget{
return mediaQuery.size.width / 3 / 2 * 2;
}
final KeyboardController controller ;
const TestKeyboard({this.controller});
const TestKeyboard({required this.controller});
static register(){
CoolKeyboard.addKeyboard(TestKeyboard.inputType,KeyboardConfig(builder: (context,controller, params){
......@@ -70,17 +70,14 @@ class TestKeyboard extends StatelessWidget{
);
}
Widget buildButton(String title,{String value}){
if(value == null){
value = title;
}
Widget buildButton(String title,{String? value}){
return Container(
color: Colors.white,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Center(child: Text(title),),
onTap: (){
controller.addText(value);
controller.addText(value ?? title);
},
),
);
......
......@@ -39,7 +39,7 @@ class MyApp extends StatelessWidget {
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
MyHomePage({Key? key, this.title = ''}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
......
......@@ -59,13 +59,13 @@ class CustomKeyboardDemoState extends State<CustomKeyboardDemo> {
}));
}
static Future<String> showInputDialogs(
{@required BuildContext context,
Widget titleWidget,
Widget messageWidget,
List<TextInputFormatter> inputFormatters,
static Future<String?> showInputDialogs(
{required BuildContext context,
Widget? titleWidget,
Widget? messageWidget,
List<TextInputFormatter>? inputFormatters,
TextInputType keyboardType = TextInputType.number}) {
String value;
String? value;
return showCupertinoDialog<String>(
context: context,
builder: (context) {
......
......@@ -10,7 +10,7 @@ description: Cool UI Example
version: 1.0.0+1
environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
......
......@@ -4,11 +4,11 @@ typedef HideCallback = Future Function();
class WeuiToastWidget extends StatelessWidget {
const WeuiToastWidget({
Key key,
@required this.stopEvent,
@required this.alignment,
@required this.icon,
@required this.message,
Key? key,
required this.stopEvent,
required this.alignment,
required this.icon,
required this.message,
}) : super(key: key);
final bool stopEvent;
......@@ -68,16 +68,16 @@ class WeuiLoadingIcon extends StatefulWidget {
class WeuiLoadingIconState extends State<WeuiLoadingIcon>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _doubleAnimation;
AnimationController? _controller ;
Animation<double>? _doubleAnimation;
@override
void initState() {
super.initState();
_controller = new AnimationController(
_controller = AnimationController(
vsync: this, duration: Duration(milliseconds: 1000))
..repeat();
_doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller)
_doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller!)
..addListener(() {
setState(() {});
});
......@@ -86,14 +86,14 @@ class WeuiLoadingIconState extends State<WeuiLoadingIcon>
@override
void dispose() {
// TODO: implement dispose
_controller.dispose();
_controller!.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Transform.rotate(
angle: _doubleAnimation.value ~/ 30 * 30.0 * 0.0174533,
angle: _doubleAnimation!.value ~/ 30 * 30.0 * 0.0174533,
child: Image.asset("assets/images/loading.png",
package: "cool_ui", width: widget.size, height: widget.size));
}
......@@ -115,7 +115,7 @@ class WeuiToastConfigData{
this.loadingBackButtonClose = false,
this.toastAlignment = const Alignment(0.0, -0.2)});
copyWith({String successText,Duration successDuration,String loadingText,Alignment toastAlignment}){
copyWith({String? successText, Duration? successDuration, String? loadingText, Alignment? toastAlignment}){
return WeuiToastConfigData(
successText: successText ?? this.successText,
successDuration: successDuration ?? this.successDuration,
......@@ -126,8 +126,8 @@ class WeuiToastConfigData{
}
class WeuiToastConfig extends InheritedWidget{
final WeuiToastConfigData data;
WeuiToastConfig({Widget child,this.data}): super(child:child);
final WeuiToastConfigData? data;
WeuiToastConfig({required Widget child,this.data}): super(child:child);
@override
bool updateShouldNotify(WeuiToastConfig oldWidget) {
......@@ -137,21 +137,21 @@ class WeuiToastConfig extends InheritedWidget{
static WeuiToastConfigData of(BuildContext context) {
var widget = context.inheritFromWidgetOfExactType(WeuiToastConfig);
var widget = context.dependOnInheritedWidgetOfExactType<WeuiToastConfig>();
if(widget is WeuiToastConfig){
return widget.data;
return widget.data ?? WeuiToastConfigData();
}
return WeuiToastConfigData();
}
}
Future showWeuiSuccessToast(
{@required BuildContext context,
Widget message,
{required BuildContext context,
Widget? message,
stopEvent = false,
bool backButtonClose,
Alignment alignment,
Duration closeDuration}) {
bool? backButtonClose,
Alignment? alignment,
Duration? closeDuration}) {
var config = WeuiToastConfig.of(context);
message = message?? Text(config.successText);
......@@ -171,11 +171,11 @@ Future showWeuiSuccessToast(
}
HideCallback showWeuiLoadingToast(
{@required BuildContext context,
Widget message,
{required BuildContext context,
Widget? message,
stopEvent = true,
bool backButtonClose,
Alignment alignment}) {
bool? backButtonClose,
Alignment? alignment}) {
var config = WeuiToastConfig.of(context);
message = message?? Text(config.loadingText);
backButtonClose = backButtonClose ?? config.loadingBackButtonClose;
......@@ -192,20 +192,19 @@ HideCallback showWeuiLoadingToast(
int backButtonIndex = 2;
HideCallback showWeuiToast(
{@required BuildContext context,
@required Widget message,
@required Widget icon,
{required BuildContext context,
required Widget message,
required Widget icon,
bool stopEvent = false,
Alignment alignment,
bool backButtonClose}) {
Alignment? alignment,
bool backButtonClose = false}) {
var config = WeuiToastConfig.of(context);
alignment = alignment?? config.toastAlignment;
alignment = alignment ?? config.toastAlignment;
Completer<VoidCallback> result = Completer<VoidCallback>();
var backButtonName = 'CoolUI_WeuiToast$backButtonIndex';
BackButtonInterceptor.add((stopDefaultButtonEvent){
print(backButtonClose);
BackButtonInterceptor.add((stopDefaultButtonEvent, routeInfo){
if(backButtonClose){
result.future.then((hide){
hide();
......@@ -215,7 +214,7 @@ HideCallback showWeuiToast(
}, zIndex: backButtonIndex, name: backButtonName);
backButtonIndex++;
var overlay = OverlayEntry(
OverlayEntry? overlay = OverlayEntry(
maintainState: true,
builder: (_) => WillPopScope(
onWillPop: () async {
......@@ -224,7 +223,7 @@ HideCallback showWeuiToast(
return false;
},
child: WeuiToastWidget(
alignment: alignment,
alignment: alignment!,
icon: icon,
message: message,
stopEvent: stopEvent,
......@@ -234,11 +233,11 @@ HideCallback showWeuiToast(
if(overlay == null){
return;
}
overlay.remove();
overlay!.remove();
overlay = null;
BackButtonInterceptor.removeByName(backButtonName);
});
Overlay.of(context).insert(overlay);
Overlay.of(context)!.insert(overlay!);
return () async {
......
......@@ -3,7 +3,7 @@ part of cool_ui;
class KeyboardController extends ValueNotifier<TextEditingValue>{
final InputClient client;
KeyboardController({TextEditingValue value,this.client})
KeyboardController({TextEditingValue? value,required this.client})
: super(value == null ? TextEditingValue.empty : value);
......
......@@ -3,8 +3,7 @@ part of cool_ui;
class KeyboardMediaQuery extends StatefulWidget{
final Widget child;
KeyboardMediaQuery({this.child})
: assert(child != null);
KeyboardMediaQuery({required this.child});
@override
State<StatefulWidget> createState() =>KeyboardMediaQueryState();
......@@ -12,23 +11,22 @@ class KeyboardMediaQuery extends StatefulWidget{
}
class KeyboardMediaQueryState extends State<KeyboardMediaQuery >{
double keyboardHeight;
ValueNotifier<double> keyboardHeightNotifier;
double keyboardHeight = 0;
ValueNotifier<double> keyboardHeightNotifier = CoolKeyboard._keyboardHeightNotifier;
@override
void initState(){
super.initState();
CoolKeyboard._keyboardHeightNotifier.addListener(onUpdateHeight);
keyboardHeightNotifier = CoolKeyboard._keyboardHeightNotifier;
}
@override
Widget build(BuildContext context) {
// TODO: implement build
var data = MediaQuery.of(context, nullOk: true);
var data = MediaQuery.maybeOf(context);
if(data == null){
data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window);
}
var bottom = CoolKeyboard._keyboardHeightNotifier.value ?? data.viewInsets.bottom;
// TODO: implement build
......@@ -43,7 +41,7 @@ class KeyboardMediaQueryState extends State<KeyboardMediaQuery >{
}
onUpdateHeight(){
WidgetsBinding.instance.addPostFrameCallback((_){
WidgetsBinding.instance!.addPostFrameCallback((_){
setState(()=>{});
});
}
......
......@@ -7,7 +7,7 @@ class KeyboardRootWidget extends StatefulWidget {
final TextDirection textDirection;
const KeyboardRootWidget(
{Key key, this.child, this.textDirection = TextDirection.ltr})
{Key? key, required this.child, this.textDirection = TextDirection.ltr})
: super(key: key);
@override
......@@ -18,7 +18,7 @@ class KeyboardRootWidget extends StatefulWidget {
}
class KeyboardRootState extends State<KeyboardRootWidget> {
WidgetBuilder _keyboardbuilder;
WidgetBuilder? _keyboardbuilder;
bool get hasKeyboard => _keyboardbuilder != null;
// List<OverlayEntry> _initialEntries = [];
......@@ -38,7 +38,7 @@ class KeyboardRootState extends State<KeyboardRootWidget> {
List<Widget> children = [widget.child];
if (_keyboardbuilder != null) {
children.add(Builder(
builder: _keyboardbuilder,
builder: _keyboardbuilder!,
));
}
return Directionality(
......
......@@ -7,7 +7,7 @@ class NumberKeyboard extends StatelessWidget{
return mediaQuery.size.width / 3 / 2 * 4;
}
final KeyboardController controller ;
const NumberKeyboard({this.controller});
const NumberKeyboard({required this.controller});
static register(){
CoolKeyboard.addKeyboard(NumberKeyboard.inputType,KeyboardConfig(builder: (context,controller, params){
......@@ -68,17 +68,14 @@ class NumberKeyboard extends StatelessWidget{
);
}
Widget buildButton(String title,{String value}){
if(value == null){
value = title;
}
Widget buildButton(String title,{String? value}){
return Container(
color: Colors.white,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Center(child: Text(title),),
onTap: (){
controller.addText(value);
controller.addText(value ?? title);
},
),
);
......
......@@ -34,7 +34,7 @@ class _ScreenUtil {
double _bottomBarHeight = 0.0;
double _appBarHeight = 0.0;
double _textScaleFactor = 0.0;
MediaQueryData _mediaQueryData;
MediaQueryData? _mediaQueryData;
static final _ScreenUtil _singleton = _ScreenUtil();
......@@ -82,7 +82,7 @@ class _ScreenUtil {
double get bottomBarHeight => _bottomBarHeight;
/// media Query Data
MediaQueryData get mediaQueryData => _mediaQueryData;
MediaQueryData? get mediaQueryData => _mediaQueryData;
/// screen width
/// 当前屏幕 宽
......
......@@ -11,8 +11,8 @@ part of cool_ui;
/// Widget Util.
class _WidgetUtil {
bool _hasMeasured = false;
double _width;
double _height;
double? _width;
double? _height;
/// Widget rendering listener.
/// Widget渲染监听.
......@@ -22,8 +22,8 @@ class _WidgetUtil {
void asyncPrepare(
BuildContext context, bool isOnce, ValueChanged<Rect> onCallBack) {
if (_hasMeasured) return;
WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) {
RenderBox box = context.findRenderObject();
WidgetsBinding.instance!.addPostFrameCallback((Duration timeStamp) {
RenderBox? box = context.findRenderObject() as RenderBox?;
if (box != null && box.semanticBounds != null) {
if (isOnce) _hasMeasured = true;
double width = box.semanticBounds.width;
......@@ -38,9 +38,9 @@ class _WidgetUtil {
}
/// Widget渲染监听.
void asyncPrepares(bool isOnce, ValueChanged<Rect> onCallBack) {
void asyncPrepares(bool isOnce, ValueChanged<Rect?>? onCallBack) {
if (_hasMeasured) return;
WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) {
WidgetsBinding.instance!.addPostFrameCallback((Duration timeStamp) {
if (isOnce) _hasMeasured = true;
if (onCallBack != null) onCallBack(null);
});
......@@ -49,8 +49,8 @@ class _WidgetUtil {
///get Widget Bounds (width, height, left, top, right, bottom and so on).Widgets must be rendered completely.
///获取widget Rect
static Rect getWidgetBounds(BuildContext context) {
RenderBox box = context.findRenderObject();
return (box != null && box.semanticBounds != null)
RenderBox? box = context.findRenderObject() as RenderBox?;
return (box != null)
? box.semanticBounds
: Rect.zero;
}
......@@ -58,7 +58,7 @@ class _WidgetUtil {
///Get the coordinates of the widget on the screen.Widgets must be rendered completely.
///获取widget在屏幕上的坐标,widget必须渲染完成
static Offset getWidgetLocalToGlobal(BuildContext context) {
RenderBox box = context.findRenderObject();
RenderBox? box = context.findRenderObject() as RenderBox?;
return box == null ? Offset.zero : box.localToGlobal(Offset.zero);
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ part of cool_ui;
class CupertinoPopoverMenuList extends StatelessWidget {
final List<Widget> children;
const CupertinoPopoverMenuList({this.children});
const CupertinoPopoverMenuList({this.children = const []});
@override
Widget build(BuildContext context) {
......@@ -25,16 +25,16 @@ class CupertinoPopoverMenuList extends StatelessWidget {
}
class CupertinoPopoverMenuItem extends StatefulWidget {
final Widget leading;
final Widget? leading;
final Widget child;
final BoolCallback onTap;
final BoolCallback? onTap;
final bool isTapClosePopover;
final Color activeBackground;
final Color background;
const CupertinoPopoverMenuItem(
{this.leading,
this.child,
required this.child,
this.onTap,
this.background = Colors.white,
this.activeBackground = const Color(0xFFd9d9d9),
......@@ -57,7 +57,7 @@ class CupertinoPopoverMenuItemState extends State<CupertinoPopoverMenuItem> {
height: 35.0,
child: IconTheme(
data: IconThemeData(color: Color(0xff007aff), size: 20.0),
child: widget.leading),
child: widget.leading!),
));
}
widgets.add(Expanded(
......@@ -75,7 +75,7 @@ class CupertinoPopoverMenuItemState extends State<CupertinoPopoverMenuItem> {
setState(() {
isDown = false;
});
if (widget.onTap != null && widget.onTap()) {
if (widget.onTap != null && widget.onTap!()) {
return;
}
if (widget.isTapClosePopover) {
......
......@@ -54,9 +54,9 @@ class CoolTableState extends State<CoolTable>{
}
class CoolColumnInfo{
final double flex;
final double width;
final Widget title;
final double? flex;
final double? width;
final Widget? title;
const CoolColumnInfo({this.flex, this.width, this.title});
}
\ No newline at end of file
......@@ -5,15 +5,15 @@ typedef PaintCallback = void Function(PaintingContext context, Offset offset,Siz
class PaintEvent extends SingleChildRenderObjectWidget{
final PaintCallback paintBefore;
final PaintCallback paintAfter;
final PaintCallback? paintBefore;
final PaintCallback? paintAfter;
const PaintEvent({
Key key,
Key? key,
this.paintBefore,
this.paintAfter,
Widget child
Widget? child
}) :
super(key: key, child: child);
@override
......@@ -34,11 +34,11 @@ class PaintEvent extends SingleChildRenderObjectWidget{
class PaintEventProxyBox extends RenderProxyBox{
PaintCallback paintBefore;
PaintCallback paintAfter;
PaintCallback? paintBefore;
PaintCallback? paintAfter;
PaintEventProxyBox({
RenderBox child,
RenderBox? child,
this.paintBefore,
this.paintAfter
}):super(child);
......@@ -51,11 +51,8 @@ class PaintEventProxyBox extends RenderProxyBox{
@override
void paint(PaintingContext context, Offset offset) {
assert(size.width != null);
assert(size.height != null);
if(this.paintBefore != null){
this.paintBefore(context,offset,size);
this.paintBefore!(context,offset,size);
}
super.paint(context, offset);
......@@ -63,7 +60,7 @@ class PaintEventProxyBox extends RenderProxyBox{
if(this.paintAfter != null){
this.paintAfter(context,offset,size);
this.paintAfter!(context,offset,size);
}
}
......
set PUB_HOSTED_URL=
set FLUTTER_STORAGE_BASE_URL=
set http_proxy=http://127.0.0.1:1080
set https_proxy=https://127.0.0.1:1080
set http_proxy=http://127.0.0.1:7890 & set https_proxy=http://127.0.0.1:7890
flutter packages pub publish
\ No newline at end of file
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.13"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
version: "2.5.0"
back_button_interceptor:
dependency: "direct main"
description:
name: back_button_interceptor
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.2.2"
version: "5.0.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.3"
collection:
version: "1.2.0"
clock:
dependency: transitive
description:
name: collection
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.14.12"
convert:
version: "1.1.0"
collection:
dependency: transitive
description:
name: convert
name: collection
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
crypto:
version: "1.15.0"
fake_async:
dependency: transitive
description:
name: crypto
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
......@@ -74,48 +67,27 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
image:
dependency: transitive
description:
name: image
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.12"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.6"
version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.8"
version: "1.3.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.4"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.0"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
version: "1.8.0"
sky_engine:
dependency: transitive
description: flutter
......@@ -127,63 +99,56 @@ packages:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.7.0"
version: "1.8.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.3"
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.5"
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.15"
version: "0.2.19"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.6"
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.8"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.6.1"
version: "2.1.0"
sdks:
dart: ">=2.6.0 <3.0.0"
flutter: ">=1.17.0 <2.0.0"
dart: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
name: cool_ui
description: Some practical Widget for flutter,Popover,Weui,Custom Keyboard
version: 0.6.1
version: 1.0.0
author: Kevin <liangkaikevin@gmail.com>
homepage: https://github.com/Im-Kevin/cool_ui
environment:
sdk: ">=2.0.0 <3.0.0"
flutter: ">=1.17.0 <2.0.0"
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0 <3.0.0"
dependencies:
back_button_interceptor: ^4.0.6
back_button_interceptor: 5.0.0
flutter:
sdk: flutter
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论