news 2026/10/21 19:12:26

Diagram-design实战:从布局、连线到配色,教你画出一眼看懂的系统架构图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Diagram-design实战:从布局、连线到配色,教你画出一眼看懂的系统架构图

先说个真实感受:我画了这么多年的系统图,越来越觉得Diagram-design这个活,难度根本不在工具操作上,而是在“怎么让看图的人三秒内抓到重点”。代码写得清楚是给机器看的,图画得清楚是给人看的。很多人把画图当成“把几个框连起来”,结果画出来的架构图、流程图、数据流向图,信息全堆在一起,找人评审时对方盯着屏幕看半天,问出的第一个问题是“这是从哪边看起”。

这篇文章我想把Diagram-design这条线上我沉淀下来的经验做一次完整梳理:从画图前要想清楚什么,到布局、连线、配色、字体,再到一个具体架构图的完整实操过程,最后是踩过的坑和排查思路。如果你是正要画第一张架构图的新人,或者已经画了很多年但总觉得图“哪里不对”的老手,这篇都应该能给你一些能直接拿走用的方法。

1. 先想清楚再做图:Diagram设计的三个关键前置问题

1.1 一张Diagram到底在传递什么

很多人把Diagram当成插画来画,这是最大的误区。插画传递的是感受和氛围,可以留白、可以做模糊处理;但一份架构图、流程图、时序图,本质上是把“多对多的复杂关系”编码成二维视觉语言,让看图的人在一眼之间还原出系统结构。换句话说,Diagram是一张地图,不是在墙上挂的风景画。地图的每一根线条都必须有明确的指向和约束,乱画一根线,就可能让读者误判整个模块的边界。

我自己总结过一个很粗糙的公式:一张好Diagram的信息量 = 视觉占用面积 × 单位面积里有效信息的密度。那些看似“信息满满”的图,往往是因为每个框里塞了一堆文字、每个箭头上都挂了三四个标注,整体读起来反而像一堆彩色色块,找不到重点。真正有用的图,是做减法做出来的,每个元素出现在画布上都有存在的理由,而不是“因为某工具自带这个形状,所以我放上去了”。

这里还要分清Diagram的种类。架构图强调系统边界和模块关系,流程图强调顺序和分支,时序图强调消息的先后,思维导图强调层级从属。很多人画图翻车,是因为把“架构图”画成了“流程图”,又想在里面塞“部署结构”,最后什么都想说,什么都没说清。我建议动手之前,先明确这张图的“主语义”:你是在表达静态结构,还是在表达动态行为?确定后再决定用什么图形、什么标注方式。

1.2 给谁看、在哪看、用多久:三个前置问题的取舍

画图之前,我会强迫自己回答三个问题,答案直接决定整张图的信息密度、尺寸和标注方式。

第一个问题:这张图是给谁看的。给技术评审看的图,要突出模块边界、依赖关系和协议类型,甚至可以把技术栈直接写在框里;给新入职同事看的图,需要更多引导性标注,比如“入口从这开始”“这条链路是核心链路”;给外部客户看的图,就要减少内部技术细节,最好加入业务语义,比如把“消息队列”换成“异步通知”。同一个系统完全可以画出两个不同版本,不要指望一张图服务所有读者。

第二个问题:这图在什么媒介上看。是在投影仪上放PPT,还是在A4纸的文档里,或者是在高清屏幕上自由缩放?这个问题会影响两个具体参数:字号和画布尺寸。投影仪和大屏观看需要更大的字号,至少14号以上;打印成A4纸时,字号不能太小,同时要考虑黑白打印时颜色区分失效的问题,需要配合线型或图标来表达层次。

第三个问题:这张图是一次性汇报用,还是要长期维护。如果是要长期放在文档里跟着系统演进的图,就一定要预留“修改的余地”:少用绝对固定的绝对定位、多用图层和分组,导出源文件要保留。如果只是临时画给评审看的图,那就可以牺牲一部分美观度,优先保证快速产出。

这三个问题想清楚之后,基本就确定了这张图的上限不会太差。反之,如果一上来就打开工具拖形状,画到一半才开始纠结布局,大概率要推翻重来。我现在特别坚持的一点:拿笔之前先谈清楚图意,哪怕只是在脑子里用一句话把图的主旨说出来,也好过直接开画。

