阅读视图

发现新文章,点击刷新页面。

欧盟委员会将修改长期预算案

当地时间11月10日,在欧洲议会威胁要阻止欧盟的下一份长期预算案后,欧盟委员会主席冯德莱恩以书面形式告知欧洲议会议长和欧盟轮值主席国,将对长期预算案进行修改。欧盟委员会主席冯德莱恩10日在社交媒体上表示,她与欧洲议会议长、欧盟轮值主席国丹麦举行了具有建设性的会议,讨论了欧盟2万亿欧元长期预算案,明确了方向。(央视新闻)

A股三大指数集体高开

36氪获悉,A股三大指数集体高开,沪指高开0.13%,深成指高开0.36%,创业板指高开0.58%;半导体、光模块概念领涨,神工股份涨超16%,阳光电源、东山精密涨超3%;锂电、冰雪旅游概念跌幅居前,华盛锂电跌超5%,天赐材料、大连圣亚跌超3%。

恒指开盘涨0.37%,恒生科技指数涨0.79%

36氪获悉,恒指开盘涨0.37%,恒生科技指数涨0.79%;汽车、科技板块领涨,小鹏汽车涨超9%,百度集团涨超3%,腾讯涨超2%;零售、电气设备板块跌幅居前,京东集体、阿里巴巴跌超1%。

中信证券:商业地产的运营、持有和改造或将迎来有史以来最有利的发展环境

36氪获悉,中信证券指出,政策发力支持提效线下消费设施。商业地产的运营、持有和改造或将迎来有史以来最有利的发展环境。REITs市场持续发育,险资等长钱持续增配商业地产。不动产投资基金在多年沉寂后,迎来快速发展期。城市走向内涵式发展,再投资回报率逐渐下降,核心资产大多成为非卖品,核心重资产具备较大重估潜力。存量改造需求持续井喷,头部企业产能有限。预计未来龙头商管公司增加包租业务,透过筛选提升订单质量。整个商管行业则可能快速增长,龙头无暇满足的需求将被众多二线品牌分享。

芋道实战|34k开源项目如何新建模块?

前言

我将持续更新 yudao-vue-pro 芋道源码笔记,记录“全局架构 → 模块拆解 → 源码细节 → 最佳实践”的完整过程,每一步保留真实思考与踩坑记录,欢迎一起打卡。

为什么选它

  1. 34.1k Star,社区体量足够,遇到问题能搜到现成讨论。** yudao-vue-pro 是 在 RuoYi-Vue 若依 基础上“二次开发”的社区版增强项目**
  2. 官方把 RBAC、多租户、工作流、支付、短信、商城等模块做成可插拔 starter,不必自己补业务场景,直接调试即可。
  3. 同一套后端接口同时供给 Vue3 管理端 + UniApp 小程序,前端部分可一次性验证 PC 与移动端,减少重复对接。

技术栈:Spring Boot、MyBatis Plus、Vue3、Element Plus、UniApp。
目标:借完整项目把后端零散知识串成体系,并夯实前端工程化能力。

本文从新增一个用户组功能开始作为入口来梳理下项目的结构和涉及到的前后端的功能模块。

新增用户组模块

下面简单列一下新增模块的过程,具体的可查阅网上相关资料。本文重点是来聊聊技术实现相关的内容。

第一步:数据库表设计

在数据库中设计 system_group 表,作为用户组模块的基础数据载体。

第二步:代码生成

进入管理后天台,先导入我们的设计表 system_group,然后在 “代码生成” 页面找到已设计好的 system_group 表,一鍵生成前后端代码和对应的 sql 文件。

第三步:代码复制与项目运行

将生成的代码分别复制到项目对应的目录中。

這是生成好的代码。将它们复制到对应的项目中进行运行。

运行成功后效果如下:

后端 yudao-module-system 目录结构

我们先从后端的项目代码来看起,首先来看看项目结构。这边仅列举了 yudao.module.system 包下的内容。这是本次新增用户组功能涉及到的模块。

