普通视图

发现新文章,点击刷新页面。
昨天 — 2025年12月26日首页

中国人民银行:实施更加积极有为的宏观政策,防范化解重点领域风险

2025年12月26日 20:03
36氪获悉,中国人民银行发布《中国金融稳定报告(2025)》报告指出,金融系统将坚持以习近平新时代中国特色社会主义思想为指导,全面贯彻落实党的二十大和二十届二中、三中、四中全会精神,按照中央经济工作会议、中央金融工作会议部署,统筹国内国际两个大局,完整准确全面贯彻新发展理念,加快构建新发展格局,坚持稳中求进工作总基调,实施更加积极有为的宏观政策,防范化解重点领域风险,为实现“十五五”良好开局打牢基础。

淘宝闪购启动“燎原深耕计划”:加大技术投入,助力服务商提质增效、商家持续增收

2025年12月26日 21:26
12月26日,淘宝闪购官方生态餐饮服务商大会在杭州举行,来自全国各地的百余位官方服务商代表、城市运营团队及行业专家出席会议。会上,淘宝闪购宣布启动“燎原深耕计划”,将通过政策扶持、组织建设与AI技术三位一体的系统性支持,持续加大对官方生态伙伴的战略投入,助力服务商运营团队及商家伙伴把握确定性增长,共建高效、韧性、可持续的商家服务新生态。

“光因科技”获亿元级A+轮融资

2025年12月26日 21:13
近日,钙钛矿光伏企业 “光因科技”宣布完成亿元级A+轮融资。本轮融资由启赋资本、神骐资本等投资机构投资。光因科技将此次资金重点用于加速200MW量产线产能释放、拓展3C消费电子与IoT无源终端场景落地。

大烨智能:涉嫌信息披露违法违规被中国证监会立案

2025年12月26日 20:58
36氪获悉,大烨智能公告,公司于2025年12月26日收到中国证监会下发的《立案告知书》,因公司涉嫌信息披露违法违规,根据相关法律法规,中国证监会决定对公司立案。立案调查期间,公司将积极配合中国证监会的各项工作,并履行信息披露义务。目前,公司生产经营正常,上述事项不会对公司的正常生产经营活动产生重大影响。

派瑞股份:因涉嫌信息披露违法违规被中国证监会立案

2025年12月26日 20:56
36氪获悉,派瑞股份公告,公司于2025年12月26日收到中国证监会下发的《立案告知书》,因公司涉嫌信息披露违法违规,中国证监会决定对公司立案。公司自查发现,2024年度一笔销售合同中部分收入存在延期确认的会计处理差错,并已对所涉定期报告进行会计差错更正及追溯调整。目前公司各项经营活动和业务均正常开展,将积极配合中国证监会的各项工作,并持续关注上述事项的进展情况。

Flutter组件封装:视频播放组件全局封装

作者 SoaringHeart
2025年12月26日 20:52

一、需求来源

最近要开发一个在线视频播放的功能,每次实时获取播放,有些卡顿和初始化慢的问题,就随手优化一下。

二、使用示例

1、数据源

class VideoDetailsProvider extends ChangeNotifier {

    /// 当前播放中的
    final _videoModelController = StreamController<VideoDetailModel?>.broadcast();

    /// 当前播放中 Stream<VideoDetailModel>
    Stream<VideoDetailModel?> get videoModelStream => _videoModelController.stream;


    /// 点击(model不为空时播放,为空时关闭)
    sinkModelForVideoPlayer({required VideoDetailModel? model}) {
      _videoModelController.add(model);
    }

}

2、显示播放器组件

StreamBuilder<VideoDetailModel?>(
  stream: provider.videoModelStream,
  builder: (context, snapshot) {
    if (snapshot.data == null) {
      return const SizedBox();
    }
    final model = snapshot.data;
    if (model?.isVideo != true) {
      return const SizedBox();
    }

    return SafeArea(
      top: true,
      bottom: false,
      left: false,
      right: false,
      child: Container(
        decoration: BoxDecoration(
          color: Colors.black,
        ),
        child: AppVideoPlayer(
          key: Key(model?.url ?? ""),
          url: model?.url ?? "",
          onFullScreen: (value) async {
            if (!value) {
              await Future.delayed(const Duration(milliseconds: 300));//等待旋转完成
              SystemChromeExt.changeDeviceOrientation(isPortrait: true);
            }
          },
          onClose: () {
            DLog.d("close");
            provider.sinkModelForVideoPlayer(model: null);
          },
        ),
      ),
    );
  },
)