2. 布局与信息架构:看图的人第一眼就能抓住重点

2.1 阅读顺序设计:图里的信息也有“视线动线”

Diagram既然是给人“读”的,就一定存在阅读顺序。大多数人的视觉习惯是从左上角进入,然后沿着对角线自然移动到右下角。这个规律在所有视觉媒介里基本通用,但很多画图的人完全不考虑它,把核心模块放在右下角,把入口放在左上角,导致看的人视线在图上转了好几圈才找到主线。

我常用的做法参考了杂志排版里的“视觉动线”概念:先用大结构把画布分成几个区域,然后安排读者视线从左上开始,经过主链路,最终落在产出或结果上。举个例子,画一个订单处理流程图,起点“用户下订单”放左上,接下来按时间线往下或往右推进,最后“订单完成”落在右下。这条主线尽量保持简单,不要来回折返,所有分支都从主线旁边分叉出去,而不是打断主线。

为了做到这一点,我会在草图阶段刻意做“路线简化”。核心链路如果超过五个节点,就要考虑能不能拆成子图;如果核心链路里出现了回环,优先考虑把回环作为侧注来解释,而不是在主线上画一根很长的回头线。视觉上,主线如果用实线粗一点,分支用虚线细一点,读者潜意识里就能区分主次。

还有一个容易被忽略的问题:图的“重心”位置。如果整个画布上所有元素都居中对称排列,视觉上会很平,找不到重点。我会把最重要的模块放在稍微偏离中心的位置,或者用更大的尺寸、更深的颜色来建立视觉层级。这就像合影照片里,C位不一定要站最中间,但一定是最显眼的那个人。

2.2 分组与边界:用分区让复杂系统一目了然

信息一多,图就会乱。对付“多”最好的方法不是减小字号、缩小框,而是分组。分组的本质是用“容器”表达逻辑边界,让读者先看到一个大的结构,再进入局部细节。

在实践中,我会用不同形状的大框来区分不同层级的语义。比如一份微服务架构图里,可以用一个大框圈住“业务服务层”,里面放订单服务、商品服务、用户服务;另一个大框圈住“数据层”,里面放各个数据库实例。这样就形成了“大框里套小框”的嵌套结构,读者先看到的是“采用了分层架构”,然后再逐层往里看。大框本身也是一种信息载体,用不同的边框样式表达不同的边界类型,效果更好:

边界类型视觉表现典型用途
逻辑边界圆角大框+浅底色服务模块、业务领域
物理边界实线直角框服务器、容器、机房
部署边界虚线大框可用区、命名空间
外部系统粗边框+灰底色不可控的外部依赖

分组还有一个容易被忽略的好处:它天然帮你实现了“先讲结构,再讲细节”的解说节奏。评审时指着大框说“整体是前端-网关-服务-数据四层”,听众大脑里就有了地图,再指具体模块时,大家不会迷失。

我在分组时会遵守一个经验:一个分组区域里的核心节点数尽量控制在七左右,也就是7 ± 2。如果一个大框里装了十五六个小框,读者其实很难同时处理这么多信息,这时该拆成两个子图了。拆的规则也简单:先找它们对外关系的交集,交集大的放同一组,交集小的拆分出去。

2.3 连线设计:减少交叉,克制用量

连线是Diagram里最容易翻车的地方。很多人画图时,框排完,连线随意一拉,结果图上满是歪的弧线、穿框的斜线、结成一团的交叉线。好的连线应该像城市地铁图——每条线都走正交方向、转弯规则、线路之间尽量少交叉,颜色还能标识不同的线路。

我在落线之前会有一个强制动作:先布局,后连线。也就是说,先确定所有节点的大致位置,观察哪些节点之间要连线,再微调位置,让连接点尽量相邻,从源头上减少跨越。多数交叉不是线的问题,是摆放的问题。节点摆放合理,连线自然就顺了。

连线有几种风格可选,我几乎只用正交直线,不做曲线或斜线:

连线风格优点缺点
正交直线专业、清晰、符合工程图感稍微生硬
曲线柔和,观感自然容易乱,指向性弱
直线斜连省事,拖拽即出交叉和误读风险高
分层总线结构清晰,适合大规模图占空间大,搭建耗时

