news 2026/11/4 7:47:04

Mac版Axure RP 9中文界面与高保真交互原型落地指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mac版Axure RP 9中文界面与高保真交互原型落地指南

简介:Axure RP 9 for Mac 中文破解版面向 macOS 平台的产品经理、交互设计师和原型设计学习者,适用于低保真与高保真原型搭建、页面流程梳理、交互演示及团队评审等场景。该版本采用重新设计的界面和硬件加速渲染引擎,文件结构针对保存、加载速度做了优化,简化画布让缩放更平滑、编辑更快捷,便于读者练习页面跳转、组件交互与原型验证。资源以 zip 压缩包分发,整体约 54.67MB;上游暂未提供文件总数及主要文件类型明细,包内具体构成需以实际下载内容为准。已有 3926 人学习或下载,适合希望体验 Axure RP 9 中文环境、熟悉新版原型工作流的中级用户参考。

1. Axure RP 9 在 Mac 上到底该怎么落地:先搞清楚它解决什么问题

在 Mac 上折腾 Axure RP 9 的人,十个里有八个卡在同一件事上:软件装完了,界面全是英文,交互面板里一堆词对不上,做出来的原型在评审会上被一句“点了没反应”打回来。Axure 不是画图工具,它的价值在于把需求文档里那些“点击切换、列表筛选、表单校验”变成能点的页面,让产品和开发在写代码之前先把分歧吵完。这篇面向的是已经拿到 Mac 版安装包、准备拿它做高保真原型的从业者,尤其是需要中文界面、需要交付可评审 HTML 的那批人。下面按环境、文件结构、交互、避坑、交付的顺序,把整套流程拆开讲,每一步都给到能直接抄的配置和脚本。

2. Mac 环境准备:界面中文化与首次启动的三道关

2.1 装之前先把系统账算清楚:芯片架构、系统版本与磁盘余量

Mac 版 Axure RP 9 是 Intel 时代打包出来的应用,在 Apple Silicon 机器上要靠 Rosetta 2 转译运行。这条信息决定了三件事:首次启动明显偏慢;系统里没装转译层时双击会直接弹提示;复杂图形滚动时更容易掉帧。我一般先跑三条命令把账算清楚再动手。

sw_vers # 看 macOS 主版本号,太老的系统交互渲染会不稳 uname -m # arm64 是 Apple Silicon,x86_64 是 Intel df -h /Applications # 看系统盘可用空间,低于 15G 先清一轮

第一条输出里的 ProductVersion 决定后面要不要考虑兼容问题,老系统上中继器分页不渲染的情况我见过。第二条输出的架构决定要不要预留转译层的安装步骤,arm64 机器第一次启动这类 Intel 应用时系统会提示安装,同意就行。第三条看 Avail 那一列,应用本体不大,真正吃空间的是自动备份和历史副本,一个两百页的高保真工程,备份目录一个月能吃掉两三个 G。

还有一件常见的事:从浏览器直接下载的应用包会被系统加上“来源”标记,双击时提示无法打开。这不是文件坏了,是系统的隔离属性在起作用。常见做法是右键打开,或者在系统设置的隐私与安全性里对被拦下的那一项手动放行。

xattr -l "/Applications/Axure RP 9.app" # 看有没有 com.apple.quarantine 属性

如果输出里确实带隔离标记,右键“打开”一次之后系统就会记住这个选择,不必反复操作。要注意的是,只有你自己确认过来源的文件才值得放行。

2.2 中文界面为什么“放进去了还是英文”:语言资源的加载顺序与缓存

Mac 应用的界面文字来自应用包内部的语言资源目录,路径是Contents/Resources/lang。很多人替换完目录后重启还是英文,问题基本出在两个地方:资源目录层级放错了一层,或者偏好缓存里还记着上一次的语言选择。

# 1. 确认语言资源目录的真实结构 ls -la "/Applications/Axure RP 9.app/Contents/Resources/lang" # 2. 看当前目录下有几个候选语言目录,正常应该只有一个 default find "/Applications/Axure RP 9.app/Contents/Resources/lang" -maxdepth 2 -type d