cn.iocoder.yudao.module.system
├── api // 提供给其它模块的 API 接口(供其他模块/服务调用)
│   ├── dept        # 部门模块的服务间接口目录
│   │   ├── dto     # 服务间数据传输对象(DTO)目录
│   │   │   ├── DeptRespDTO.java  # 部门服务间响应 DTO,定义部门模块对外暴露的核心业务字段
│   │   │   └── PostRespDTO.java  # 岗位服务间响应 DTO
│   │   ├── DeptApi.java  # 部门服务间接口,定义部门模块可被外部调用的方法(如查询部门列表)
│   │   └── DeptApiImpl.java  # 部门服务间接口实现类,封装部门服务的调用逻辑(内部依赖 DeptService)
│   ├── ... // 其他业务模块的 api 目录
├── controller
│   ├── admin // 管理后台
│   │   ├── captcha
│   │   ├── dept
│   │   ├── dict
│   │   ├── group      # 你新增的用户组模块控制器目录
│   │   │   ├── vo     # 数据传输对象(DTO/VO)目录
│   │   │   │   ├── GroupPageReqVO.java  # 分页查询用户组的请求参数
│   │   │   │   ├── GroupRespVO.java     # 用户组详情的响应参数
│   │   │   │   ├── GroupSaveReqVO.java  # 新增/修改用户组的请求参数
│   │   │   └── GroupController.java     # 用户组模块的控制器(接口入口)
│   │   ├── ip
│   │   ├── logger
│   │   │   ├── dto     # 日志模块的请求/响应 DTO 目录(供 Controller 与 Service 交互)
│   │   │   │   ├── OperateLogPageReqDTO.java  # 操作日志分页查询请求 DTO
│   │   │   │   └── OperateLogRespDTO.java     # 操作日志响应 DTO
│   │   ├── mail
│   │   ├── notice
│   │   ├── notify
│   │   ├── oauth2
│   │   ├── permission
│   │   ├── sms
│   │   ├── social
│   │   ├── tenant
│   │   └── user
│   └── app // C端客户
│       ├── dict
│       ├── ip
│       └── tenant
├── dal // 数据访问层 Data Access Layer
│   ├── dataobject // 数据库实体对象(DO)目录,等同于 nest 中的 entity 
│   │   ├── dept
│   │   ├── dict
│   │   ├── group      # 用户组模块的数据库实体目录
│   │   │   └── GroupDO.java  # 系统用户组 DO,映射数据库表 `system_group`,封装用户组的基础字段(如ID、名称、状态等)
│   │   ├── logger
│   │   ├── mail
│   │   ├── notice
│   │   ├── notify
│   │   ├── oauth2
│   │   └── ... // 其他业务模块的 DO 目录
│   ├── convert // 数据对象转换工具(可选,用于 DO、VO、DTO 之间的转换)
│   ├── mapper // MyBatis 映射接口目录
│   ├── mysql // 数据库方言/特定实现目录(针对 MySQL 数据库的扩展)
│   │   ├── dict
│   │   ├── group      # 用户组模块的 MySQL 专属映射目录
│   │   │   └── GroupMapper.java  # 系统用户组 Mapper 接口,基于 MyBatis-Plus 实现数据库表 `system_group` 的 CRUD 操作,包含自定义分页查询等逻辑
│   │   ├── logger
│   │   ├── mail
│   │   ├── notice
│   │   ├── notify
│   │   ├── oauth2
│   │   ├── user
│   │   └── ... // 其他业务模块的 MySQL 专属 Mapper 目录
│   └── ... // 其他数据访问层组件(如 Repository)
├── service // 业务逻辑层
│   ├── group      # 用户组模块的业务服务目录
│   │   ├── GroupService.java  # 用户组业务接口,定义用户组的核心操作(新增、删除、查询、绑定用户等)
│   │   └── impl
│   │       └── GroupServiceImpl.java  # 用户组业务接口实现类,封装具体业务逻辑
│   └── ... // 其他业务模块的服务目录
├── enums // 枚举类目录
│   ├── group      # 用户组模块的枚举目录(可选,如用户组状态枚举 `GroupStatusEnum`)
│   └── ... // 其他业务模块的枚举
  • api跨模块 / 服务的 “对外接口” ,供其他系统调用;
  • service模块内的 “业务逻辑中心” ,供本模块的 Controller 调用;
  • controller前端的 “入口” ,接收前端请求并调用 Service 处理。