三、源码

1、AppVideoPlayer.dart

//
//  AppVideoPlayer.dart
//  flutter_templet_project
//
//  Created by shang on 2025/12/12 18:11.
//  Copyright © 2025/12/12 shang. All rights reserved.
//

import 'package:chewie/chewie.dart';
import 'package:flutter/material.dart';
import 'package:flutter_templet_project/basicWidget/AppVideoPlayer/AppVideoPlayerService.dart';
import 'package:flutter_templet_project/extension/extension_local.dart';
import 'package:video_player/video_player.dart';

/// 播放器
class AppVideoPlayer extends StatefulWidget {
  const AppVideoPlayer({
    super.key,
    this.controller,
    required this.url,
    this.autoPlay = true,
    this.looping = false,
    this.aspectRatio = 16 / 9,
    this.isPortrait = true,
    this.fullScreenVN,
    this.onFullScreen,
    this.onClose,
  });

  final AppVideoPlayerController? controller;

  final String url;
  final bool autoPlay;
  final bool looping;
  final double aspectRatio;

  /// 设备方向
  final bool isPortrait;

  final ValueNotifier<bool>? fullScreenVN;

  final void Function(bool isFullScreen)? onFullScreen;

  final VoidCallback? onClose;

  @override
  State<AppVideoPlayer> createState() => _AppVideoPlayerState();
}

class _AppVideoPlayerState extends State<AppVideoPlayer> with WidgetsBindingObserver, AutomaticKeepAliveClientMixin {
  VideoPlayerController? _videoController;
  ChewieController? _chewieController;

  Duration position = Duration.zero;