第一条命令的输出里应该能看到一个名为default的目录,界面文字就取自它内部的资源文件。第二条命令如果列出多个并列的语言目录,就说明放错了层级,应用只会读最外层的那一个。正确做法是先把原来的default整个移到桌面留作回退,再把中文资源目录改名或替换成default,不要出现default/中文/...这种嵌套。

第二个坑是偏好缓存。应用的界面语言选择会写进用户的偏好文件,改完资源目录但缓存没清,界面就保持原样。

# 先备份,再删,出问题能立刻还原 cp ~/Library/Preferences/com.axure.AxureRP9.plist ~/Desktop/axure9-pref-backup.plist defaults read com.axure.AxureRP9 | head -40 # 看一眼里面有哪些键,心里有数 rm ~/Library/Preferences/com.axure.AxureRP9.plist

defaults read那一步不是必须的,但它能让你知道这个文件里除了语言还存了什么,比如最近打开列表和窗口位置。删掉之后首次启动会重建,代价是要重新配一遍偏好,所以我在删之前一定先复制一份到桌面。如果删完仍然不生效,说明你替换的资源目录本身不完整,缺了部分资源文件,这时候回退到备份目录,别在残缺状态下继续折腾。

注意:语言资源只做界面文字替换,不改变软件的授权状态。商用环境请走正规授权渠道,这一点别含糊。

2.3 首次启动必须改的六项偏好:备份、字体、单位

界面语言搞定之后,别急着画页面,先把偏好设置过一遍。默认配置是给演示场景设计的,真拿来交付会一直绊脚。

偏好项建议值为什么这么设
自动备份间隔5 分钟默认值偏长,一次闪退能丢半小时的交互配置
自动备份保留份数20 份以上出问题时要能往前翻两三个版本,只留三五份不够
默认字体PingFang SC默认西文字体在中文页面里字重和行高都不对
撤销层级100 步以上调中继器时误操作密度很高
页面单位px和前端对齐的口径一致,避免评审时反复换算
网格与吸附8px 网格开启交付给前端时元素尺寸更整齐,减少对齐争议

自动备份的路径在偏好里能看到,通常是用户目录下 Application Support 里的一个子目录。我习惯把路径复制出来存个备忘,因为真丢东西的时候,第一件事就是去那个目录里翻最近的备份,而不是在应用里找撤销。

# 找一下自动备份目录的实际位置 find ~/Library/Application\ Support -maxdepth 4 -type d -iname "*backup*" 2>/dev/null

这条命令只在找不到路径时用,正常情况偏好设置界面就能看到。找到目录之后可以顺手用ls -lt按时间排序,确认最近一次备份的时间戳是否对得上你刚才的编辑。

2.4 建一个自己的空白模板工程

重复劳动最浪费时间的是每次新建文件都要重设页面尺寸、栅格、正文字阶、常用元件样式。我的做法是建一个空白工程,把这些全部配好,另存为模板,以后每个新项目从它复制出来。

模板里我会固定放几样东西:一套 8 列栅格、三种文字层级(标题、正文、辅助说明)、一个标准页头母版、一个空的中继器元件、一个全局变量占位。这样接手任何需求时,第一小时不是配样式,而是直接画流程。模板工程单独放一个目录,不要和正式项目混在一起,否则哪天误改模板会传染到所有后续项目。

3. 拆开一个 .rp 文件:页面、母版与资源的真实结构

3.1 .rp 不是黑盒:先用 unzip 看一眼里面

很多人把.rp当成不透明的二进制文件,其实它就是一个压缩包,里面是 XML 加资源目录。理解这一点之后,很多问题就有了排查路径:文件打不开可以先解包看结构有没有损坏,页面数量异常可以统计 XML,交付前还可以脚本化巡检。

# 不解包,先列出内部条目,判断结构是否完整 unzip -l ./demo.rp | head -40 # 需要细看时再解到临时目录,别在工程目录里操作 unzip -o ./demo.rp -d ./_rp_unpacked find ./_rp_unpacked -maxdepth 2 -type d | sort

第一条命令的-l是只列出不落地,输出里能看到条目数量和目录层级,如果条目数为零或者报“无法识别的归档”,那基本可以判定文件损坏,先去找自动备份。第二条命令把内容解到临时目录,-o表示覆盖已存在文件,所以这个目录名要固定并且定期清,不然会残留上一次的旧文件,统计结果就失真了。第三条列出两层目录,用来确认页面、资源、元数据这几类目录都在。