Debug 执行流程

在新增完代码以后我们可以通过 Debug 模式启动 Java 项目,设置断点进行接口调试。我们从一次前端请求作为入口来说明整个调试的流程。

服务端可以简单分为三层

  1. Controller 层定义了暴露给前端的接口。
  2. Service 层定义了业务逻辑相关的代码。
  3. Mapper 层定义了数据库相关的操作,由于使用了 mybatisplus 一些基础的增删改成都是集成自 BaseMapper 无需自己定义,简化了很多代码。

  1. 前端请求发送 POST /system/group/create 请求,携带 GroupSaveReqVO 格式的 JSON 参数
  2. Controller 层
@PostMapping("/create") // Spring MVC 匹配POST请求路由
@Operation(summary = "创建系统用户组")
@PreAuthorize("@ss.hasPermission('system:group:create')") // Spring Security 权限校验
public CommonResult<Long> createGroup(
    @Valid @RequestBody GroupSaveReqVO createReqVO // @Valid参数校验,@RequestBody解析请求体为VO
) {
    // 调用Service层处理业务,返回结果包装为统一响应格式
    return success(groupService.createGroup(createReqVO)); 
}
  1. Service 层
@Override
public Long createGroup(GroupSaveReqVO createReqVO) {
    // 将前端传递的VO转换为数据库实体DO(匹配表结构)
    GroupDO group = BeanUtils.toBean(createReqVO, GroupDO.class);
    // 调用Mapper层插入数据到数据库
    groupMapper.insert(group);
    // 返回插入后的自增ID
    return group.getId();
}
  1. Mapper 层
// 继承MyBatis-Plus的BaseMapper,获得通用CRUD方法
public interface BaseMapper <T> extends com.baomidou.mybatisplus.core.mapper.Mapper<T> {
    int insert(T entity); // MyBatis-Plus自动生成INSERT SQL,执行数据库插入
}

概念 VO、DTO、DO

在代码中经常涉及到这三者的定义和使用,有些项目使用不规范的话可能并不区分的这么细,但是我对于三者的关系和实际的使用场景简单罗列如下:

维度 ReqVO/RespVO(视图对象) ReqDTO/RespDTO(数据传输对象)
核心定位 前端与控制层(Controller)的交互载体 服务层(或模块间)的数据传输契约
使用场景 前端提交请求参数、接收前端展示数据 服务间调用、模块内数据传递
字段设计 贴合前端页面需求(如表单字段、格式化数据) 贴合业务逻辑(如核心业务字段、校验规则)
变更驱动 前端页面需求变更(如新增输入框、展示列) 服务接口契约变更(如新增业务字段、逻辑)
数据来源 从 ReqDTO 转换而来(或直接接收前端参数) 从 DO(数据库实体)转换而来
典型示例 DeptPageReqVO(含分页 + 前端查询条件)DeptRespVO(含负责人姓名、格式化时间) DeptSaveReqDTO(含部门名称、父部门 ID)DeptRespDTO(含部门 ID、名称、状态)

VO(View Object) :聚焦前端视图交互,是控制层与前端的专属载体,字段设计贴合页面需求。

DTO(Data Transfer Object) :聚焦服务间数据传输,是服务层的标准化契约,字段设计贴合业务逻辑

DO 是数据库表的代码镜像,是持久层与业务层的内部数据载体,仅负责数据存储映射,无业务逻辑。