正交连线还方便表达方向。箭头的用法上,我有一条很朴素的原则:有方向必有箭头,没方向就别画箭头。很多时候两个模块之间的连接表示“依赖”而不是“数据流动”,这时候连线上不需要箭头,加了反而让人误解为消息有方向。线型上也可以做语义区分:实线表示同步调用,虚线表示异步消息,粗线表示批量数据或核心链路,细线表示非关键依赖。把线型约定写进图例,比在每条线上加文字标注更高效。

连线还有一条硬性禁忌:不要让线从文本框上面穿过。穿过文字会直接打断阅读,视觉上瞬间变成一团乱麻。如果发现线必须穿过某个框,那就修改布局让线绕行,或者干脆把穿过的节点挪走,不要偷懒硬留。

3. 实操记录:用一张某订单系统架构图走完全流程

3.1 第一步:从需求里拆出元素清单

纸上谈兵说完了,我拿一个“某订单系统架构图”当例子,完整走一遍我画图的流程。这不算什么特别复杂的系统,但足够展示Diagram-design的核心动作。

第一步是拆元素。假设需求方给我的描述是:“用户下单后,订单服务先查商品库存,扣减库存后发送消息通知,支付成功后更新订单状态,同时对接第三方支付接口。”这段话看起来很短,但画图的话,里面藏着超过十个实体。我会把它拆成一张元素清单:

元素类型职责主要关联
前端应用客户端用户交互入口API网关
API网关网关路由、鉴权、限流各业务服务
订单服务业务服务订单生命周期管理订单库、消息生产者
商品服务业务服务库存和商品信息商品库
用户服务业务服务用户信息与鉴权用户库
第三方支付外部依赖支付处理订单服务、支付回调
消息队列中间件异步解耦订单服务、通知服务
通知服务业务服务发送短信/邮件/推送消息队列
订单数据库数据层订单数据存储订单服务
商品数据库数据层商品和库存存储商品服务
用户数据库数据层用户信息存储用户服务

这张清单的作用,是确保正式画图时不漏元素、不乱加关系。很多人漏画外部依赖,比如支付回调、短信服务,评审时被人一问才发现缺了一整块。把元素先列出来,再用箭头把关系标清,画图就变成了“摆位置”的工作,脑子里的负担小很多。

3.2 第二步:在白板上定大块布局

元素清单列好之后,我一般不直接在工具里拖形状,而是先拿笔在草稿纸上定大框架。这一步只做一件事:把画布划分为几个大区域,并决定每个区域放什么内容。

针对这个订单系统,我会先画五块大区域,从上到下依次是:入口层、网关与对外接口层、业务服务层、中间件与数据层、外部依赖层。这五块的顺序不是随便定的,它符合“请求从用户出发,往深处走”的直观理解。读者从上往下扫一遍,就对系统结构有了基础认知。

大区域定好后,再把元素清单里的元素逐个放进对应区域。这个过程我会刻意留白,不让框紧贴在一起,每个元素之间至少空出一个元素宽度的距离。留白看着浪费画布,但它会给后续的连线调整留出空间。所有元素放完、确认布局基本合理后,拿出手机拍一下草稿,再打开正式工具。

布局阶段我还会顺便标注“主链路”。这个订单系统的核心链路是:前端 → 网关 → 订单服务 → 支付 → 消息队列 → 通知服务。我会在草稿上用粗线把这几个节点连一遍,确认这条链路是一条尽量顺的路径(不回头、不绕路)。如果发现核心链路在草稿上已经绕了三次,那就说明布局有问题,必须重排,不要将就去连线。

3.3 第三步:工具落地与细节打磨

接下来是正式制作。市面上的工具很多,但我的选择标准基本稳定:支持图层、支持网格对齐、支持导出SVG、能方便地调整所有形状的统一样式。无论你用的是在线白板工具还是开源本地绘图软件,只要满足这四个条件,都可以胜任。

新建画布后,我做的第一件事不是画框,而是把网格打开、开启对齐。大多数工具默认的画布像一张白纸,没有网格参考时,人会凭感觉对齐元素,一张二十个元素的图,差两三个像素看着不明显,但整体就是有股“说不上来的乱”。打开网格对齐后,所有元素自动吸附到网格点,间距、对齐问题基本解决。