不同小版本的目录命名会有差异,所以我不建议记死某个具体路径,而是先看一遍输出,再针对自己手上的版本写脚本。这是解包类排查的基本纪律:先观察,再动手。

3.2 从目录映射到画布:页面、母版、动态面板的对应关系

解包之后你会看到几个关键部分:描述整个工程的元数据文件、按页面拆分的目录、存放图片和字体等资源的目录。页面目录里每个页面通常对应一个以数字 ID 命名的条目,这个 ID 就是内部引用用的键,页面重命名不影响它,但复制粘贴页面时会新建 ID。

母版是独立的一类,它被页面引用而不是复制,所以改一次母版,所有引用它的页面同步生效。这也是团队协作里最容易出问题的地方:两个人同时改一个母版,合并时谁也说不清哪个版本是对的。动态面板则属于页面内部结构,它的每个状态在文件里是独立的子树,状态越多文件越大,一个页面里塞十几个多状态动态面板,打开就会明显卡。

搞清这套映射关系,遇到“改了母版但某个页面没变”就不会抓瞎——多半是那个页面里放的是复制出来的元件,不是母版实例。判断方法很简单,选中元件看属性面板上有没有母版名称,没有就是普通元件。

3.3 用 Python 做一次工程体检:空页面、超长命名与资源体积

工程超过五十页之后,靠人工翻是翻不完的。我一般会跑一次体检脚本,把几个容易出问题的指标先列出来。

import zipfile import re from collections import Counter from pathlib import Path rp = Path("./demo.rp") with zipfile.ZipFile(rp) as z: names = z.namelist() # 1. 资源体积分布:找出体积最大的前十个条目 big = sorted(z.infolist(), key=lambda i: i.file_size, reverse=True)[:10] for i in big: print(f"{i.file_size/1024/1024:8.2f} MB {i.filename}") # 2. 按扩展名统计条目数量,判断资源类型是否失控 ext = Counter(Path(n).suffix.lower() for n in names) print(dict(ext.most_common(10))) # 3. 抓出命名过长的页面(很多工具对路径长度有上限) long_names = [n for n in names if len(n) > 120] print("超长路径条目:", len(long_names))

第一段按未压缩体积排序,直接把最大的十个条目打出来。原型里最容易失控的是截图和背景大图,一张没压缩的 4K 背景图能顶上几百个页面。第二段按扩展名统计,如果图片类条目占了大头,说明需要做一轮资源瘦身,把装饰性大图换成压缩后的版本。第三段的超长路径检查是为了跨平台交付,路径过长在解压和上传环节都可能失败。

脚本只读不改,跑完看清楚再决定动哪里,别一上来就批量删资源。

3.4 版本管理:哪些文件该进仓库,哪些必须忽略

.rp是压缩包,二进制文件做 diff 没有意义,所以版本管理策略要提前定。我的做法是:只把.rp主文件和一个说明文件纳入版本管理,自动备份目录、解包目录、导出的 HTML 全部写进忽略列表。

# 项目根目录下的忽略规则,按需增删 cat > .gitignore <<'EOF' # 自动备份与临时解包目录 _AutoBackup/ _rp_unpacked/ *.bak # 导出的 HTML 产物,不进版本库 /dist/ # 系统垃圾文件 .DS_Store EOF

这段规则里最关键的是_rp_unpacked/,解包目录体积大且随时可重建,纳入版本管理只会让仓库迅速膨胀。/dist/是导出产物,每次都能重新生成,同样不入库。团队里如果有人习惯把导出的 HTML 直接提交,仓库半年就能到几个 G,克隆一次要等很久。

需要多人并行改同一个工程时,更稳的做法是按模块拆文件,一个人负责一部分页面,最后合并到一个主工程,而不是几个人同时开同一个.rp。压缩包的合并冲突是没法手工解决的,这是血泪经验。

4. 交互落地:动态面板、中继器与全局变量三件套

4.1 动态面板的三种切换方式与状态命名约定

动态面板是 Axure 里最核心也最容易被用坏的元件。它的本质是一组互斥的图层状态,同一时刻只显示一个。切换方式我归成三类,选错了后期维护成本会翻倍。