维度 DO(数据对象)
核心定位 数据库表在代码中的实体映射
使用场景 数据访问层与业务层的内部数据载体
字段设计 与数据库表字段一一对应(含所有底层字段)
变更驱动 数据库表结构变更(如新增字段、修改类型)
数据来源 直接映射数据库表,由持久层操作生成
典型示例 GroupDO(映射system_group表,含 id、name、status 等字段)

前端 yudao-ui-admin-vue3

项目结构

  • 业务模块:在 apiviews 层均按 “系统、bpm、crm” 等业务域拆分子模块(如 system/group 同时管理接口与页面),让每个业务功能的代码链路高度集中,便于独立维护与迭代。
  • 权限管控:通过 store/permissionstore/user 深度联动,不仅支持动态路由的后端驱动生成,还能实现按钮级的权限校验,结合自定义指令完成细粒度操作控制,满足企业级后台的安全要求。
  • 工程化分层:以 hooks 封装可复用业务逻辑、directives 封装通用交互行为,store 层通过 modules 区分业务与全局状态,既保证架构的扩展性,又让复杂后台的状态管理更有条理,特别适配多业务域的中大型后台系统开发。
yudao-ui-admin-vue3
├── src
│   ├── api                  # 接口封装层,按业务模块拆分,统一管理前后端接口交互
│   │   ├── system           # 系统管理模块接口
│   │   │   ├── group        # 用户组管理接口模块,封装用户组增删改查等接口
│   │   │   │   └── index.ts # 用户组管理接口实现
│   ├── assets               # 静态资源,存储图标、图片、全局样式等
│   ├── components           # 全局通用组件,可在各业务模块复用
│   ├── config/axios         # 请求封装与拦截器,配置请求全局规则、响应拦截逻辑
│   ├── directives           # 自定义指令,封装权限控制、拖拽、防抖等通用指令
│   ├── hooks                # 组合式 Hook,封装 web 交互、事件处理、业务逻辑复用等逻辑
│   ├── layout               # 框架布局,管理系统整体布局结构(侧边栏、顶部导航、标签页等)
│   ├── router               # 路由中心,管理静态路由和动态路由的注册、守卫逻辑
│   ├── store                # Pinia 模块,管理应用状态(核心模块如下)
│   │   ├── modules          # 业务模块状态(如 bpm、mall 等)
│   │   ├── permission.ts    # 权限状态(路由权限过滤、按钮权限校验,控制用户可访问页面和操作)
│   │   ├── user.ts          # 用户状态(用户信息、token、登录态管理,对接权限校验逻辑)
│   │   └── index.ts         # Pinia 模块注册入口
│   ├── styles               # 全局样式与 SCSS 变量,定义系统样式规范
│   ├── utils                # 工具函数,封装权限、字典、树结构、路由辅助等通用工具
│   └── views                # 业务页面,核心业务模块集合
│       ├── system           # 系统管理模块,包含各类系统配置与管理页面
│       │   ├── group        # 用户组管理业务页面模块
│       │   │   ├── index.vue # 用户组列表页,展示用户组数据、提供查询、操作入口
│       │   │   └── GroupForm.vue # 用户组表单页,实现用户组的新增、编辑功能
└── public                   # 公共静态资源,存储无需编译的静态文件

路由守卫核心流程解析

  1. 身份验证:校验访问令牌存在性,已登录且目标为登录页时重定向至根路径。
  2. 依赖初始化:按需拉取全局枚举字典、用户基础信息及权限菜单树,完成 Pinia 状态持久化与缓存写入。
  3. 动态路由注入:依据后端菜单数据递归生成符合 Vue Router 规范的 RouteRecordRaw,通过 router.addRoute 在运行时注入路由表,并追加通配符 404 兜底。
  4. 导航重置:利用 next({ path, query, replace: true }) 触发新一轮路由匹配,解决刷新后因 matcher 快照未更新导致的 404 问题,同时保留查询参数。