  @override
  void dispose() {
    widget.controller?._detach(this);
    WidgetsBinding.instance.removeObserver(this);
    _onClose();
    // 不销毁 VideoPlayerController,让全局复用
    // _chewieController?.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    widget.controller?._attach(this);
    WidgetsBinding.instance.addObserver(this);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      initPlayer();
    });
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.inactive:
      case AppLifecycleState.hidden:
      case AppLifecycleState.paused:
        {
          _chewieController?.pause();
        }
        break;
      case AppLifecycleState.detached:
        break;
      case AppLifecycleState.resumed:
        {
          _chewieController?.play();
        }
        break;
    }
  }

  Future<void> initPlayer() async {
    // DLog.d(widget.url.split("/").last);
    assert(widget.url.startsWith("http"), "url 错误");

    _videoController = await AppVideoPlayerService.instance.getController(widget.url);

    _chewieController?.dispose();
    _chewieController = ChewieController(
      videoPlayerController: _videoController!,
      autoPlay: widget.autoPlay,
      looping: widget.looping,
      aspectRatio: widget.aspectRatio,
      autoInitialize: true,
      allowFullScreen: true,
      allowMuting: false,
      showControlsOnInitialize: false,
      // customControls: const AppVideoControls(),
    );

    _chewieController!.addListener(() {
      final isFullScreen = _chewieController!.isFullScreen;
      widget.fullScreenVN?.value = isFullScreen;
      widget.onFullScreen?.call(isFullScreen);
      if (isFullScreen) {
        DLog.d("进入全屏");
      } else {
        DLog.d("退出全屏");
      }
    });
    if (mounted) {
      setState(() {});
    }
  }

  Future<void> _onClose() async {
    if (_videoController?.value.isPlaying == true) {
      _videoController?.pause();
    }
  }

  @override
  void didUpdateWidget(covariant AppVideoPlayer oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.url != widget.url) {
      initPlayer();
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    /// 🔥屏幕横竖切换时 rebuild Chewie,但不 rebuild video
    DLog.d([MediaQuery.of(context).orientation]);
    // setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    if (widget.url.startsWith("http") != true) {
      return const SizedBox();
    }

    if (_chewieController == null) {
      return const Center(child: CircularProgressIndicator());
    }
    // return Chewie(controller: _chewieController!);
    return Stack(
      children: [
        Positioned.fill(
          child: Chewie(
            controller: _chewieController!,
          ),
        ),
        Positioned(
          right: 20,
          top: 10,
          child: Container(
            // decoration: BoxDecoration(
            //   color: Colors.red,
            //   border: Border.all(color: Colors.blue),
            // ),
            child: buildCloseBtn(onTap: widget.onClose),
          ),
        ),
      ],
    );
  }

  Widget buildCloseBtn({VoidCallback? onTap}) {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () {
        DLog.d("buildCloseBtn");
        _onClose();
        if (onTap != null) {
          onTap();
          return;
        }
        Navigator.pop(context);
      },
      child: Container(
        // padding: EdgeInsets.all(6),
        // decoration: BoxDecoration(
        //   color: Colors.black54,
        //   shape: BoxShape.circle,
        //   border: Border.all(color: Colors.blue),
        // ),
        child: const Icon(Icons.close, color: Colors.white, size: 24),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

class AppVideoPlayerController {
  _AppVideoPlayerState? _anchor;

  void _attach(_AppVideoPlayerState anchor) {
    _anchor = anchor;
  }

  void _detach(_AppVideoPlayerState anchor) {
    if (_anchor == anchor) {
      _anchor = null;
    }
  }

  VideoPlayerController? get videoController {
    assert(_anchor != null);
    return _anchor!._videoController;
  }

  ChewieController? get chewieController {
    assert(_anchor != null);
    return _anchor!._chewieController;
  }
}

2、AppVideoPlayerService.dart

//
//  AppVideoPlayerService.dart
//  flutter_templet_project
//
//  Created by shang on 2025/12/12 18:10.
//  Copyright © 2025/12/12 shang. All rights reserved.
//

import 'package:flutter_templet_project/extension/extension_local.dart';
import 'package:quiver/collection.dart';
import 'package:video_player/video_player.dart';

/// 视频播放控制器全局管理
class AppVideoPlayerService {
  AppVideoPlayerService._();
  static final AppVideoPlayerService _instance = AppVideoPlayerService._();
  factory AppVideoPlayerService() => _instance;
  static AppVideoPlayerService get instance => _instance;

  /// 播放器字典
  LruMap<String, VideoPlayerController> get controllerMap => _controllerMap;
  // final _controllerMap = <String, VideoPlayerController>{};
  final _controllerMap = LruMap<String, VideoPlayerController>(maximumSize: 10);

  /// 最新使用播放器
  VideoPlayerController? current;

  /// 有缓存控制器
  bool hasCtrl({required String url}) => _controllerMap[url] != null;

  /// 是网络视频
  static bool isVideo(String? url) {
    if (url?.isNotEmpty != true) {
      return false;
    }

    final videoUri = Uri.tryParse(url!);
    if (videoUri == null) {
      return false;
    }

    final videoExt = ['.mp4', '.mov', '.avi', '.wmv', '.flv', '.mkv', '.webm'];
    final ext = url.toLowerCase();
    final result = videoExt.any((e) => ext.endsWith(e));
    return result;
  }

  /// 获取 VideoPlayerController
  Future<VideoPlayerController?> getController(String url, {bool isLog = false}) async {
    assert(url.startsWith("http"), "必须是视频链接,请检查链接是否合法");
    final vc = _controllerMap[url];
    if (vc != null) {
      current = vc;
      if (isLog) {
        DLog.d(["缓存: ${vc.hashCode}"]);
      }
      return vc;
    }

    final videoUri = Uri.tryParse(url);
    if (videoUri == null) {
      return null;
    }

    final ctrl = VideoPlayerController.networkUrl(videoUri);
    await ctrl.initialize();
    _controllerMap[url] = ctrl;
    current = ctrl;
    if (isLog) {
      DLog.d(["新建: ${_controllerMap[url].hashCode}"]);
    }
    return ctrl;
  }

  /// 播放
  Future<void> play({required String url, bool onlyOne = true}) async {
    await getController(url);
    for (final e in _controllerMap.entries) {
      if (e.key == url) {
        if (!e.value.value.isPlaying) {
          e.value.play();
        } else {
          e.value.pause();
        }
      } else {
        if (onlyOne) {
          e.value.pause();
        }
      }
    }
  }

  /// 暂停所有视频
  void pauseAll() {
    for (final e in _controllerMap.entries) {
      e.value.pause();
    }
  }

  void dispose(String url) {
    _controllerMap[url]?.dispose();
    _controllerMap.remove(url);
  }

  void disposeAll() {
    for (final c in _controllerMap.values) {
      c.dispose();
    }
    _controllerMap.clear();
  }
}

最后、总结

1、播放视频组件和视频列表是分开的,通过监听 VideoPlayerController 保持状态(播放,暂停)一致性,类似网络视频小窗口播放。

2、通过 AppVideoPlayerService 实现全局 VideoPlayerController 缓存,提高初始化加载速度。

3、通过 quiver 的 LruMap 实现最大缓存数控制,防止内存爆炸。

github

上海北京杭州三城全年卖地收入超千亿

2025年12月26日 20:50
截至12月26日,全国住宅用地出让成交总价前十城市包括上海、北京、杭州、成都、南京、南通、武汉、苏州、广州和西安,其中出让金破千亿元的仅有上海、北京和杭州三城。因此,“谁是今年的卖地第一城”,取决于统计口径。仅看公开招拍挂,北京在2025年最后一周完成反超,险胜上海、杭州;若计入协议与遴选出让的全口径,上海则凭借另一条赛道,稳居第一。 (第一财经)

万科A:2022年度第五期中期票据宽限期延长至30个交易日

2025年12月26日 20:48
36氪获悉,万科A公告,公司在中国银行间市场交易商协会网站披露了关于2022年度第五期中期票据的宽限期延长及本息偿付安排的公告。公告显示,本期中期票据存续期内的本息兑付日之宽限期由5个工作日延长至30个交易日,即宽限期届满日为2026年2月10日。在30个交易日的宽限期内,若本期中期票据本息得到足额偿付、违约事件消除或通过债券持有人会议豁免,则不构成发行人违约。宽限期内不设罚息,不另行设置或产生违约金、逾期利息和罚息等,未偿付本金宽限期内按照本期中期票据票面利率继续支付利息,在宽限期内实际支付日利随本清,未偿付利息宽限期内不额外计息。

文峰股份:拟使用不超过10亿元自有资金进行委托理财

2025年12月26日 20:41
36氪获悉,文峰股份公告,公司于2025年12月26日召开董事会,审议通过使用不超过10亿元闲置自有资金进行委托理财,投资种类包括银行、证券公司、基金公司等金融机构发行的安全性高、流动性好的理财产品。投资期限为2026年1月1日至12月31日。本事项属于公司董事会决策权限范围内,无需提交股东会审议。

中国人民银行 国家外汇管理局发布《关于境内企业境外上市资金管理有关问题的通知 》

2025年12月26日 20:40
36氪获悉,中国人民银行 国家外汇管理局发布《关于境内企业境外上市资金管理有关问题的通知 》。通知提到,注册在境内的股份有限公司经中国证券监督管理委员会备案,直接境外发行上市或发行境外存托凭证的相关资金管理事宜,适用本通知。中国人民银行、国家外汇管理局及其分支机构对境内企业境外上市涉及的业务登记、账户开立与使用、跨境收支、资金汇兑等行为实施监督、管理与检查。境外上市前境内股东持有的内资股、境外上市后在境内增发的内资股、外资股东持有的未上市流通股份,经中国证监会备案进行H股“全流通”

海汽集团:收购海旅免税控制权存在不确定性

2025年12月26日 20:35
36氪获悉,海汽集团公告,公司原计划通过发行股份及支付现金购买海南旅投持有的海南旅投免税品公司(简称“海旅免税”)全部股权,并募集配套资金。但因国内免税市场竞争激烈、消费需求放缓等因素影响,海旅免税业绩未达预期,导致重组推进受阻。目前,是否能最终完成收购存在重大不确定性。

开勒股份:拟与杭州溯元共同投资1.2亿元设立合伙企业,聚焦半导体产业链投资

2025年12月26日 20:30
36氪获悉,开勒股份公告,公司与杭州溯元企业管理合伙企业(有限合伙)签署合伙协议,拟共同投资1.2亿元设立杭州勒泽企业管理合伙企业(有限合伙),围绕半导体相关产业链进行投资。其中,公司作为有限合伙人以自有资金出资7000万元,占合伙企业出资额的58.33%;杭州溯元作为普通合伙人出资5000万元,占合伙企业出资额的41.67%。

TCL科技:子公司TCL华星成功竞买福建兆元光电80%股权及相关债权 交易价格为4.9亿元

2025年12月26日 20:25
36氪获悉,TCL科技公告,公司子公司TCL华星光电技术有限公司已成功竞买福建省电子信息(集团)有限责任公司持有的福建兆元光电有限公司80%股权及相关债权,交易价格为4.9亿元。此次交易旨在完善TCL华星在新一代显示技术领域的布局,强化核心技术储备,构建可持续竞争力。本次交易完成后,福建兆元光电有限公司将成为公司控股子公司。

海南华铁:因重大合同临时公告披露不完整等,遭800万元行政处罚

2025年12月26日 20:14
36氪获悉,海南华铁公告,公司收到中国证监会浙江监管局下发的《行政处罚事先告知书》。经查明,公司重大合同临时公告披露不完整,未披露对协议履行有重大影响的条款;重大合同重大进展或变化披露不及时。公司拟被责令改正,给予警告,并处以800万元罚款。此外,公司时任总经理、董事胡丹锋,时任董事长张祺奥,时任董事会秘书、副总经理郭海滨也拟被处以罚款。公司表示,不触及其他风险警示、重大违法强制退市情形,目前经营活动和业务均正常开展。

闻泰科技:10月中旬以来安世中国累计出货超110亿片芯片 公司将于近期参加安世第二次听证会

2025年12月26日 20:10
从闻泰科技下午召开的2025年第五次临时股东会上获悉,自今年10月中旬恢复出货以来,安世中国已累计出货超过110亿片芯片、供应全球超过800家客户。针对安世半导体相关争议事项,今年10月闻泰科技已在荷兰启动多项法律程序并已提交了争议通知,如果问题在六个月内得不到解决,公司可能就此寻求国际仲裁,索赔金额可能高达80亿美元。2026年1月份,公司将借助第二次听证会,重申立场并进行积极维权。(财联社)

中国人民银行:稳妥有序完善房地产信贷基础性制度 促进房地产市场平稳健康发展

2025年12月26日 20:09
36氪获悉,中国人民银行发布《中国金融稳定报告(2025)》。报告提出,下一步,中国人民银行将继续认真贯彻落实党中央、国务院部署,密切关注房地产市场及金融形势边际变化,抓好保障性住房再贷款等已出台金融政策落实,加强房地产金融宏观审慎管理,稳妥有序完善房地产信贷基础性制度,促进房地产市场平稳健康发展,助力构建房地产发展新模式。

中国人民银行:着力健全有利于“长钱长投”的制度政策环境,提高各类中长期资金实际投资A股的规模和比例

2025年12月26日 20:07
36氪获悉,中国人民银行发布《中国金融稳定报告(2025)》。报告提出,下一步,中国证监会、财政部、人力资源社会保障部、中国人民银行、金融监管总局等相关部门将立足大局,加强协作,形成合力,在中央金融办统筹协调下,进一步提升工作的前瞻性、主动性和针对性,着力健全有利于“长钱长投”的制度政策环境,显著提高各类中长期资金实际投资A股的规模和比例,努力实现中长期资金保值增值、资本市场平稳健康运行与实体经济高质量发展的良性循环。
❌
❌