第一类是点击触发。给按钮加交互,动作选“设置面板状态”,指定目标面板和目标状态,配上动画。这种方式最直观,适合导航切换、弹窗开关。第二类是页面载入时按条件设置。适合根据上一个页面传过来的变量值决定初始状态,比如从列表页进入详情页时默认展开哪一栏。第三类是通过元件事件间接触发,比如中继器某一项被点击时联动另一个面板。

状态命名是撑住后期维护的关键。默认的 State1、State2 用不了两周就没人记得哪个是哪个。我的约定是“场景_结果”,比如tab_默认、tab_选中、弹窗_打开、弹窗_关闭。命名里带中文在预览时不会出问题,但如果要导出给前端看,建议用英文加下划线,避免某些环境下的编码差异。

还有一个细节:面板状态的尺寸要统一。不同状态尺寸不一致时,切换会让周围元素跳动,评审时特别显眼。我一般在第一个状态里定好尺寸,其余状态复制这个尺寸再改内容。

4.2 中继器的数据集:列名、载入事件与筛选

中继器解决的是“一堆长得一样的东西”。它的结构分三层:数据集(表格形式的行与列)、项模板(每行长什么样)、交互(排序、筛选、分页)。数据集里每一列就是一个字段,项模板里通过[[Item.列名]]引用。

中继器的列名建议用英文,因为后面拼表达式时中文容易和界面文字混在一起看不清。我常用的一套列名如下:

列名类型用途
id文本行唯一标识,用于跳转和定位
title文本主要展示字段
status文本状态标记,筛选条件依赖它
updatedAt文本排序用的时间字段,格式统一成 YYYY-MM-DD
owner文本责任人,用于分组统计

数据载入的关键在“每项载入时”这个事件里做绑定,而不是在页面载入时统一处理。前者每行执行一次,后者只执行一次,混淆了就会导致所有行显示同一份数据。绑定写法就是在项模板里的文本元件上直接写[[Item.title]]这样的表达式,简单场景根本不需要写逻辑。

筛选的做法是给中继器加“添加筛选”,条件写成[[Item.status == 变量值]]。这里有个容易翻车的地方:比较的两边类型要一致,一边是数字一边是文本,结果永远是 false,界面上看就是筛完一条不剩。我一般会在筛选前先把输入值做一次空值判断,空的时候不加筛选条件,直接把完整列表显示出来。

分页则在“页面载入时”事件里设置每页条数,配合上一页下一页按钮改页码。条目很少的时候别开分页,多一层状态就多一堆要测的路径。

4.3 全局变量模拟登录态与页面间传参

原型要演示“登录后才能看的页面”,靠复制页面是做不完的。全局变量的作用是存一个跨页面的值,页面载入时读它、按钮点击时改它。常见做法是建三个变量:当前用户、当前角色、登录标记。

具体配置分三步。第一步,在工程的全局变量面板里新增变量并给一个空默认值。第二步,在登录页的提交按钮上,加交互设置变量值,把输入框里的文字赋给“当前用户”,登录标记设为真。第三步,在受保护页面的页面载入事件里加条件判断,如果登录标记不为真,就跳回登录页。

变量引用的写法是双中括号包变量名。要注意的是变量值是文本类型,判断真假时别写成标记 == true,用标记 == "1"这种字符串比较更稳。我见过因为类型不一致导致判断永远走不到分支的情况,排查半天。

页面间传参还可以更偷懒:把参数拼在跳转链接后面,目标页面载入时从 URL 里取值赋给变量。这种方式的好处是刷新页面后状态还在,适合需要反复演示的评审场景。

4.4 用 javascript 链接补最后一块:Axure 做不到的那些小动作

有些效果用原生交互拼不出来,比如按回车触发按钮、滚动到指定位置、动态改页面标题。这类需求可以用“打开链接”动作里填javascript:开头的地址来实现,本质是在预览页面里执行一段脚本。

// 绑定在文本框的“按键松开时”交互上,链接地址填下面的内容 // 作用:按下回车时触发登录按钮的点击,模拟真实表单行为 javascript: (function(){ var e = window.event || {}; if (e.keyCode === 13) { // 通过文本匹配找到目标按钮并触发点击 var btns = document.querySelectorAll('.ax_default'); for (var i = 0; i < btns.length; i++) { if (btns[i].innerText.indexOf('登录') > -1) { btns[i].click(); break; } } } })();