router.beforeEach(async (to, from, next) => {
  start()                 // 顶部进度条开始转
  loadStart()             // 页面 loading 蒙层

  if (getAccessToken()) { /* ===== ① 有 token ===== */
    if (to.path === '/login') {
      next({ path: '/' }) // 已登录再进登录页 → 直接踢走
      return
    }

    // 字典对应枚举
    const dictStore = useDictStoreWithOut()
    // 用户信息
    const userStore = useUserStoreWithOut()
    // 权限信息
    const permissionStore = usePermissionStoreWithOut()

    /* ③ 全局字典(性别、状态等下拉选项)只拉一次 */
    if (!dictStore.getIsSetDict) await dictStore.setDictMap()

    /* ④ 只要刷新页面 isSetUser 就是 false → 去拿用户数据 */
    if (!userStore.getIsSetUser) { // 是否设置过用户信息
      isRelogin.show = true                       // 显示“正在加载用户信息”遮罩
      await userStore.setUserInfoAction()         // 拿:用户详情 + 权限 + 菜单树
      isRelogin.show = false

      /* ⑤ 根据后端返回的菜单树 → 现拼前端路由 */
      await permissionStore.generateRoutes()      // 返回 addRouters[]
      permissionStore.getAddRouters.forEach(r =>  // 逐条塞进 vue-router
        router.addRoute(r as RouteRecordRaw))

      /* ⑥ 正确加载动态路由,必须使用 next(pathParams) 才能正确渲染新添加的路由  */
      const redirect = decodeURIComponent((from.query.redirect as string) || to.fullPath)
      const { paramsObject: query } = parseURL(redirect)
      next(to.path === redirect ? { ...to, replace: true } : { path: redirect, query })
    } else {
      next() // 用户、路由、字典都已就绪 → 直接放行
    }
  } else { /* ===== 无 token ===== */
    whiteList.includes(to.path)
      ? next()                           // 白名单页面直接过
      : next(`/login?redirect=${to.fullPath}`) // 其余统一跳登录
  }
})

“有 token → 拉用户 → 拼路由 → addRoute → 重跳带参 → 页面正常”

setUserInfoAction

setUserInfoAction 完成用户身份、权限、角色及菜单树的一次性拉取与持久化缓存,为后续路由生成、按钮级权限控制及全局用户信息渲染提供可复用的单一数据源

export const useUserStore = defineStore('admin-user', {
  actions: {
    async setUserInfoAction() {
      /* 1. 如果连 token 都没有 → 直接 reset,后面代码不再执行 */
      if (!getAccessToken()) {
        this.resetState()
        return
      }

      /* 2. 先读本地缓存,保证刷新页面瞬间就能渲染,不会白屏 */
      let userInfo = wsCache.get(CACHE_KEY.USER)

      /* 3. 无论缓存是否存在,都去后端拉一次最新数据(失败也不踢人) */
      if (!userInfo) {
        userInfo = await getInfo()          // 第一次:必须等接口
      } else {
        try { userInfo = await getInfo() }  // 非第一次:后台悄悄更新
        catch {}
      }

      /* ===== 下面 4 行分别对应“4 件事” ===== */

      /* ① 拿权限标识集合 → 按钮级 v-hasPerm 会用它 */
      this.permissions = new Set(userInfo.permissions || [])

      /* ② 拿角色数组 → 按钮级 v-hasRole 会用它 */
      this.roles = userInfo.roles

      /* ③ 拿用户基本信息 → 顶部栏头像、个人中心等页面显示 */
      this.user = userInfo.user

      /* ④ 标记“我已经知道你是谁了”,路由守卫下次不再重复跑 */
      this.isSetUser = true

      /* ⑤ 把最新数据写缓存,下次刷新直接读,省一次接口 */
      wsCache.set(CACHE_KEY.USER, userInfo)

      /* ⑥ 把菜单树单独再写一份缓存 → permissionStore 会用它来拼装路由 */
      wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus)
    }
  }
})