第二步是统一形状和尺寸。所有表示服务的节点,我会用同一个圆角矩形模板,固定宽度和高度;数据库统一用圆柱体;外部系统统一用另一种边框颜色。这里我踩过一个坑:一开始为了图好看,给每个节点用了不同的形状和配色,结果整张图华丽得像贺卡,信息读取效率极其糟糕。后来我把非核心装饰全部去掉,整个画布只剩两种主色加一种强调色,图反而“专业”了。

第三步是建图层。很多画图的人不用图层,所有元素平铺在一个层里,改图时想选中一个框,结果连带选到周围的线。我把图层分成几组:背景框一层、节点一层、连线一层、文字标注一层。这样做的好处,是改线的时候不会误碰节点,导出版本时可以单独隐藏标注层生成“无字版”作为白底图使用。这是Diagram-design里收益最高但最少人用的习惯。

第四步是加图例和标注。如果这张图要发给不熟悉系统的人,我会在图的右下角放一个简短的图例,说明“实线为同步调用、虚线为异步消息、深色框为核心服务”,并加上一条阅读引导:“建议从左上角入口层开始阅读。”这话看着多余,但实际效果非常明显,能大幅减少别人追问“这是什么意思”的次数。

打磨阶段我会做最后一遍“信息密度审计”:逐个元素问自己,这个框删掉会不会影响理解?这个文字标注有必要吗?如果答案是不影响、没必要,直接删。图不是越满越好,而是越“干净”越好。把那些“留着也行”的元素删干净,整张图的档次就出来了。

4. 视觉规范化:颜色、字体、图标这样用才不会翻车

4.1 颜色:有一两把刷子就够了,别把整个调色盘端上来

配色是Diagram-design里最容易被“用坏”的一环。很多人的图颜色一多,立刻失去了重点。我自己的配色原则始终是:整个图最多三种主色系加一种强调色,其余接近灰色。

具体来说,我常用的方案是:背景用浅灰或纯白,节点边框用中灰,节点内的文字用深灰,核心模块用一种强调色做底色,比如深蓝或深青。这样一来,读者眼睛会天然聚焦到有颜色的核心模块上,其他部分作为“背景信息”存在。强调色不要超过一种,如果一个图里有五六个颜色各异的“重点”,那等于没有重点。

还有一个容易忽视的细节:不要只用颜色深浅表达关键区分。考虑到部分读者色弱或者看黑白打印稿,如果两个模块只是颜色不同,在灰度打印后可能完全无法区分。所以我用颜色辅助区分的同时,一定会搭配边框线型或者图标的差异。比如核心服务用深色底白字,普通服务用白色底深色边框,这样即使去色,深底和浅底依然能明显区分。

关于颜色选取,我更推荐使用同一色相的深浅梯度,而不是在色环上随便挑几个颜色。比如深蓝表示核心链路,浅蓝表示次要链路,灰色表示依赖或外围。同一色相梯度会让整张图有很强的整体感,而且天然带有层级信息。我见过一些图把“订单服务”画成橙红色、“用户服务”画成绿色、“商品服务”画成紫色,虽然每个模块内部很醒目,但整体看起来像调色板在开会。

4.2 字体、图标和排版质感

字体的作用常被低估。Diagram里的文字是给快速阅读用的,应该选现代无衬线体,比如现在各类系统默认的UI字体就足够,不推荐用带衬线或花体字。在同一张图里字体不要超过两种,最好全图统一,通过字号大小来区分层级。

我通常设置三个字号级别:区块大标题用最大字号,节点名称用中等字号,辅助说明文字用最小字号。这里要特别记住一个底线:最小字号要保证在最终展示环境下能看得清。如果你要做的是PPT里放的图,宁可字体大一点,也不要为了把二十个模块塞进一页A4纸排版而把字号缩到肉眼勉强可辨的程度。到时候读者凑近屏幕眯着眼看,你的图就失败了。

图标的用法同样讲究统一性。如果要加图标,请使用同一套图标库里的样式,不要混搭填充风格和线性风格。图标的真正用途不是装饰,而是帮助读者快速识别模块的类别,比如用信封表示通知服务、用数据库柱体表示存储、用云朵表示外部服务。如果找不到合适的图标,宁可不放,也不要放一个意义不明的抽象图案。