这段代码的逻辑是:先判断按键码是不是 13,只在回车时继续;然后遍历页面上所有元件节点,用文字内容匹配目标按钮,找到就触发点击。参数上唯一需要改的是匹配文字,把“登录”换成你实际按钮上的文字。用文字匹配是因为 Axure 导出后元件的类名和 ID 都是自动生成的,写死 ID 换个版本就失效。

限制也要说清楚:这类脚本只在内置预览和导出的 HTML 里有效,在编辑器里不执行;页面上的元件文字改动后,匹配逻辑要同步改。所以我把这类技巧只用在演示频率最高的那一两个交互上,其余尽量用原生交互拼,可维护性差一个量级。

5. 避坑与排查:Mac 上五个高频翻车点

5.1 双击工程提示应用无法打开

现象:双击.rp文件,系统弹出无法打开的提示,选择“打开”也没有反应,但从应用图标启动却正常。

原因:系统对从网络下载的应用包和文件加了隔离属性,双击关联文件时触发校验,校验不通过就直接拦下。这类提示和文件本身是否损坏是两回事,很多人误以为是工程坏了,跑去下第二份安装包。

解决:先确认应用本体能单独启动,再检查隔离属性。定位到应用包后查看扩展属性,有隔离标记的,手动右键打开一次,系统会记住这次选择。工程文件同样处理:右键,选择打开方式,指定应用。如果只有某一个工程打不开,其余正常,那就不是隔离问题,去自动备份目录找最近一份备份对比,判断是不是文件传输中断导致的不完整。

5.2 中文界面装完只翻了一半

现象:主菜单是中文,属性面板、交互面板里的字段还是英文,或者反过来。

原因:资源目录里只替换了部分资源文件,不同面板的文字取自不同资源条目;另一种情况是替换后没有清偏好缓存,应用读的还是上一次的选择。

解决:先把资源目录整个换掉而不是单个文件替换,替换前把原目录整体移到桌面备份。然后清一次偏好文件再启动。如果仍然半中半英,说明手上的资源包和当前小版本不匹配,选个稳定的小版本,配它对应的资源包,别混用。

5.3 大工程打开要三分钟,滚动一卡一卡

现象:五十页以内的工程没问题,上百页之后打开明显变慢,滚动和拖拽元件都有延迟。

原因:解包看体积分布基本能定位。常见来源是未压缩的大图、单个页面里塞了太多多状态动态面板、以及长期没清理的历史备份堆积在同一个目录。

解决:先跑一次资源统计,把前十大体积条目列出来,装饰性大图压到合适尺寸再重新导入;把超过八个状态的动态面板拆成多个面板按需切换;把自动备份目录定期归档到外部存储,只保留最近两周。这三步做完,我手上一个两百页的工程打开时间从两分多回到二十秒左右。

5.4 导出 HTML 后点了没反应,或者页面一片空白

现象:编辑器里预览一切正常,导出 HTML 放给评审看,部分交互失效,个别页面点进去是空白。

原因:三类情况最常见。一是导出时没勾全页面,某些页面没被包含;二是交互里引用了只在编辑环境存在的资源,比如外部图片路径写了本地绝对路径;三是文件名里带了特殊字符,在部分浏览器或服务器上解析异常。

解决:导出前把页面列表过一遍,确认要交付的都在。图片统一走工程内导入,不用外部链接。页面命名只用字母、数字、下划线和中划线。导出后立刻在本地打开首页点一遍主流程,别等评审开始才发现。

5.5 崩了一次,半天的配置全没了

现象:应用异常退出,重开之后最近的编辑内容消失,撤销也回不来。

原因:自动备份间隔设得太长,或者备份目录被清理工具当成垃圾文件删了。还有一种隐蔽情况:备份目录所在磁盘空间不足,备份静默失败,界面上没有任何提示。

解决:把备份间隔改到五分钟,保留份数调到二十份以上,每周确认一次备份目录里最新文件的时间戳。我现在的习惯是,每次做完一段复杂的交互配置就手动另存一个带时间后缀的副本,虽然土,但比事后找备份靠谱。