generateRoutes

基于后端菜单树一次性生成可访问动态路由及侧边栏菜单数据。

export const usePermissionStore = defineStore('permission', {
  actions: {
    /**
     * usePermissionStore.generateRoutes()
     * 把【后端菜单】→【前端可访问路由】→【侧边栏菜单】
     * 一次性全算完,只在前端刷新后跑一遍。
     */
    async generateRoutes(): Promise<void> {
      return new Promise<void>(async (resolve) => {
        /* 1. 拿后端给的菜单树(登录时已缓存) */
        let res: AppCustomRouteRecordRaw[] = [];
        const roleRouters = wsCache.get(CACHE_KEY.ROLE_ROUTERS);
        if (roleRouters) res = roleRouters as AppCustomRouteRecordRaw[];
    
        /* 2. 递归把后端 JSON 转成 vue-router 需要的 RouteRecordRaw */
        const routerMap: AppRouteRecordRaw[] = generateRoute(res);
    
        /* 3. 追加“通配符 404”,保证任意非法路径都能落到 404 组件 */
        this.addRouters = routerMap.concat([
          {
            path: '/:path(.*)*',
            component: () => import('@/views/Error/404.vue'),
            name: '404Page',
            meta: { hidden: true, breadcrumb: false }
          }
        ]);
    
        /* 4. 拼出“完整菜单”:静态路由(login、404、dashboard)+ 动态路由
              用于侧边栏渲染、标签页、面包屑 */
        this.routers = cloneDeep(remainingRouter).concat(routerMap);
    
        /* 5. 通知外部“路已铺完”,可以 forEach(router.addRoute) 了 */
        resolve();
      });
    }
  }
}

拿到后端菜单相关数据,根据数据生成一份前端路由相关的配置。

动态加载路由

  1. 将 permissionStore.getAddRouters 中的动态路由动态添加的路由注册表
  2. 通过 next(routeParams) 重新渲染路由视图,否则动态路由不会正确被渲染
/* ④ 只要刷新页面 isSetUser 就是 false → 去拿用户数据 */
    if (!userStore.getIsSetUser) { // 是否设置过用户信息
      isRelogin.show = true                       // 显示“正在加载用户信息”遮罩
      await userStore.setUserInfoAction()         // 拿:用户详情 + 权限 + 菜单树
      isRelogin.show = false

      /* ⑤ 根据后端返回的菜单树 → 现拼前端路由 */
      await permissionStore.generateRoutes()      // 返回 addRouters[]
      permissionStore.getAddRouters.forEach(r =>  // 逐条塞进 vue-router
        router.addRoute(r as RouteRecordRaw)
      )

      /* ⑥ 正确加载动态路由,必须使用 next(pathParams) 才能正确渲染新添加的路由  */
      const redirect = decodeURIComponent((from.query.redirect as string) || to.fullPath)
      const { paramsObject: query } = parseURL(redirect)
      next(to.path === redirect ? { ...to, replace: true } : { path: redirect, query })
    } else {
      next() // 用户、路由、字典都已就绪 → 直接放行
    }

next() 使用分析

如果动态路由,直接使用 next() 未重新指定路由地址和参数。则无法匹配新添加的路由导致 404

使用 next({...to, replace: true }) 指定跳转动态路由的地址和参数

结尾

就从“新增一个用户组”这道小入口出发,我把它当成芋道源码学习的第一课:后端以 Spring Boot 的调用链、权限模型;前端以 Vue3 的动态路由、表单校验与权限回显。如果你也在用芋道搭建自己的技术体系,欢迎持续关注,我们一起把这条主线走深、走实。

维萨与万事达达成协议,降低商户手续费

维萨与万事达已与零售商达成协议,将降低向商户收取的手续费。这一举措或能降低商品价格,但也可能对消费者珍视的信用卡奖励机制造成影响。协议方案显示,未来五年内,两家公司将把交换费降低0.1%;同时,商户将获得两项新权利:一是可在消费者使用信用卡付款时额外收取附加费,二是可拒绝接受 “高端信用卡”(这类卡片通常收取远高于普通卡的手续费)。(新浪财经)

本周39只公募新基发行,权益类产品担纲

11月份,新基金发行数量将连续两周稳步增长。根据公募排排网最新统计数据,按认购起始日统计,预计本周(2025年11月10日至16日)全市场共有39只新基金启动募集,数量较上周(2025年11月3日至9日)的37只小幅增加,增长幅度为5.41%。与此同时,新基金的平均募集天数明显缩短,从上周的19天降至本周的不到17天,从侧面印证了投资者对公募基金产品的关注度和认可度不断提升,资金入市意愿增强。(证券日报)

西班牙豪门马德里竞技队将易主美国资本,与阿波罗体育资本达成协议

马德里竞技队即将归入美国资本旗下。这家西班牙足球豪门于11月10日(周一)宣布,资产管理公司阿波罗体育资本(Apollo Sports Capital)将于明年初成为俱乐部的控股股东。双方未披露此次交易的财务细节。双方在联合声明中表示,作为协议的一部分,现任首席执行官米格尔・安赫尔・希尔・马林与主席恩里克・塞雷佐将继续留任,以确保 “俱乐部愿景与领导层的连续性”。(新浪财经)

华西证券:AI应用细分化场景加速突破,重点关注工业智造相关AI应用落地

36氪获悉,华西证券研报表示,通用高频场景基本完成布局,头部互联网企业对于模型的高频升级,不断提升用户体验,AI产业用户习惯逐渐形成,AI产业正在进入快速迭代的竞争深水区,未来AI应用有望向更细分、深度的场景挖掘,包括教育、医疗、办公等。伴随国产大模型持续开源迭代,包括AI手机和AI眼镜等终端产品加速普及,行业应用大模型落地,我国AI在政策推动与产业落地进程中加速应用突破阶段。持续推进包括先进制造,重点关注工业智造相关的AI应用落地和数字化应用。

及时回应投资者关切,上市券商密集召开业绩说明会

截至11月10日,已召开2025年第三季度业绩说明会的上市券商已达到10家。10日当天,就有东兴证券、东方证券2家上市券商双双召开2025年第三季度业绩说明会。A股今年前三季度行情向好、交投活跃带动券商整体业绩增长。作为增收的重要“功臣”,券商经纪业务及自营业务功不可没,相关业务表现及未来布局规划成为业绩说明会上投资者关注的重点;适逢AI在证券行业应用进一步深化,券商在金融科技领域尤其是AI方向的投入及取得的成果,也被投资者频繁问及。(中证网)

中国银河证券:四季度铜铝行业业绩增速有望进一步提升,锂行业公司利润有望继续好转

36氪获悉,中国银河证券指出,2025Q4铜铝行业业绩增速有望进一步提升。国内外储能需求旺盛,以及进入2026年国内新能源汽车购置税减免政策退坡或将引发年底抢购,国内锂电池排产环比持续提升并传导至上游锂电正极材料环节,部分头部材料厂商已满产,使订单已外溢到二三线材料厂商;产业链下游高景气下,带动上游碳酸锂需求增加并出现供应缺口,致使国内碳酸锂库存在进入四季度后已加速去化近1万吨,驱动锂价持续上涨。预计2025Q4在下游旺盛需求下,国内碳酸锂库存或将继续去化以支撑价格走强,锂行业公司利润在四季度有望继续好转。

两市融资余额增加76.7亿元

36氪获悉,截至11月10日,上交所融资余额报12600.0亿元,较前一交易日增加32.5亿元;深交所融资余额报12152.44亿元,较前一交易日增加44.2亿元;两市合计24752.44亿元,较前一交易日增加76.7亿元。
❌