排版方面,关于对齐我有一条铁律:所有同层级的节点,要么左边缘对齐,要么垂直中心线对齐,不允许“差一点点”的近似对齐。近似对齐是最容易让观者感到“不舒服”却又说不清原因的现象。网格对齐开启后,统一间距,这种问题基本可以被工具解决掉。

4.3 进阶玩法:分层视图做“一图多用”

一张图能不能既给技术评审看,又给新同事做入门资料,还能放到产品文档里?能,但前提是你愿意做分层,而不是试图把三层信息压进同一张图。

我现在的习惯是做一个“母图”,然后通过图层和链接生成三个视图:全景总览层,只展示模块名和大分区,不带任何协议细节;建议用这张讲系统轮廓,适合所有读者;技术细节层,展示协议、端口、数据表、调用链路由,适合开发评审;部署拓扑层,展示多实例、部署边界、可用区与中间件等,适合运维和部署相关同事。

总览层可以把细节层里一半的元素隐藏;明细层才显示完整节点和标注。这样“一图多用”最大的好处是统一了信源——你不用维护三份独立的图,系统变动时只需改母图,三个视图同步更新。我在项目里因为在一次技术方案评审时,评审人要求“只看服务划分、不要让我看表结构”,我直接把细节图层隐藏,总览层导出,一分多钟就拿到了对应视图。这就是图层管理实实在在省下来的时间。

5. 常见问题排查与长期维护技巧

5.1 图老是改,怎么保持可维护性

系统演进快,架构图要跟着更新。但很多人每次改图都像做一次外科手术,这里挪一个框、那里改一条线,改完之后图变得更乱。图的可维护性不是靠“认真”维持的,是靠一开始就设计好的结构和习惯。

我的维护技巧主要有三个,都很具体:第一,所有节点名用统一命名规范,比如“订单服务-订单查询”“订单服务-订单创建”这种,会让图面的阅读成本明显降低;第二,每个大分组都在图层里建独立分组,修改时直接在组内操作,避免误碰其他区域的元素;第三,保存源文件时,把导出的PNG、SVG放在同一个目录,文件名里带版本号。遇到“这个版本看着还行,我想退回上一版”的瞬间,版本号能救你一命。

还有个容易踩的坑:在改图时随手删除老连线然后拉新线,结果漏删了旧的一段,图上出现“带箭头的幽灵线”。我排查时会全局扫一遍所有线条的起点和终点,确认每条线两端都连接到了节点边框,而不是悬空停在画布上。悬空箭头比错误箭头更危险,因为它会让人误以为是某种隐含关系。

5.2 导出模糊、文字太小怎么办

导出图片模糊是高频问题。这通常不是工具的问题,而是导出参数设置的锅。如果你最终需要PPT用的图,不要只导出一张低分辨率位图,建议直接导出SVG矢量图,或者把画布尺寸设置成实际展示尺寸的两倍再导。位图导出时,绝大多数工具都有DPI选项,选150 DPI以上;如果还有模糊感,检查画布本身的缩放级别,有些工具在画布缩放到50%时导出,会按当前显示比例输出低清晰度图。

文字太小的问题,根源多半是信息量超出画布容积。你试着把所有内容压缩在一张图里,文字自然缩到蚂蚁大小。两个解决方向:一是拆图,把一张总图拆成一张主图和几张子图,通过编号互相关联;二是调整画布比例,用更宽的横向比例而不是正方形画布,为文字争取更多空间。这里要给个经验值:正式文档里的架构图字号,正文节点最小不要低于8号,区块标题不要低于12号,在投影场景下这两个数字还要往上提。字号一旦低于可读底线,你图里表达的信息就全部作废了。

5.3 别人说看不懂,问题出在哪

“看不懂”往往是创作者和读者的信息不对称导致的。创作者脑子里装着完整的系统,画图时觉得自己每一步都画得明明白白;读者第一次看到这张图,没有上下文,自然容易迷失。遇到这种情况,我的排查顺序是:先确认有没有明确的阅读顺序和入口标记,图的左上角是否放了一个“从这里开始看”的提示;再看图例是否存在,虚线、实线、不同颜色到底代表什么,是否解释清楚;最后看是否缺少一个“一句话说明”,一段不超过五十字的图意说明放在图上方或备注里,能解决大量理解成本。