6. 交付前的一次自检:把原型变成能评审的 HTML

6.1 导出参数与目录约定

导出走生成 HTML 的入口,输出目录固定成dist/版本号/,这样每次交付都留档,评审意见能对应到具体版本。导出选项里,把“包含所有页面”勾上,页面单独成目录的选项按需开,页面数超过三十时我建议开,单文件过大在弱网环境打开很慢。图片和资源都放工程内部,不要引用外部链接,评审时打开的是一个不依赖网络的静态包。

6.2 用脚本做交付前断链检查

手工点页面只能覆盖主流程,边角页面容易漏。我一般跑一遍断链检查,把所有内部引用过一遍。

import re from pathlib import Path root = Path("./dist/v1.0") htmls = list(root.rglob("*.html")) bad = [] for f in htmls: text = f.read_text(errors="ignore") # 抓出 href/src 里的本地相对路径,跳过外链和锚点 for ref in re.findall(r'(?:href|src)="([^"]+)"', text): if ref.startswith(("http", "#", "javascript:", "data:")): continue if not (f.parent / ref).exists(): bad.append((str(f), ref)) print(f"页面数 {len(htmls)},疑似断链 {len(bad)} 条") for item in bad[:20]: print(item)

脚本遍历导出目录下所有 HTML,用正则抓出href和src里的引用,跳过外链、锚点和脚本链接,只校验本地相对路径是否存在。输出的前二十条足够定位问题,剩下的通常是同一类原因批量出现。这一步能挡掉评审现场“这个按钮点了跳空白”的尴尬。

我现在每次导出前都强制跑一遍这个脚本加一次主流程手点,哪怕时间紧也跳不过去——有一次偷懒省了,结果评审开场第一个按钮就跳空页,现场重新导出花了十分钟。希望帮到你。

本文还有配套的精品资源,点击获取

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

综合能源园区非合作交易机制设计与优化实践

1. 项目背景与核心价值在能源结构转型的大背景下&#xff0c;综合能源园区正成为电力市场改革的重要试验场。这个项目针对园区内三类典型市场主体——系统能源运营商、分布式光伏用户和电动汽车充电运营商&#xff0c;提出了一套创新的非合作交易机制。我在参与某省级工业园区微…

作者头像 李华
网站建设 2026/11/4 7:45:25

Pytest Fixture循环限制解析与参数化测试实践

1. 问题背景与现象解析在pytest测试框架中&#xff0c;fixture是用于提供测试依赖的核心机制。最近社区中一个引发热议的现象是&#xff1a;当开发者尝试在fixture内部使用for循环来动态生成多个测试用例时&#xff0c;pytest会抛出明确禁止的异常。这个设计决策看似反直觉&…

作者头像 李华
网站建设 2026/11/4 7:44:41

Decoder-Only架构原理与工程实践全解析

1. Decoder-Only架构&#xff1a;大模型时代最被低估的底层设计选择你打开任何一个主流大语言模型的官方技术报告&#xff0c;翻到模型结构图那一页&#xff0c;十有八九会看到一个醒目的“Decoder-only”标签。它不像“Transformer”那样家喻户晓&#xff0c;也不像“LoRA微调…

作者头像 李华
网站建设 2026/11/4 7:43:43

水库自动化巡检系统:智能传感与AI预警实践

1. 水库自动化巡检系统概述作为一名水利信息化工程师&#xff0c;我在过去五年参与了国内多个大型水库的智能化改造项目。传统的人工巡检方式确实存在诸多痛点&#xff1a;巡检人员需要徒步走遍大坝各个角落&#xff0c;用肉眼观察裂缝、用手持设备测量位移&#xff0c;不仅效率…

作者头像 李华
网站建设 2026/11/4 7:43:41

Web逆向工程:无限debugger机制解析与绕过策略

1. 无限debugger机制解析与应对策略在Web逆向工程和调试过程中&#xff0c;我们经常会遇到网站设置的无限debugger保护机制。这种机制的核心原理是通过不断触发debugger语句来阻止开发者工具的常规调试操作。具体表现为&#xff1a;当开发者工具打开时&#xff0c;JavaScript代…

作者头像 李华