2026-10-27 11:17:24 +08:00
|
|
|
|
%% Copyright 2016 Christophe Roger
|
|
|
|
|
|
%
|
|
|
|
|
|
% Author:
|
|
|
|
|
|
% Christophe Roger (Darwiin)
|
|
|
|
|
|
%
|
|
|
|
|
|
% This work may be distributed and/or modified under the
|
|
|
|
|
|
% conditions of the LaTeX Project Public License, either version 1.3c
|
|
|
|
|
|
% of this license or (at your option) any later version.
|
|
|
|
|
|
% The latest version of this license is in
|
|
|
|
|
|
% http://www.latex-project.org/lppl.txt
|
|
|
|
|
|
% and version 1.3 or later is part of all distributions of LaTeX
|
|
|
|
|
|
% version 2005/12/01 or later.
|
|
|
|
|
|
%
|
|
|
|
|
|
% This work has the LPPL maintenance status `maintained'.
|
|
|
|
|
|
%
|
|
|
|
|
|
% The Current Maintainer of this work is M. C. Roger.
|
|
|
|
|
|
%
|
|
|
|
|
|
% This work consists of the files awesome-source-cv.cls
|
|
|
|
|
|
|
|
|
|
|
|
\ProvidesClass{awesome-source-cv}[2016/11/05 v1.6.1 Awesome Source CV Class]
|
|
|
|
|
|
|
|
|
|
|
|
\LoadClass[a4paper]{article}
|
|
|
|
|
|
|
|
|
|
|
|
\DeclareOption{green}{
|
|
|
|
|
|
\def\@green{green}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\DeclareOption{red}{
|
|
|
|
|
|
\def\@red{red}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\DeclareOption{indigo}{
|
|
|
|
|
|
\def\@indigo{indigo}
|
|
|
|
|
|
}
|
|
|
|
|
|
\DeclareOption{orange}{
|
|
|
|
|
|
\def\@orange{orange}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\DeclareOption{localFont}{
|
|
|
|
|
|
\def\@local{local}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\DeclareOption{alternative}{
|
|
|
|
|
|
\def\@alternative{alternate}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\ProcessOptions
|
|
|
|
|
|
|
|
|
|
|
|
% Dependences
|
|
|
|
|
|
%A Few Useful Packages
|
2026-10-29 11:59:43 +08:00
|
|
|
|
% ⚠️ 选项名用 french,不要用旧写法 frenchb。
|
|
|
|
|
|
% frenchb 是 babel 早期的法语方言名,两个名字在 TeX Live 2022 及更早
|
|
|
|
|
|
% 版本上等价;但 TeX Live 2025 的 babel 已把 frenchb 从「已知语言」
|
|
|
|
|
|
% 列表里移除,写旧名会报
|
|
|
|
|
|
% ! Package babel Error: Unknown option `frenchb'.
|
|
|
|
|
|
% 即使压住这条,还会进一步炸在 \begin{document} 处:
|
|
|
|
|
|
% ! Undefined control sequence.
|
|
|
|
|
|
% \__hook begindocument ...fter {\bbl@main@language }...
|
|
|
|
|
|
% 改用 french 在老版本上同样可用,是向前兼容的写法。
|
|
|
|
|
|
% (本模板正文是中文,babel 这里只影响西文连字与断词细节,
|
|
|
|
|
|
% 中文断行由 xeCJK 负责。)
|
|
|
|
|
|
\RequirePackage[french]{babel}
|
2026-10-27 11:17:24 +08:00
|
|
|
|
%\RequirePackage[utf8]{luainputenc} % luatex
|
|
|
|
|
|
\RequirePackage{fontspec} % for loading fonts
|
|
|
|
|
|
\RequirePackage{url,parskip} % other packages for formatting
|
|
|
|
|
|
\RequirePackage[usenames,dvipsnames]{xcolor}
|
|
|
|
|
|
\RequirePackage{fullpage}
|
|
|
|
|
|
\RequirePackage[margin=1.5cm]{geometry}
|
|
|
|
|
|
\RequirePackage{fontawesome}
|
|
|
|
|
|
\RequirePackage{hyperref}\hypersetup{hidelinks}
|
|
|
|
|
|
\RequirePackage{titlesec}
|
|
|
|
|
|
\RequirePackage{array}
|
|
|
|
|
|
\RequirePackage{enumitem}
|
|
|
|
|
|
\RequirePackage{longtable}
|
|
|
|
|
|
\RequirePackage{etoolbox}
|
|
|
|
|
|
\RequirePackage{tikz}
|
|
|
|
|
|
\RequirePackage[skins]{tcolorbox}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
% \DeclareUnicodeCharacter{00E9}{\'{e}} %luatex
|
|
|
|
|
|
|
|
|
|
|
|
% Define default accent colors
|
|
|
|
|
|
%\definecolor{basecolor}{HTML}{000066} %BLUE
|
|
|
|
|
|
\definecolor{basecolor}{HTML}{0f4c81}
|
|
|
|
|
|
\ifundef{\@green} {
|
|
|
|
|
|
\ifundef{\@red} {
|
|
|
|
|
|
\ifundef{\@indigo}{
|
|
|
|
|
|
\ifundef{\@orange} {}
|
|
|
|
|
|
{ \definecolor{basecolor}{HTML}{e68a00} }
|
|
|
|
|
|
}
|
|
|
|
|
|
{ \definecolor{basecolor}{rgb}{0.2, 0.07, 0.48} }
|
|
|
|
|
|
}
|
|
|
|
|
|
{ \definecolor{basecolor}{HTML}{b30000} } %RED
|
|
|
|
|
|
}
|
|
|
|
|
|
{ \definecolor{basecolor}{rgb}{0.0, 0.62, 0.38} }
|
|
|
|
|
|
|
|
|
|
|
|
\definecolor{darkGrey}{HTML}{989898}
|
|
|
|
|
|
|
|
|
|
|
|
\colorlet{linkcolor}{basecolor}
|
|
|
|
|
|
\colorlet{accentcolor}{linkcolor!90}
|
|
|
|
|
|
\colorlet{symbolcolor}{linkcolor!85}
|
|
|
|
|
|
|
|
|
|
|
|
% Setup hyperref package, and colours for links
|
|
|
|
|
|
%\definecolor{linkcolour}{rgb}{0,0.2,0.6}
|
|
|
|
|
|
\hypersetup{breaklinks}
|
|
|
|
|
|
|
|
|
|
|
|
\pagestyle{empty} % non-numbered pages
|
|
|
|
|
|
%\font\fb=''[cmr10]'' % for use with \LaTeX command
|
|
|
|
|
|
|
|
|
|
|
|
% Setup CV sections
|
|
|
|
|
|
\titleformat{\section}{\Large\raggedright}{}{0em}{}[\titlerule]
|
|
|
|
|
|
\titlespacing{\section}{0pt}{2pt}{2pt}
|
|
|
|
|
|
|
|
|
|
|
|
% Configure list
|
2026-10-27 13:13:54 +08:00
|
|
|
|
\setlist[itemize,1]{label=\faAngleRight, nosep, leftmargin=2em}
|
|
|
|
|
|
|
|
|
|
|
|
%----------------------------------------------------------------------
|
|
|
|
|
|
% 中西文之间的断行弹性
|
|
|
|
|
|
%
|
|
|
|
|
|
% 现象:论文条目里「… Applications (ICIEA), 88--93. 中国青岛, 中国: IEEE,
|
|
|
|
|
|
% 2023. https://doi.org/…」这一整段会冲出右边距 88.5pt,文字一直排到
|
|
|
|
|
|
% 页面纸边(x=595.5,而纸宽才 595.28)。用 Termes 时只有 0.4pt 之差,
|
|
|
|
|
|
% 换 Cochineal 后(西文窄 1.9%,断点位置整体前移)暴露成 88.5pt。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 根因:XeLaTeX 里「中文紧跟英文」的位置默认**不是**断开点,TeX 会把
|
|
|
|
|
|
% 「2023 IEEE 18th Annual Conference on Industrial Electronics and
|
|
|
|
|
|
% Applications (ICIEA), 88--93.」当成一个长单词找断点,找到头也没有,
|
|
|
|
|
|
% 于是硬冲出去。上游模板没有设 \emergencystretch,也没有开
|
|
|
|
|
|
% \XeTeXlinebreaklocale,所以一点余量都没有。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 修法(三选一,这里选第 1 个):
|
|
|
|
|
|
% ① 给 itemize 加 \emergencystretch —— 允许在极端情况下把行拉松
|
|
|
|
|
|
% 而不是硬冲出去。不动字体、不改内容、不影响其他环境。
|
|
|
|
|
|
% ② 全局 \sloppy —— 效果类似但会把**所有**段落的词距都放松,
|
|
|
|
|
|
% 连正常的短段落也变松散,观感下降。
|
|
|
|
|
|
% ③ 在 .tex 里手工插入 \allowbreak / \- —— 要逐条改,换字体又要重来。
|
|
|
|
|
|
%
|
|
|
|
|
|
% \emergencystretch=3em 的量级:按 10pt 正文,3em=30pt,足以吃掉
|
|
|
|
|
|
% 88.5pt 中的大部分,剩余部分交给行内词距自然拉伸。若将来换了更宽的
|
|
|
|
|
|
% 西文字体(如 Pagella 宽 10.8%)还报 Overfull,把这个值调到 4em~5em。
|
|
|
|
|
|
% ⚠️ 不要设成 \maxdimen 一劳永逸 —— 那等于关掉断行检查,
|
|
|
|
|
|
% 真正的排版问题会被全部藏起来,日志再也不报。
|
|
|
|
|
|
%----------------------------------------------------------------------
|
|
|
|
|
|
\setlength{\emergencystretch}{3em}
|
2026-10-27 11:17:24 +08:00
|
|
|
|
|
|
|
|
|
|
% Setup Array : new column type
|
2026-10-27 13:13:54 +08:00
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 原来是 >{\hfill}m{#1},即「固定宽度 + 内容靠右贴」。
|
|
|
|
|
|
% 用在本简历里会出问题:\hfill 让短日期贴着左列的**右**边界排,
|
|
|
|
|
|
% 日期本身只有约 57pt 宽而左列有 2.5cm=71.13pt,于是日期左边缘落在
|
|
|
|
|
|
% 42.5(左边距) + 6(\tabcolsep) + 71.13 - 57.3 = 62.33pt
|
|
|
|
|
|
% 而其他章节(工作经历/教育经历/奖励与荣誉)用的是 tabular{rl},
|
|
|
|
|
|
% 左列宽度自适应到最长的日期区间(约 122pt),日期左边缘在
|
|
|
|
|
|
% 42.5 + 6 = 48.5pt
|
|
|
|
|
|
% 两节一比就差 13.8pt,看上去「项目经验往里缩了一点」。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 现在改成左对齐:日期左边缘回到 48.5pt,与其余章节的日期左边缘
|
|
|
|
|
|
% 严格对齐(本项目全部日期都是「YYYY 年MM 月」同宽 57.3pt,
|
|
|
|
|
|
% 所以左对齐后右边缘也齐,列不会显乱)。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 用 p{} 而不用 m{}:m{} 是「垂直居中」的 parbox 列,在
|
|
|
|
|
|
% longtable 里跨页断行时行为不如 p{} 稳;这张表一行可能很高
|
|
|
|
|
|
% (右栏带 itemize)。配 \arraybackslash 让 \\ 在列内恢复正常。
|
|
|
|
|
|
% ⚠️ R 列只被 experiences 环境使用(skills 环境虽也写了 R,但本
|
|
|
|
|
|
% 简历没有调用 section_skills),改动不会波及别处。若将来启用
|
|
|
|
|
|
% skills 环境,那里是「技能名 + 五点圆点」,左对齐同样合适。
|
|
|
|
|
|
\newcolumntype{R}[1]{>{\raggedright\arraybackslash}p{#1}}
|
2026-10-27 11:17:24 +08:00
|
|
|
|
|
|
|
|
|
|
%Italian hyphenation for the word: ''corporations''
|
|
|
|
|
|
\hyphenation{im-pre-se}
|
|
|
|
|
|
|
|
|
|
|
|
% Setup fonts
|
|
|
|
|
|
\defaultfontfeatures{Mapping=tex-text}
|
|
|
|
|
|
%
|
|
|
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------------------------
|
|
|
|
|
|
% Configuration for fonts
|
|
|
|
|
|
%-------------------------------------------------------------------------------
|
|
|
|
|
|
% ⚠️⚠️ 本文件已被改写:字体**全部**取自仓库公共字体包 ../fonts.tex。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 上游 awesom e-cv 的中文版原来这么配(共三处,都已删除):
|
|
|
|
|
|
% ① zh_cn-adobefonts_external.sty 里 \setCJKmainfont{AdobeSongStd-Light.otf}
|
|
|
|
|
|
% —— Adobe 宋/黑/楷/仿四款共 56 MB,商业授权,**不能随仓库分发**。
|
|
|
|
|
|
% 而且那份文件还拿 HarmonyOS Sans 去冒充 Bold/Italic/SmallCaps:
|
|
|
|
|
|
% BoldFont = HarmonyOS_Sans_SC_Regular.ttf
|
|
|
|
|
|
% ItalicFont = HarmonyOS_Sans_SC_Regular.ttf
|
|
|
|
|
|
% 等于"加粗=不变"、"斜体=不变",标题的层次全靠字号撑,是个将就做法。
|
|
|
|
|
|
% ② \setmainfont{SourceSansPro-Light}(localFont 分支)
|
|
|
|
|
|
% 9 个 .otf,SIL OFL 1.1 可用,但本仓库不打算为一份字体再带 4 MB。
|
|
|
|
|
|
% ③ \setfontfamily\FA[Path=fonts/]{FontAwesome}
|
|
|
|
|
|
% Path 指向本目录下不存在的 fonts/ —— 那份图标字体在 TeX Live 里。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 现在的映射:
|
|
|
|
|
|
% 西文正文 Source Sans Pro Light → TeX Gyre Termes(本仓库自带)
|
|
|
|
|
|
% 中文正文 Adobe Song / HarmonyOS → OUC Serif(思源宋体子集,自带)
|
|
|
|
|
|
% 中文粗体 (原来=不变) → OUC Serif Bold(真粗体)
|
|
|
|
|
|
% 中文斜体 无 → OUC Kai(楷体代斜体,中文惯例)
|
|
|
|
|
|
% FontAwesome TeX Live 系统包 → 仓库 fonts/fontawesome/
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 字体文件本体在 ../fonts/ 下,由 ../fonts.tex 统一设置,
|
|
|
|
|
|
% **不要在本文档或 .tex 里再写 \setCJKmainfont / \setmainfont**。
|
|
|
|
|
|
% 下面只做"西文用哪一档"的局部调整。
|
|
|
|
|
|
%-------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
% FontAwesome:图标字体已经放进仓库公共字体目录,
|
|
|
|
|
|
% ⚠️ 但**不要在这里重新声明 \FA** —— fontawesome.sty 自己在正文里就做了
|
|
|
|
|
|
% \newfontfamily{\FA}[Path=../fonts/fontawesome/]{FontAwesome.otf}
|
|
|
|
|
|
% 且它在 \RequirePackage{fontawesome} 时就执行(早于本 cls 的后面几句)。
|
|
|
|
|
|
% 这里再声明一次会报 "Font \FA already defined"(LaTeX3 的
|
|
|
|
|
|
% \NewDocumentCommand 语义),所以只留注释说明。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 上游原来是 \setfontfamily\FA[Path=fonts/]{FontAwesome},
|
|
|
|
|
|
% Path 指向本目录下并不存在的 fonts/ —— 只能靠系统字体兜底。
|
|
|
|
|
|
% 现在路径写进 fontawesome.sty 了。
|
|
|
|
|
|
|
2026-10-27 13:13:54 +08:00
|
|
|
|
% 西文正文:上游用 Source Sans Pro Light(很细),本模板改用 Cochineal。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 这里**不能**直接 \setmainfont —— 那会在 cls 里再写一套字体声明,
|
|
|
|
|
|
% 违反本仓库「字体只在 ../fonts.tex 声明」的规矩(换字号/换字体时
|
|
|
|
|
|
% 要改两处,早晚改漏一处)。改调用 fonts.tex 提供的开关命令。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 为什么从 Termes 换成 Cochineal:
|
|
|
|
|
|
% 中文用思源宋体(OUC Serif),笔画中等粗细;Termes 是 Times 的度量
|
|
|
|
|
|
% 兼容替代,笔画偏细偏紧,中英混排时西文那一段视觉上会"陷进去"。
|
|
|
|
|
|
% Cochineal(Minion 风格)笔画更饱满,与宋体灰度接近。
|
|
|
|
|
|
% 宽度只差 1.9%(229.68 → 225.42pt @10pt),断行位置基本不动。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 注意 \tnr / \tnrb 也被这个命令一并重指向,否则上游代码里显式写
|
|
|
|
|
|
% \tnr 的地方仍是 Termes,同一页会混两种西文字体。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 必须包在 \AtBeginDocument 里,不能直接写 \oucUseCochineal:
|
|
|
|
|
|
% cls 执行时主文件还没 \input{../fonts.tex},那个命令尚未定义,会报
|
|
|
|
|
|
% ! Undefined control sequence.
|
|
|
|
|
|
% l.191 \oucUseCochineal
|
|
|
|
|
|
% \AtBeginDocument 的内容排在导言区末尾才展开,那时 fonts.tex 已读入。
|
|
|
|
|
|
% ⚠️ 不要用 \providecommand 兜底:兜底会让 fonts.tex 缺席时静默跳过
|
|
|
|
|
|
% 换字体,比直接报错更难查。
|
|
|
|
|
|
\AtBeginDocument{\oucUseCochineal}
|
|
|
|
|
|
|
|
|
|
|
|
% 上游用 Source Sans Pro 的 Light / Semibold 两档,这里映射到 Cochineal
|
|
|
|
|
|
% 的常规/粗体,保持"正文常规、强调加粗"的层级不变。
|
|
|
|
|
|
% ⚠️ 要在 \AtBeginDocument 之后重新定义才指向新字体,故也放进
|
|
|
|
|
|
% \AtBeginDocument;直接用 \providecommand 会在换字体前就把 \tnr
|
|
|
|
|
|
% 的**旧值**(Termes)存进去,之后再改 \tnr 也传不过去。
|
|
|
|
|
|
\AtBeginDocument{%
|
|
|
|
|
|
\providecommand{\sourcesanslight}{\tnr}%
|
|
|
|
|
|
\providecommand{\sourcesanssemibold}{\tnrb}%
|
|
|
|
|
|
}
|
2026-10-27 11:17:24 +08:00
|
|
|
|
|
|
|
|
|
|
%New length definition
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 这两个长度原来写死 14.8cm / 2.5cm,加起来 17.3cm,看着小于版心宽
|
|
|
|
|
|
% 18cm(A4 21cm − 2×1.5cm 边距)。但 longtable 每列还有 \tabcolsep
|
|
|
|
|
|
% 各占左右一侧(默认 6pt),两列共 4 个 \tabcolsep = 24pt ≈ 0.85cm,
|
|
|
|
|
|
% 于是实际占宽 18.15cm → 溢出 4.48pt,报
|
|
|
|
|
|
% Overfull \hbox (4.48311pt too wide) in alignment at lines 20--70
|
|
|
|
|
|
% 这种"算着够、实际差一点"的溢出,换字号/字体后会时有时无,很难查。
|
|
|
|
|
|
%
|
2026-10-27 13:13:54 +08:00
|
|
|
|
% 改法:不让它猜,直接用版心宽减去左列与列间距。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️⚠️ 【必须在 \AtBeginDocument 里算,不能在 cls 的这里直接 \setlength】
|
|
|
|
|
|
%
|
|
|
|
|
|
% 根因:\RequirePackage[margin=1.5cm]{geometry} 只是**登记**参数,
|
|
|
|
|
|
% geometry 真正改写 \textwidth 是在导言区结束时(\begin{document}
|
|
|
|
|
|
% 的那一刻)。cls 里这条 \setlength 执行得比它早,读到的是 article
|
|
|
|
|
|
% 的默认 \textwidth = 345pt,于是算出
|
|
|
|
|
|
% 345 − 71.13(2.5cm) − 24(4×6pt) = 249.87pt
|
|
|
|
|
|
% 而真实版心宽 18cm = 512.15pt,本应是
|
|
|
|
|
|
% 512.15 − 71.13 − 24 = 417.02pt
|
|
|
|
|
|
% 两者差 167.15pt。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 后果不是报错,而是**整块内容右移**:longtable 默认把宽度小于版心
|
|
|
|
|
|
% 的表格居中排(\LTleft/\LTright 都是 \fill),表格总宽只剩 345pt,
|
|
|
|
|
|
% 于是在 512pt 的版心里左留白 (512.15−345)/2 ≈ 83.6pt。
|
|
|
|
|
|
% 表现就是「项目经验那一节缩进了一大截」——左边 2.5cm 的日期列被
|
|
|
|
|
|
% 推到 x≈145pt,而其他用 tabular 的章节(工作经历/教育经历/奖励)
|
|
|
|
|
|
% 还是 x≈48pt,两节对不齐。
|
|
|
|
|
|
% 日志里零 error、零 warning,只看日志发现不了。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 验证方式(改完看这个数对不对):
|
|
|
|
|
|
% \typeout{\the\rightcolumnlength} → 416.6pt 左右
|
|
|
|
|
|
% 若仍是 249.86pt 左右,说明又被别的地方提前算掉了。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 用 \textwidth 而不是 \linewidth:\linewidth 在列表/环境里会被
|
|
|
|
|
|
% 局部改写,而这张表永远按版心宽排。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 还要减掉 \arrayrulewidth(0.4pt):experiences 环境用的是
|
|
|
|
|
|
% {R{..}|E},中间那条竖线本身占 0.4pt 宽度。只减 4 个 \tabcolsep
|
|
|
|
|
|
% 的话,表格总宽 = 版心宽 + 0.4,日志里会多一条
|
|
|
|
|
|
% Overfull \hbox (0.4pt too wide) in alignment
|
|
|
|
|
|
% 数值小到肉眼看不出来,但属于「算得不准」,一并修掉。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 与西文字体联动:\rightcolumnlength 里没有西文字宽,所以换字体
|
|
|
|
|
|
% (Termes → Cochineal)不影响这个数的正确性;但右栏 p{} 的断行
|
|
|
|
|
|
% 会随字体变,换字体后必须复查一遍日志有没有新 Overfull。
|
2026-10-27 11:17:24 +08:00
|
|
|
|
\newlength{\rightcolumnlength}
|
|
|
|
|
|
\newlength{\leftcolumn}
|
|
|
|
|
|
\setlength{\leftcolumn}{2.5cm}
|
2026-10-27 13:13:54 +08:00
|
|
|
|
\AtBeginDocument{%
|
|
|
|
|
|
\setlength{\rightcolumnlength}{%
|
|
|
|
|
|
\dimexpr\textwidth-\leftcolumn-4\tabcolsep-\arrayrulewidth\relax}%
|
|
|
|
|
|
}
|
2026-10-27 11:17:24 +08:00
|
|
|
|
|
|
|
|
|
|
% Font Awesome icons aliases
|
|
|
|
|
|
\newcommand{\mailSymbol}{\faEnvelope}
|
|
|
|
|
|
\newcommand{\mailSymbolO}{\faEnvelopeO}
|
|
|
|
|
|
\newcommand{\locationSymbol}{\faMapMarker}
|
|
|
|
|
|
\newcommand{\infoSymbol}{\faInfo}
|
|
|
|
|
|
\newcommand{\homeSymbol}{\faLink}
|
|
|
|
|
|
\newcommand{\weiboSymbol}{\faWeibo}
|
|
|
|
|
|
\newcommand{\linkedinSymbol}{\faLinkedin}
|
|
|
|
|
|
\newcommand{\mobileSymbol}{\faMobilePhone}
|
|
|
|
|
|
\newcommand{\githubSymbol}{\faGithub}
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand\link[2]{\color{linkcolor}\href{#1}{#2}\color{Black} }
|
|
|
|
|
|
\newcommand\important[1]{\textbf #1}
|
|
|
|
|
|
|
|
|
|
|
|
% Create a tag
|
|
|
|
|
|
% Usage: \cvtag{<tag label>}
|
|
|
|
|
|
\newcommand{\cvtag}[1]{%
|
|
|
|
|
|
%\tikz[baseline]\node[anchor=base,draw=darkGrey!70,rounded corners=0.5ex,inner xsep=1ex,inner ysep =0.55ex,text height=1.3ex,text depth=.25ex]{#1};
|
|
|
|
|
|
\begin{tikzpicture}
|
|
|
|
|
|
\node[anchor=base,draw=darkGrey!70,rounded corners=0.5ex,inner xsep=1ex,inner ysep =0.4ex,text height=2ex,text depth=.25ex]{#1};
|
|
|
|
|
|
\end{tikzpicture}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Create a chinese tag
|
|
|
|
|
|
% Usage: \cvtag{<tag label>}
|
|
|
|
|
|
\newcommand{\cvtagcn}[1]{%
|
|
|
|
|
|
%\tikz[baseline]\node[anchor=base,draw=darkGrey!70,rounded corners=0.5ex,inner xsep=1ex,inner ysep =0.55ex,text height=1.3ex,text depth=.25ex]{#1};
|
|
|
|
|
|
\begin{tikzpicture}
|
|
|
|
|
|
\node[anchor=base,draw=darkGrey!70,rounded corners=0.5ex,inner xsep=1ex,inner ysep =0.4ex,text height=2ex,text depth=.25ex]{#1};
|
|
|
|
|
|
\end{tikzpicture}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's name
|
|
|
|
|
|
% Usage: \user{<firstanme>}{<lastname>}
|
|
|
|
|
|
\newcommand\user[2]{\color{accentcolor}{\LARGE #1 \textbf{#2}}\color{Black}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render a text with its symbol
|
|
|
|
|
|
% Usage; \socialtext{<icon>}{<label>}
|
|
|
|
|
|
\newcommand{\socialtext}[2]{\mbox{\textcolor{symbolcolor}{#1}\hspace{0.5em}#2\hspace{1em}}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render a link with its symbol
|
|
|
|
|
|
% Usage; \sociallink{<icon>}{<label>}
|
|
|
|
|
|
%\newcommand{\sociallink}[3]{\mbox{\textcolor{symbolcolor}{#1}\hspace{0.5em}#2\hspace{1em}}}
|
|
|
|
|
|
\newcommand{\sociallink}[3]{\mbox{\textcolor{symbolcolor}{#1}\hspace{0.5em}\link{#2}{#3}\hspace{1em}}}
|
|
|
|
|
|
|
|
|
|
|
|
% Define author's name
|
|
|
|
|
|
% Usage: \name{<firstname>}{<lastname>}
|
|
|
|
|
|
% Usage: \firstname{<firstname>}
|
|
|
|
|
|
% Usage: \lastname{<lastname>}
|
|
|
|
|
|
% Usage: \familyname{<familyname>}
|
|
|
|
|
|
\newcommand*{\name}[2]{\def\@firstname{#1}\def\@lastname{#2}}
|
|
|
|
|
|
\newcommand*{\firstname}[1]{\def\@firstname{#1}}
|
|
|
|
|
|
\newcommand*{\lastname}[1]{\def\@lastname{#1}}
|
|
|
|
|
|
\newcommand*{\familyname}[1]{\def\@lastname{#1}}
|
|
|
|
|
|
\def\@familyname{\@lastname}
|
|
|
|
|
|
|
|
|
|
|
|
% Define author's tagline
|
|
|
|
|
|
% Usage: \tagline{<tag line>}
|
|
|
|
|
|
\newcommand*{\tagline}[1]{\def\@tagline{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Define author's photo
|
|
|
|
|
|
% Usage \photo{<diameter>}{<photo>}
|
|
|
|
|
|
\newcommand{\photo}[2]{\def\@photo{#2}\def\@photodiameter{#1}}
|
|
|
|
|
|
|
2026-10-27 14:25:27 +08:00
|
|
|
|
%----------------------------------------------------------------------
|
|
|
|
|
|
% 校徽(可选,默认不印)
|
|
|
|
|
|
%
|
|
|
|
|
|
% 用法(导言区,\begin{document} 之前):
|
|
|
|
|
|
% \cvlogo{28mm} % 用仓库里带的横式彩色校徽
|
|
|
|
|
|
% \cvlogo{28mm}[ouc_logo_彩色] % 换成圆形校徽
|
|
|
|
|
|
% \cvlogo{28mm}[ouc_横式_海大红] % 换配色
|
|
|
|
|
|
% 不调用就完全不出现,版面与调用前逐字节一致。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 本目录 logos/ 下**只放实际用到的那一个**(横式彩色,377KB)。
|
|
|
|
|
|
% 想换圆形或别的配色,从 ../科技报告/logos/ 复制过来即可,
|
|
|
|
|
|
% 那边有全部官方 VI 素材:
|
|
|
|
|
|
% ouc_logo_{彩色,海大红,海大蓝,天蓝,专金,墨黑}.png 圆形 1200×1200
|
|
|
|
|
|
% ouc_横式_{彩色,海大红,海大蓝,黑}.png 横式 2400×640
|
|
|
|
|
|
% (不预先全放进来,是因为每个 300~380KB,用不到就是纯占体积。)
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 导言区只**登记**参数,真正画图是在 \makecvheader 开头做的
|
|
|
|
|
|
% (见下面 \@makecvlogo)。原因:导言区不能产生任何内容,
|
|
|
|
|
|
% 直接在导言区画 tikzpicture 会报
|
|
|
|
|
|
% ! LaTeX Error: Missing \begin{document}.
|
|
|
|
|
|
%
|
|
|
|
|
|
% 定位:距纸左 10mm、距纸顶 6mm(相对【纸边】,不随页边距变)。
|
|
|
|
|
|
% 两个数值分别由 \cvlogox / \cvlogoy 控制,想在导言区微调就重设:
|
|
|
|
|
|
% \setlength{\cvlogox}{12mm}
|
|
|
|
|
|
% \setlength{\cvlogoy}{8mm}
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 为什么距顶是 6mm 而不是科技报告的 20mm:
|
|
|
|
|
|
% 简历页边距只有 15mm(科技报告是 27mm),抬头第一行「姓名」的墨迹顶
|
|
|
|
|
|
% 就在 48.8pt = 17.2mm。28mm 宽的横式 logo 高 7.06mm,若距顶 20mm
|
|
|
|
|
|
% 会直接压到姓名上,距顶 8mm 也只剩 6pt 间隙(2mm,视觉上贴着)。
|
2026-11-01 09:29:00 +08:00
|
|
|
|
% 实际6mm 时 logo 下沿在 13.1mm,仍在 15mm 版心边距以内,
|
2026-10-27 14:25:27 +08:00
|
|
|
|
% 距姓名顶有 11.6pt(4.1mm),是这块空间里最平衡的位置。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 距纸左 10mm 已接近 A4 打印的裁切余量(一般 10~12mm),
|
|
|
|
|
|
% 不要再改小。同理距顶 6mm 也偏小 —— **屏幕阅读和普通办公打印没问题**
|
|
|
|
|
|
% (A4 纸本身不裁切),但若要专业印刷/装订,建议把 \cvlogoy 改成 8mm
|
|
|
|
|
|
% 以上,并接受 logo 与姓名靠得近一点。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️⚠️ 为什么后面跟着 \vspace*{-17pt}:
|
|
|
|
|
|
% tikzpicture 即使全部内容都是 overlay,它本身仍是一个**占一行的盒子**,
|
2026-11-01 09:29:00 +08:00
|
|
|
|
% 插在 \makecvheader 前面会把姓名整体往下推 17pt(实际48.8 → 65.8)。
|
2026-10-27 14:25:27 +08:00
|
|
|
|
% \smash、\hbox to 0pt、\vbox to 0pt 三种写法都消不掉这一行
|
|
|
|
|
|
% (因为要断行就必须有 \par,有 \par 就有行高)。
|
2026-11-01 09:29:00 +08:00
|
|
|
|
% 直接用等量的负 \vspace 抵消,姓名回到 48.8pt,误差 0.0。
|
|
|
|
|
|
% ⚠️ 这个 17pt 与 logo 尺寸无关(18~30mm 五档实际姓名都是 48.8),
|
2026-10-27 14:25:27 +08:00
|
|
|
|
% 它是一行正文的高度。但若改了 \parskip 或正文字号,要重新量。
|
|
|
|
|
|
%----------------------------------------------------------------------
|
|
|
|
|
|
\newlength{\cvlogox}
|
|
|
|
|
|
\newlength{\cvlogoy}
|
|
|
|
|
|
\setlength{\cvlogox}{10mm}
|
|
|
|
|
|
\setlength{\cvlogoy}{6mm}
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand{\cvlogo}[2][ouc_横式_彩色]{%
|
|
|
|
|
|
\def\@cvlogowidth{#2}%
|
|
|
|
|
|
\def\@cvlogofile{#1}%
|
|
|
|
|
|
}
|
|
|
|
|
|
% 内部命令:真正画 logo。未调用 \cvlogo 时为空操作。
|
|
|
|
|
|
\newcommand{\@makecvlogo}{%
|
|
|
|
|
|
\ifdefined\@cvlogofile
|
|
|
|
|
|
\begin{tikzpicture}[remember picture, overlay]
|
|
|
|
|
|
\node[anchor=north west, inner sep=0pt,
|
|
|
|
|
|
xshift=\cvlogox, yshift=-\cvlogoy]
|
|
|
|
|
|
at (current page.north west)
|
|
|
|
|
|
{\includegraphics[width=\@cvlogowidth]{logos/\@cvlogofile.png}};
|
|
|
|
|
|
\end{tikzpicture}%
|
|
|
|
|
|
\par\vspace*{-17pt}%
|
|
|
|
|
|
\fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-27 11:17:24 +08:00
|
|
|
|
% Render author's address
|
|
|
|
|
|
% Usage: \address{<address>}
|
|
|
|
|
|
\newcommand*{\address}[1]{\socialtext{\locationSymbol}{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's infos
|
|
|
|
|
|
% Usage: \infos{<infos>}
|
|
|
|
|
|
\newcommand*{\infos}[1]{\socialtext{\infoSymbol}{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's homepage
|
|
|
|
|
|
% Usage: \homepage{<homepage>}
|
|
|
|
|
|
\newcommand*{\homepage}[1]{\sociallink{\homeSymbol}{http://#1}{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's homepage
|
|
|
|
|
|
% Usage: \weibo{<weibo>}
|
|
|
|
|
|
\newcommand*{\weibo}[1]{\sociallink{\weiboSymbol}{http://www.weibo.com/#1}{weibo.com/#1}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's linked-in (optional)
|
|
|
|
|
|
% Usage: \linkedin{<linked-in-nick>}
|
|
|
|
|
|
\newcommand*{\linkedin}[1]{\sociallink{\linkedinSymbol}{http://www.linkedin.com/in/#1}{linkedin.com/in/#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's viadeo(optional)
|
|
|
|
|
|
% Usage: \viadeo{<viadeo-nick>}
|
|
|
|
|
|
\newcommand*{\viadeo}[1]{\sociallink{\viadeoSymbol}{http://www.viadeo.com/fr/profile/#1}{viadeo.com/fr/profile/#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's github (optional)
|
|
|
|
|
|
% Usage: \github{<github-nick>}
|
|
|
|
|
|
\newcommand*{\github}[1]{\sociallink{\githubSymbol}{https://www.github.com/#1}{github.com/#1}} % Github icon + URL
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's email (optional)
|
|
|
|
|
|
% Usage: \email{<email adress>}
|
|
|
|
|
|
\newcommand*{\email}[1]{\sociallink{\mailSymbol}{mailto:#1}{#1}}
|
|
|
|
|
|
\newcommand*{\emailO}[1]{\sociallink{\mailSymbolO}{mailto:#1}{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's mobile phone (optional)
|
|
|
|
|
|
% Usage: \smartphone{<mobile phone number>}
|
|
|
|
|
|
\newcommand*\smartphone[1]{\socialtext{\mobileSymbol}{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
% Render author's tagline
|
|
|
|
|
|
\newcommand\resumetitle[1]{
|
|
|
|
|
|
\ifundef{\@
|
|
|
|
|
|
}{
|
|
|
|
|
|
\par{
|
|
|
|
|
|
\bigskip\center{\Large \color{accentcolor}\textsc{#1}\color{Black}}\par
|
|
|
|
|
|
}
|
|
|
|
|
|
\bigskip
|
|
|
|
|
|
}{
|
|
|
|
|
|
% \color{accentcolor}\textsc{\large{#1}}\color{black}
|
|
|
|
|
|
\par{
|
|
|
|
|
|
\bigskip\center{\Large \color{accentcolor}\textsc{#1}\color{Black}}\par
|
|
|
|
|
|
}
|
|
|
|
|
|
\bigskip
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Define social entries to print in header
|
|
|
|
|
|
\newcommand{\socialinfo}[1]{\def\@socialinfo{#1}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
% Render CV header
|
|
|
|
|
|
% Needs \@firstname, \@lastname and \@tagline to be defined
|
|
|
|
|
|
\newcommand*{\makecvheader}{
|
2026-10-27 14:25:27 +08:00
|
|
|
|
\@makecvlogo% 校徽(未调用 \cvlogo 时为空操作,不占位)
|
2026-10-27 11:17:24 +08:00
|
|
|
|
\ifundef{\@alternative}{
|
|
|
|
|
|
|
|
|
|
|
|
\ifundef{\@photodiameter}{
|
|
|
|
|
|
\begin{minipage}{\linewidth}
|
|
|
|
|
|
}{
|
|
|
|
|
|
\begin{minipage}{\dimexpr\linewidth-\@photodiameter-2em}
|
|
|
|
|
|
}
|
|
|
|
|
|
% ⚠️ 原文是 \vspace*{0.3cm}\\ —— \vspace 后面紧跟 \\ 会在
|
|
|
|
|
|
% 换行前多出一个**空的 hbox**,日志每条都刷
|
|
|
|
|
|
% Underfull \hbox (badness 10000) in paragraph at lines 75--75
|
|
|
|
|
|
% 改用 \\[0.3cm](换行并附垂直间距,LaTeX 标准写法),
|
|
|
|
|
|
% 间距效果完全一样,但不产生空盒。下面的 \smallskip\\
|
|
|
|
|
|
% 同理改成 \\[\smallskipamount]。
|
|
|
|
|
|
\color{accentcolor}\user{\@firstname}{\@lastname}\color{black}\\[0.3cm]
|
|
|
|
|
|
\small{\@socialinfo}
|
|
|
|
|
|
\end{minipage}
|
|
|
|
|
|
\ifdef{\@photodiameter}{
|
|
|
|
|
|
\begin{minipage}{\@photodiameter}
|
|
|
|
|
|
\begin{tikzpicture}%
|
|
|
|
|
|
\node[circle, text=white, minimum size=2.5cm,
|
|
|
|
|
|
path picture={\node at (path picture bounding box.center){
|
|
|
|
|
|
\includegraphics[width=2.5cm]{\@photo}
|
|
|
|
|
|
};
|
|
|
|
|
|
}]{ };
|
|
|
|
|
|
\end{tikzpicture}
|
|
|
|
|
|
\end{minipage}
|
|
|
|
|
|
}{}
|
|
|
|
|
|
\resumetitle{\@tagline}
|
|
|
|
|
|
}{
|
|
|
|
|
|
\ifundef{\@photodiameter}{
|
|
|
|
|
|
\begin{minipage}{\linewidth}
|
|
|
|
|
|
}{
|
|
|
|
|
|
\begin{minipage} {\dimexpr\linewidth-\@photodiameter-2em}
|
|
|
|
|
|
}
|
|
|
|
|
|
\user{\@firstname}{\@lastname}\\[0.3cm]
|
|
|
|
|
|
\resumetitle{\@tagline}
|
|
|
|
|
|
\\[\smallskipamount]
|
|
|
|
|
|
\small{\@socialinfo}
|
|
|
|
|
|
\end{minipage}
|
|
|
|
|
|
\ifdef{\@photodiameter}{
|
|
|
|
|
|
\begin{minipage}{\@photodiameter}
|
|
|
|
|
|
\begin{tikzpicture}%
|
|
|
|
|
|
\node[circle, text=white, minimum size=2.5cm,
|
|
|
|
|
|
path picture={\node at (path picture bounding box.center){
|
|
|
|
|
|
\includegraphics[width=2.5cm]{\@photo}
|
|
|
|
|
|
};
|
|
|
|
|
|
}]{ };
|
|
|
|
|
|
\end{tikzpicture}
|
|
|
|
|
|
\end{minipage}
|
|
|
|
|
|
% \begin{minipage}{\@photodiameter}
|
|
|
|
|
|
% \tikz\path[fill overzoom image={\@photo}]circle[radius=0.5\linewidth];
|
|
|
|
|
|
% \end{minipage}
|
|
|
|
|
|
|
|
|
|
|
|
}{}
|
|
|
|
|
|
\bigskip
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Resume part title definition
|
|
|
|
|
|
\newcommand\sectionTitle[2]{\section{\texorpdfstring{\color{accentcolor}#2\enspace \textbf{#1}}{#1}}}
|
|
|
|
|
|
|
|
|
|
|
|
% Define a new column type for the scholarship environment
|
|
|
|
|
|
\newcolumntype{Y}{>{\raggedleft}p{\leftcolumn}}
|
|
|
|
|
|
|
|
|
|
|
|
% Define the 'scholarship' environment
|
|
|
|
|
|
\newenvironment{scholarship}{%
|
|
|
|
|
|
\begin{tabular}{Y p{\rightcolumnlength}}
|
|
|
|
|
|
}{%
|
|
|
|
|
|
\end{tabular}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Render a scholarshipentry in the scolarship environment
|
|
|
|
|
|
% Usage: \scholarshipentry{<date>}{<description>}
|
|
|
|
|
|
\newcommand\scholarshipentry[2]{
|
|
|
|
|
|
#1 & #2 \\
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Define the 'skills' environment
|
|
|
|
|
|
\newenvironment{skills}{%
|
|
|
|
|
|
\begin{longtable}{R{\leftcolumn}p{\rightcolumnlength}}
|
|
|
|
|
|
}{%
|
|
|
|
|
|
\end{longtable}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Render a skill in the skills environment
|
|
|
|
|
|
% Usage: \skill{<skill>}{<level>}
|
|
|
|
|
|
\newcommand\skill[2]{
|
|
|
|
|
|
\textsc{#1} & \foreach \x in {1,...,5}{{\color{accentcolor!80} \ifnumgreater{\x}{#2}{\faCircleO}{\faCircle}}\enspace }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\newcolumntype{E}{>{\raggedright\arraybackslash}p{\rightcolumnlength}}
|
|
|
|
|
|
|
|
|
|
|
|
% Define the 'experiences' environment
|
|
|
|
|
|
\newenvironment{experiences}{%
|
|
|
|
|
|
\begin{longtable}{R{\leftcolumn}|E}
|
|
|
|
|
|
}{%
|
|
|
|
|
|
\end{longtable}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
% Render an experience in the experiences environment
|
|
|
|
|
|
% Usage:
|
|
|
|
|
|
% \tags {<Technology list>}
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand\tags[1]{
|
|
|
|
|
|
\foreach \n in {#1}{\cvtagcn{\n}}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
% Render an experience in the experiences environment
|
|
|
|
|
|
% Usage:
|
|
|
|
|
|
% \experience
|
|
|
|
|
|
% {<End date>} {<Title>}{<Enterprise>}{<Country>}
|
|
|
|
|
|
% {<Start date} {
|
|
|
|
|
|
% <Experience description (Could be a list)>
|
|
|
|
|
|
% }
|
|
|
|
|
|
% {<Technology list>}
|
|
|
|
|
|
\newcommand\experience[7]{
|
|
|
|
|
|
\textsc{#1} & \textsc{#2, #3, #4} \\*
|
|
|
|
|
|
\textsc{#5} & \begin{minipage}[t]{\rightcolumnlength}
|
|
|
|
|
|
#6
|
|
|
|
|
|
\end{minipage} \\*
|
|
|
|
|
|
& \footnotesize{\foreach \n in {#7}{\cvtag{\n}}} \\
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% Render a consultant experience in the experiences environment
|
|
|
|
|
|
% Usage:
|
|
|
|
|
|
% \consultantexperience
|
|
|
|
|
|
% {<End date>} {<Consultant title>}{<Consulting Enterprise>}{<Country>}
|
|
|
|
|
|
% {<Start date} {<Client title>}{<Client business unit>}
|
|
|
|
|
|
% {
|
|
|
|
|
|
% <Experience description (Could be a list)>
|
|
|
|
|
|
% }
|
|
|
|
|
|
% {<Technology list>}
|
|
|
|
|
|
\newcommand\consultantexperience[9]{
|
|
|
|
|
|
\textsc{#1} & \textsc{#2, #3, #4} \\*
|
|
|
|
|
|
\textsc{#5} & \emph{#6} pour #7 \\*
|
|
|
|
|
|
& \begin{minipage}[t]{\rightcolumnlength}
|
|
|
|
|
|
#8
|
|
|
|
|
|
\end{minipage} \\*
|
|
|
|
|
|
& \footnotesize{\foreach \n in {#9}{\cvtag{\n}}} \\
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand\emptySeparator{\multicolumn{2}{c}{}\\}
|
2026-10-27 14:56:34 +08:00
|
|
|
|
|
|
|
|
|
|
%======================================================================
|
|
|
|
|
|
% 成果统计:让概述里的数字自动来自后面章节的条目
|
|
|
|
|
|
%
|
|
|
|
|
|
% 问题:简历第一段概述通常写「发表论文 40 余篇、授权专利 12 项、成果转化
|
|
|
|
|
|
% 3 项……」。这些数字若手写,每增删一条论文就得回头改概述,极易漏改。
|
|
|
|
|
|
%
|
2026-10-27 15:04:48 +08:00
|
|
|
|
% 思路:正文里计数,概述用 \cvnum 取数。**列几条就算几条**,不去猜总数——
|
|
|
|
|
|
% 你不列出来的成果本来也不该出现在概述里。
|
2026-10-27 14:56:34 +08:00
|
|
|
|
%
|
2026-10-27 15:04:48 +08:00
|
|
|
|
% 两种写法,按「一条算几类」选:
|
2026-10-27 14:56:34 +08:00
|
|
|
|
%
|
2026-10-27 15:04:48 +08:00
|
|
|
|
% 【全自动】cvlist 环境 —— 一条 = 一个成果时用,**条目里什么都不用写**
|
|
|
|
|
|
% \begin{cvlist}{软著}
|
|
|
|
|
|
% \item 某某系统...登记号...
|
|
|
|
|
|
% \item 另一个系统...
|
|
|
|
|
|
% \end{cvlist}
|
|
|
|
|
|
% 每多一个 \item 自动 +1。增删条目完全不用管标记。
|
|
|
|
|
|
% 目前用于:软著(section_06)、成果转化(section_08)、教研(section_09)。
|
2026-10-27 14:56:34 +08:00
|
|
|
|
%
|
2026-10-27 15:04:48 +08:00
|
|
|
|
% 【半自动】逐条标记 —— 一条要算进多个类别时用
|
|
|
|
|
|
% \cvmark{类别} 只计数,不显示(专利、科研项目用)
|
|
|
|
|
|
% \cvtagcount{类别} 显示加粗文字 + 计数(论文的 SCI/EI/核心用)
|
|
|
|
|
|
% 专利一条要同时算「专利」和「第一发明人」,项目要同时算
|
|
|
|
|
|
% 「科研项目」和「主持/负责」,cvlist 一次只能管一类,故用标记。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 【概述取数】两种写法统一:
|
|
|
|
|
|
% \cvnum{类别} 单类
|
|
|
|
|
|
% \cvnum*{A,B} 多类求和(英文逗号)
|
|
|
|
|
|
% 空类别返回 0,不会出现 ??,所以可以先写 \cvnum{EI} 再加标记。
|
|
|
|
|
|
% 类别名随用随建,不需要预先注册。
|
2026-10-27 14:56:34 +08:00
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 为什么用独立数据文件而不是 LaTeX 的 aux:
|
2026-11-01 09:29:00 +08:00
|
|
|
|
% 实际中文键经 aux 往返后 \ifcsname 全部匹配不上(xeCJK 把汉字设为
|
2026-10-27 14:56:34 +08:00
|
|
|
|
% 活动字符,键的 token 形态与写入时不一致;ASCII 键正常,中文键失效)。
|
|
|
|
|
|
% 故改用独立文件 \jobname.cvnum,导言区末尾 \input,键原样保留。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 必须编译两遍(或直接用 latexmk):
|
|
|
|
|
|
% 第一遍边累加边写 \jobname.cvnum,此时概述读到的是**上一遍**的值,
|
|
|
|
|
|
% 首次编译会显示 0;第二遍才是正确数字。日志末尾有 CVSTATS 一行提示。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ \jobname.cvnum 是**生成文件**,不要手改、不要提交 git(已在
|
|
|
|
|
|
% .gitignore 里挡住)。删掉它只会让数字从 0 重新算一遍,下一遍即恢复。
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 类别名限制:
|
|
|
|
|
|
% · 不要含英文逗号(, 是 \cvnum* 的分隔符)
|
|
|
|
|
|
% · 不要含 @ % # \ { } 这些特殊字符
|
|
|
|
|
|
% · 中文、英文、汉字混排都可以
|
|
|
|
|
|
%======================================================================
|
|
|
|
|
|
\makeatletter
|
|
|
|
|
|
|
|
|
|
|
|
% ---- 数据文件 ------------------------------------------------------
|
|
|
|
|
|
\newwrite\cv@statsout
|
|
|
|
|
|
|
|
|
|
|
|
% 读:导言区末尾把上一遍写入的数字读进来。
|
|
|
|
|
|
% 此时正文尚未开始,不会和本遍的累加互相干扰。
|
|
|
|
|
|
\AtBeginDocument{\InputIfFileExists{\jobname.cvnum}{}{}}
|
|
|
|
|
|
|
|
|
|
|
|
% ---- 内部:类别 -> 计数器名 ----------------------------------------
|
|
|
|
|
|
% 累加值存在 \cvacc@<类别>(TeX 整数寄存器,不用 LaTeX counter,
|
|
|
|
|
|
% 既省事又避开 \the\csname...\endcsname 的展开陷阱)。
|
|
|
|
|
|
% 显示值存在 \cvnum@<类别>(\def 出来的宏,内容就是数字字符串)。
|
|
|
|
|
|
\newcommand\cv@accname[1]{cvacc@#1}
|
|
|
|
|
|
|
|
|
|
|
|
% 保证某类别的累加器存在
|
|
|
|
|
|
\newcommand\cv@ensureacc[1]{%
|
|
|
|
|
|
\@ifundefined{\cv@accname{#1}}%
|
|
|
|
|
|
{\expandafter\newcount\csname\cv@accname{#1}\endcsname}%
|
|
|
|
|
|
{}%
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% ---- 标记 ----------------------------------------------------------
|
|
|
|
|
|
% \cvmark{<类别>}:把该类别的累加器 +1,无可见输出。
|
|
|
|
|
|
\newcommand\cvmark[1]{%
|
|
|
|
|
|
\cv@ensureacc{#1}%
|
|
|
|
|
|
\global\advance\csname\cv@accname{#1}\endcsname\@ne
|
|
|
|
|
|
% 顺便登记该类别的名字,收尾时按登记顺序写文件
|
|
|
|
|
|
\@ifundefined{cv@seen@\detokenize{#1}}%
|
|
|
|
|
|
{\expandafter\gdef\csname cv@seen@\detokenize{#1}\endcsname{1}%
|
|
|
|
|
|
\g@addto@macro\cv@taglist{\cv@writeone{#1}}}%
|
|
|
|
|
|
{}%
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-27 15:04:48 +08:00
|
|
|
|
% ---- 自动计数列表环境:cvlist --------------------------------------
|
|
|
|
|
|
% \begin{cvlist}{<类别>} ... \end{cvlist}
|
|
|
|
|
|
%
|
|
|
|
|
|
% 进入环境后,**每个 \item 自动 +1**,不需要在条目里写 \cvmark。
|
|
|
|
|
|
% 这是最省事也最不容易漏的方式:增删条目完全不用管标记。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 适用于「一条就是一个成果、章节条目数就是总数」的章节:
|
|
|
|
|
|
% 软件著作权、成果转化、教研项目、专利(见下)、奖励……
|
|
|
|
|
|
% 不适用于「一条里含多个类别」的场景(比如论文一条要同时算 SCI 和总篇数),
|
|
|
|
|
|
% 那种仍用 \cvtagcount / \cvmark 逐条标。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 用法:
|
|
|
|
|
|
% \begin{cvlist}{软著}
|
|
|
|
|
|
% \item 某系统...登记号...
|
|
|
|
|
|
% \item 另一个系统...
|
|
|
|
|
|
% \end{cvlist}
|
|
|
|
|
|
% 概述里写 \cvnum{软著} → 2
|
|
|
|
|
|
%
|
|
|
|
|
|
% ⚠️ 环境内部就是普通 itemize,版式完全不变(\begin{itemize} 包在里面)。
|
|
|
|
|
|
% ⚠️ 不能在 cvlist 里再嵌套 itemize 写子项——子项的 \item 也会被算进去。
|
|
|
|
|
|
% 需要子项就用普通 itemize + 手写 \cvmark。
|
|
|
|
|
|
\newenvironment{cvlist}[1]{%
|
|
|
|
|
|
\cvlistcat{#1}%
|
|
|
|
|
|
\begin{itemize}%
|
|
|
|
|
|
}{%
|
|
|
|
|
|
\end{itemize}%
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% 记录当前 cvlist 的类别;\item 被重定义成「先计数再走原 \item」
|
|
|
|
|
|
% ⚠️ \cvmark 内部用 \detokenize 处理类别名,所以必须先把 \cv@listcat
|
|
|
|
|
|
% **展开成实际文字**再传进去;否则写进 .cvnum 的是字面串 "\cv@listcat"。
|
|
|
|
|
|
\newcommand\cvlistcat[1]{%
|
|
|
|
|
|
\def\cv@listcat{#1}%
|
|
|
|
|
|
\let\cv@origitem\item
|
|
|
|
|
|
\renewcommand\item{\expandafter\cvmark\expandafter{\cv@listcat}\cv@origitem}%
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-27 14:56:34 +08:00
|
|
|
|
% ---- 输出 ----------------------------------------------------------
|
|
|
|
|
|
% \cvnum{SCI} 单类取数
|
|
|
|
|
|
% \cvnum*{SCI,EI} 多类求和
|
|
|
|
|
|
\newcommand\cvnum{\@ifstar\cv@numsum\cv@numone}
|
|
|
|
|
|
|
|
|
|
|
|
% ---- 带计数的标签:显示 + 计数一步完成 ------------------------------
|
|
|
|
|
|
% \cvtagcount{<显示文字>}[<类别>]
|
|
|
|
|
|
% 显示「显示文字」(与正文同号加粗,和原来的 \textbf{SCI} 完全一样),
|
|
|
|
|
|
% 同时给类别 +1。省略类别时用显示文字本身当类别。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 为什么需要它:论文的收录类型本来就写成 \textbf{SCI} 显示在条目末尾,
|
|
|
|
|
|
% 若再单独写一个 \cvmark{SCI},一是啰嗦,二是迟早会漏标。
|
|
|
|
|
|
% 用 \cvtagcount{SCI} 一次到位,显示与计数永远同步。
|
|
|
|
|
|
%
|
|
|
|
|
|
% 用法:
|
|
|
|
|
|
% \cvtagcount{SCI} % 显示 SCI,类别也叫 SCI
|
|
|
|
|
|
% \cvtagcount{核心}[中文核心] % 显示「核心」,类别记为「中文核心」
|
|
|
|
|
|
\newcommand\cvtagcount[2][\relax]{%
|
|
|
|
|
|
\textbf{#2}%
|
|
|
|
|
|
\ifx\relax#1\relax\cvmark{#2}\else\cvmark{#1}\fi}
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand\cv@numone[1]{%
|
|
|
|
|
|
\@ifundefined{cvnum@#1}{0}{\csname cvnum@#1\endcsname}}
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand\cv@numsum[1]{%
|
|
|
|
|
|
\begingroup
|
|
|
|
|
|
\count@\z@
|
|
|
|
|
|
\@for\cv@k:=#1\do{%
|
|
|
|
|
|
\@ifundefined{cvnum@\cv@k}{}{\advance\count@\csname cvnum@\cv@k\endcsname\relax}%
|
|
|
|
|
|
}%
|
|
|
|
|
|
\the\count@
|
|
|
|
|
|
\endgroup}
|
|
|
|
|
|
|
|
|
|
|
|
% ---- 收尾:写数据文件 ----------------------------------------------
|
|
|
|
|
|
% 用独立的 write 流,与 aux 完全无关,因此不受 aux 读入时机影响。
|
|
|
|
|
|
\newcommand\cv@taglist{}
|
|
|
|
|
|
|
|
|
|
|
|
\newcommand\cv@writeone[1]{%
|
|
|
|
|
|
\immediate\write\cv@statsout{%
|
|
|
|
|
|
\string\cvSetNum{\detokenize{#1}}{\the\csname\cv@accname{#1}\endcsname}}%
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
\AtEndDocument{%
|
|
|
|
|
|
\immediate\openout\cv@statsout=\jobname.cvnum\relax
|
|
|
|
|
|
\cv@taglist
|
|
|
|
|
|
\immediate\closeout\cv@statsout
|
|
|
|
|
|
% 日志提示:本遍写入了多少类
|
|
|
|
|
|
\typeout{CVSTATS: 已写入 \jobname.cvnum(若概述数字为 0,请再编译一遍)}%
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
% 数据文件里调用的设置命令。
|
|
|
|
|
|
% ⚠️ 不能含 @:读回时若 @ 不是字母,命令名会被拆断。
|
|
|
|
|
|
\newcommand\cvSetNum[2]{%
|
|
|
|
|
|
\expandafter\def\csname cvnum@#1\endcsname{#2}}
|
|
|
|
|
|
|
|
|
|
|
|
\makeatother
|