如果以上三样都有了,仍然有人看不懂,那说明图和读者之间还有一层“细节断层”。我的做法是在图下方加一段分层说明:第一层讲整体分层,第二层讲核心链路,第三层讲关键模块职责。这段文字不是图例的替代品,而是给读者搭一个“先看overall,再深入”的阶梯。实践下来,效果很好,提问从“这图什么意思”变成了“这条链路的超时策略是怎样的”,说明读者已经看到了正确的细节层面。

还有一个高频问题:更新图时忘改图例。图改了十版,图例还停留在第一版,读者按旧图例去理解新图,自然会觉得“看不懂”。所以每次改图时,我总会顺带看一眼右下角图例是否还准确。这个细节小,但直接影响整张图的可信度。

最后分享一个我坚持了很久的小习惯

画完图之后,我通常不会马上发出去,而是先放一晚,第二天再打开看一遍。这个“隔夜检查”帮我避免过太多次低级错误:箭头方向画反、连线挂错节点、图层漏开导致某区域被隐藏。人刚画完图时,脑子自带滤镜,会不自觉地忽略错误;隔一天再回看,眼睛就“干净”了,一眼就能发现那些当时觉得“没问题”的破绽。Diagram-design做到后面,拼的其实不是手速,也不是工具熟练度,而是愿不愿意在动笔之前多花半小时想清楚,在画完之后再花一晚让它沉淀一下。这两步做好了,你的图一定能比大多数人专业一截。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 19:11:35

2026年Agent岗位面试全攻略:考点拆解、系统设计与避坑指南

2026年,Agent相关的岗位需求肉眼可见地爆发了。年初我和几个在大厂做技术面试官的朋友聊天,大家共同的感受是:简历里写“会用LangChain调API”的候选人已经很难进入下一轮了,面试重点正在从“会不会用框架”快速转向“能不能理解A…

作者头像 李华
网站建设 2026/10/21 19:11:30

发电机中性点接地电阻柜选型设计与运行维护指南

1. 为什么发电机中性点必须经电阻接地 1.1 接地方式选择的底层逻辑 先说一个很多刚入行的朋友容易忽略的事实:发电机中性点不是想接地就接地,也不是越“实在”越好。中压发电机的定子绕组在运行中一旦发生单相接地,故障点会流过电容性电流和…

作者头像 李华
网站建设 2026/10/21 19:11:30

从零实现浏览器图表设计器:核心架构与交互实战

最近在做的内部项目代号叫 diagram-design,一个跑在浏览器里的图表设计器。简单说,就是让用户能在一张画布上拖拽节点、连线、框选、缩放、撤销重做,最后导出成一份结构化数据。这个项目从需求确定到核心逻辑跑通,前后迭代了好几版…

作者头像 李华
网站建设 2026/10/21 19:11:11

Agent-Skills:面向可验证能力的工程化建模方法

1. “agent-skills”不是新词,而是能力建模的底层转向最近在多个技术社区和内部项目复盘会上,频繁看到“agent-skills”这个组合被单独拎出来讨论——它既不指代某个开源库,也不是某家公司的私有SDK命名,更不是AI模型微调时的训练…

作者头像 李华
网站建设 2026/10/21 19:10:40

Agent Skills:可注册、可编排、可审计的能力契约范式

1. “agent-skills”不是新名词,而是能力建模的底层转向 最近在多个技术社区和开源项目讨论区里,“agent-skills”这个词高频出现,但它既不是某个具体SDK的名称,也不是某家公司的私有术语,而是一种正在快速收敛的 能力…

作者头像 李华
网站建设 2026/10/21 19:10:09

WebCodecs实现H265软解码:绕过浏览器差异的完整方案

做播放器开发的朋友应该都有个共同的痛点:后端把码流转成了 H265,前端却怎么都播不起来。Safari 上好好的,Chrome 直接黑屏;Windows 上硬解很流畅,换台 Mac 又报“不支持”。这些乱象的根源在于浏览器对 HEVC&#xff…

作者头像 李华