小手机使用手册

AI 只写「名字:内容」这样的纯文字,正则负责把它变成右边这样的手机画面。支持文字、语音、表情包、图片、转账、通话、分享链接、转发记录、引用、撤回、发送失败。同一个外框还能显示朋友圈。

全程只需要复制粘贴,不用懂代码。

有什么想要的功能或者样式、颜色、主题、风格,欢迎提出!

可以直接留下评论~

23:14
char
对方正在输入…
昨天 23:14
c
char
睡了吗?楼下那家馄饨店还开着。
还没,你又加班到现在?
我
c
char
12″
刚下班,路过的时候看见灯还亮着。
c
char
¥18.00
馄饨钱,不许退
转账
¥18.00
已收款
转账
我
“char”拍了拍你
c
char
嗯,今天值了。
我:还没,你又加班到现在?
“char”撤回了一条消息
已撤回其实我在楼下等了半小时。
对方未接听
我
你到底什么意思?
我
消息已发出,但被对方拒收了。
发送时输入【表情+序号】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

需要你做的

  1. 全局 CSS:小手机 1 段 + 朋友圈 1 段粘贴到 美化&正则 → 全局 CSS 的最后面,先小手机,后朋友圈。决定手机的样式,也存着表情包、角色头像和朋友圈背景。
  2. 正则:小手机 28 条 + 朋友圈 11 条粘贴到 美化&正则 → 正则,朋友圈的整块接在小手机后面。负责把文字变成手机。
  3. 输出设定:1 段粘贴到 时刻设定。前半是小手机,后半是朋友圈,告诉 AI 该怎么写。
  4. 在这里改背景/角色头像每张卡的角色都不一样,贴完 CSS 后要在里面换成你卡里角色的头像,聊天背景、颜色、表情包也在这里改。
  5. 玩家头像(可选)玩家自己写在 用户设定 里,想换头像的玩家才需要。

朋友圈

用的是小手机同一个外框。AI 写 <zzpm>,里面每条朋友圈用 <pyq> 包起来,正则就会排成右边这样:顶上是背景图、主人的名字和头像,下面每条有头像、文案、配图、位置、时间、点赞和评论。

朋友圈主人是谁,背景和右下角的头像就是谁:玩家刷自己的朋友圈时是玩家,翻看 char 的朋友圈时就是 char。

配图和小手机一样写【图片:画面描述】,有链接时写【图片:链接】。一张图时自动放大,4 张图排成两行两列。

朋友圈是可选的。不需要的话,下面各步里标着「朋友圈」的部分都可以不要。

23:40
朋友圈
char
c
不常更新,有事打电话。
c
char
加班到现在,楼下那家馄饨店居然还亮着灯。
一碗冒着热气的馄饨,旁边放着两只塑料勺
凌晨的街口,只有一家店亮着灯
便利店门口的猫,蹲在纸箱上不肯走
上海·静安区
18分钟前
周叙:又加班?
char回复周叙:习惯了
林夏:下次带我一份,加辣
c
char
周末回了一趟老家。
院子里的柿子树,挂满了橙色的果子
3天前
c
char
新的一年,少喝咖啡。
1月1日

第 1 步 全局 CSS

默认使用通用版,直接复制下方 CSS 就可以。想选其他风格,点预览到文末复制对应样式,再回到第 2 步继续。

通用版 CSS默认样式

打开 美化&正则 → 全局 CSS,把下面整段复制,粘贴到原有内容的最后面。

以后更新时:把上一次贴的那一整段删掉,再粘贴新的一整段。不要只改其中几行,容易漏。表情包和头像的设置也在这段里,更新前先把你自己加过的那几行复制出来。
/* ===== 小手机 通用版 ===== 贴在全局 CSS 最后面 */
/* 色板:小手机 */
.zzph {
  --zzph-frame: #1c1c1e;
  --zzph-bg: #f2f2f5;
  --zzph-bar: #f8f8fa;
  --zzph-text: #1f1f24;
  --zzph-sub: #8a8a93;
  --zzph-line: #e2e2e8;
  --zzph-other: #ffffff;
  --zzph-me: #cfe4fa;
  --zzph-me-text: #16324f;
  --zzph-av: #b9c0cc;
  --zzph-av-me: #8fa8c8;
  --zzph-tf: #f0a04b;
  --zzph-tf-done: #f5c999;
  --zzph-dot: #e5484d;
  --zzph-accent: #4f6f9f;
  /* 聊天背景:none 表示不用图;换图就把 none 换成 url("图片链接") */
  --zzph-wall: none;
}
/* 外框 */
.zzph {
  width: 100%;
  max-width: 340px;
  margin: 8px auto;
  box-sizing: border-box;
  border: 8px solid var(--zzph-frame);
  border-radius: 36px;
  background: var(--zzph-bg);
  overflow: hidden;
  color: var(--zzph-text);
  font-family:
    -apple-system, "PingFang SC", "Helvetica Neue", "Microsoft YaHei",
    sans-serif;
  font-size: 14px;
  line-height: 1.5;
  text-align: left;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
/* text-shadow: none:Rubii 默认样式「文字阴影」在手机上会给正文加阴影。
   头像首字虽然设成透明,阴影还在,会在头像图上留下一个淡淡的字;手机里的文字也会发虚 */
.zzph,
.zzph * {
  box-sizing: border-box;
  text-shadow: none;
}
.zzph svg {
  display: inline-block;
  vertical-align: middle;
}
.zzph .rubii-default-quote {
  background: none;
  -webkit-text-fill-color: currentColor;
  filter: none;
  color: inherit;
  font-weight: inherit;
}
/* 状态栏:App 不会按外框圆角裁切里面的内容,所以最上、最下两块自己带圆角(36px 外框 - 8px 边框 = 28px) */
.zzph-status {
  border-radius: 28px 28px 0 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 32px;
  padding: 0 18px;
  background: var(--zzph-bar);
  font-size: 12px;
  font-weight: 600;
}
/* 左右两块等宽,岛才能居中。右边三个图标共 55px,加上间距要 70px,宽度不能再小 */
.zzph-clock {
  width: 72px;
}
.zzph-island {
  width: 78px;
  height: 20px;
  border-radius: 999px;
  background: var(--zzph-frame);
}
.zzph-sig {
  width: 72px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
/* flex-shrink: 0:放不下时也不许把图标压扁(App 会压,网页端不会) */
.zzph-sig svg {
  flex-shrink: 0;
  margin-left: 5px;
}
/* 顶栏 */
.zzph-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 46px;
  padding: 0 10px;
  background: var(--zzph-bar);
  border-bottom: 1px solid var(--zzph-line);
}
.zzph-head-side {
  width: 40px;
  display: flex;
  align-items: center;
}
.zzph-head-side.is-r {
  justify-content: flex-end;
}
.zzph-head-mid {
  width: 64%;
  text-align: center;
}
.zzph-title {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zzph-subtitle {
  font-size: 10px;
  line-height: 1.2;
  color: var(--zzph-sub);
}
/* 聊天区:App 正文不支持内部滚动,所以默认不限高度,手机随消息变长;网页端的固定高度写在下面 @supports 里 */
.zzph-body {
  background-image: var(--zzph-wall);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  padding: 12px 10px 6px;
  scrollbar-width: none;
}
.zzph-body::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.zzph-time {
  margin: 4px 0 10px;
  text-align: center;
}
.zzph-time span {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-tip {
  text-align: center;
  margin: 4px 0 10px;
}
.zzph-tip span {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 消息行:zzph-l 对方 / zzph-r 自己 */
.zzph-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
  animation: zzph-in 0.35s ease-out both;
}
.zzph-l {
  justify-content: flex-start;
}
.zzph-r {
  justify-content: flex-end;
}
@keyframes zzph-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.zzph-av {
  display: block;
  width: 36px;
  min-width: 36px;
  height: 36px;
  border-radius: 6px;
  background-color: var(--zzph-av);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  line-height: 36px;
  text-align: center;
  overflow: hidden;
  object-fit: cover;
}
.zzph-l .zzph-av {
  margin-right: 8px;
}
.zzph-r .zzph-av {
  margin-left: 8px;
  background-color: var(--zzph-av-me);
}
.zzph-col {
  max-width: 72%;
}
.zzph-r .zzph-col {
  text-align: right;
}
/* 左侧发言人名字:默认不显示,群聊时由【群聊】那一行打开 */
.zzph-name {
  display: none;
  font-size: 11px;
  line-height: 1.2;
  color: var(--zzph-sub);
  margin: 0 0 3px 2px;
}
/* 1 文字 */
.zzph-bub {
  display: inline-block;
  text-align: left;
  padding: 8px 11px;
  border-radius: 4px 10px 10px 10px;
  background: var(--zzph-other);
  color: var(--zzph-text);
  word-break: break-word;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
}
.zzph-r .zzph-bub {
  border-radius: 10px 4px 10px 10px;
  background: var(--zzph-me);
  color: var(--zzph-me-text);
}
/* 2 语音(点开转文字) */
.zzph-voice {
  display: inline-block;
  vertical-align: top;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.zzph-voice summary {
  display: block;
  list-style: none;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font-weight: normal;
  cursor: pointer;
}
.zzph-voice summary::-webkit-details-marker {
  display: none;
}
.zzph-voice summary::marker {
  content: "";
}
/* 语音条和红点并排;App 正文里图标和秒数要用 flex 才排得成一行 */
.zzph-vwrap {
  display: flex;
  align-items: flex-start;
}
.zzph-r .zzph-vwrap {
  justify-content: flex-end;
}
.zzph-voice .zzph-bub {
  display: flex;
  align-items: center;
  width: 78px;
}
.zzph-voice.is-m .zzph-bub {
  width: 120px;
}
.zzph-voice.is-l .zzph-bub {
  width: 170px;
}
.zzph-r .zzph-voice .zzph-bub {
  justify-content: flex-end;
}
.zzph-l .zzph-vic-r,
.zzph-r .zzph-vic-l,
.zzph-r .zzph-dot {
  display: none;
}
.zzph-voice-txt:empty {
  display: none;
}
.zzph-r .zzph-voice .zzph-bub svg {
  transform: rotate(180deg);
}
.zzph-sec {
  margin: 0 6px;
  font-size: 13px;
}
.zzph-voice-txt {
  margin-top: 4px;
  padding: 6px 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.75);
  font-size: 13px;
  color: var(--zzph-text);
  text-align: left;
}
.zzph-dot {
  display: inline-block;
  vertical-align: top;
  width: 7px;
  height: 7px;
  margin: 15px 0 0 6px;
  border-radius: 999px;
  background: var(--zzph-dot);
}
.zzph-voice[open] + .zzph-dot {
  display: none;
}
/* 3 表情包:图片版 / 文字版 */
.zzph-stk {
  display: inline-block;
  width: 110px;
  height: auto;
  border-radius: 6px;
}
.zzph-stk-txt {
  width: 100px;
  height: 100px;
  padding-top: 20px;
  border: 1px dashed #c9ccd4;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.6);
  color: var(--zzph-sub);
  font-size: 11px;
  line-height: 1.4;
  text-align: center;
}
.zzph-stk-txt div {
  margin-top: 6px;
  padding: 0 6px;
}
/* 3b 表情包:序号版(【表情3】→ 正则换成 <span class="zzph-sk zzph-sk-3"></span>,图在文件末尾的对照表里) */
.zzph-sk {
  display: inline-block;
  width: 110px;
  height: 110px;
  border-radius: 6px;
  background-color: #e4e7ee;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  vertical-align: top;
}
/* 4 图片:图片版 / 文字描述版 */
.zzph-img {
  display: inline-block;
  width: 160px;
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}
.zzph-pic {
  display: inline-block;
  width: 160px;
  min-height: 118px;
  padding: 22px 12px 12px;
  border-radius: 8px;
  background: linear-gradient(135deg, #e4e7ee, #c9d0dc);
  color: #5d6675;
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}
.zzph-pic-txt {
  margin-top: 6px;
}
/* 5 转账 */
.zzph-tf {
  display: inline-block;
  width: 210px;
  text-align: left;
  border-radius: 8px;
  background: var(--zzph-tf);
  color: #fff;
  overflow: hidden;
}
.zzph-tf.is-done {
  background: var(--zzph-tf-done);
}
.zzph-tf-main {
  display: flex;
  align-items: center;
  padding: 12px 12px 10px;
}
.zzph-tf-ic {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 34px;
  min-width: 34px;
  height: 34px;
  margin-right: 10px;
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
}
.zzph-tf-info {
  width: 140px;
}
.zzph-tf-amt {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}
.zzph-tf-note {
  font-size: 11px;
  opacity: 0.9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zzph-tf-foot {
  padding: 4px 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
  font-size: 10px;
  opacity: 0.9;
}
/* 6 转发的聊天记录(点开看全部) */
.zzph-fw {
  display: inline-block;
  width: 220px;
  vertical-align: top;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: var(--zzph-other);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
  text-align: left;
  overflow: hidden;
  color: var(--zzph-text);
}
.zzph-fw summary {
  display: block;
  list-style: none;
  margin: 0;
  padding: 10px 12px 0;
  border: none;
  background: none;
  color: inherit;
  font-weight: normal;
  cursor: pointer;
}
.zzph-fw summary::-webkit-details-marker {
  display: none;
}
.zzph-fw summary::marker {
  content: "";
}
.zzph-fw-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.zzph-fw-meta {
  margin-top: 2px;
  font-size: 12px;
  color: var(--zzph-sub);
}
.zzph-fw-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
  padding: 5px 0 6px;
  border-top: 1px solid var(--zzph-line);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-fw[open] .zzph-fw-arrow {
  transform: rotate(180deg);
}
.zzph-fw-list {
  padding: 0 12px 6px;
  border-top: 1px solid var(--zzph-line);
}
.zzph-fw-item {
  padding: 7px 0;
  border-bottom: 1px dashed var(--zzph-line);
  font-size: 12px;
  line-height: 1.5;
}
.zzph-fw-item:last-child {
  border-bottom: none;
}
.zzph-fw-who {
  display: block;
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 7 分享链接(推文 / 文章):有链接用 <a>,没有就用 <div> */
.zzph-link {
  display: inline-block;
  width: 230px;
  vertical-align: top;
  padding: 10px 12px 0;
  border-radius: 8px;
  background: var(--zzph-other);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
  text-align: left;
  overflow: hidden;
}
.zzph .zzph-link {
  color: var(--zzph-text);
  text-decoration: none;
}
.zzph-link-title {
  max-height: 2.8em;
  overflow: hidden;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.zzph-link-body {
  display: flex;
  align-items: flex-start;
  margin-top: 6px;
}
.zzph-link-desc {
  width: 148px;
  max-height: 4.5em;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.5;
  color: var(--zzph-sub);
}
.zzph-link-thumb {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 48px;
  min-width: 48px;
  height: 48px;
  margin-left: 10px;
  border-radius: 4px;
  background: #e4e7ee;
  color: #8f98a8;
  object-fit: cover;
}
.zzph-link-foot {
  display: flex;
  align-items: center;
  margin-top: 8px;
  padding: 5px 0 6px;
  border-top: 1px solid var(--zzph-line);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-link-foot svg {
  margin-right: 4px;
}
/* 8 撤回:点开可看原文 */
.zzph-recall .zzph-tip-act {
  margin-left: 4px;
  padding: 0;
  background: none;
  color: var(--zzph-accent);
}
.zzph-recall {
  display: block;
  margin: 4px 0 10px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
  text-align: center;
}
.zzph-recall summary {
  display: inline-block;
  list-style: none;
  margin: 0;
  padding: 2px 8px;
  border: none;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  color: var(--zzph-sub);
  font-size: 11px;
  font-weight: normal;
  cursor: pointer;
}
.zzph-recall summary::-webkit-details-marker {
  display: none;
}
.zzph-recall summary::marker {
  content: "";
}
.zzph-recall-txt {
  display: inline-block;
  max-width: 80%;
  margin-top: 5px;
  padding: 6px 10px;
  border: 1px dashed #c9ccd4;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--zzph-sub);
  font-size: 12px;
  line-height: 1.5;
  text-align: left;
}
.zzph-recall-tag {
  margin-right: 4px;
  color: var(--zzph-dot);
}
/* 9 引用回复:挂在气泡下面 */
.zzph-quote {
  margin-top: 4px;
}
.zzph-quote span {
  display: inline-block;
  max-width: 100%;
  max-height: 2.8em;
  overflow: hidden;
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  color: var(--zzph-sub);
  font-size: 12px;
  line-height: 1.4;
  text-align: left;
}
/* 10 通话记录:is-miss 未接 / 取消 */
.zzph-call {
  display: flex;
  align-items: center;
}
.zzph-call svg {
  margin: 0 6px 0 0;
}
.zzph-call-语音 .zzph-ic-video,
.zzph-call-视频 .zzph-ic-phone {
  display: none;
}
.zzph-call.is-miss {
  color: var(--zzph-dot);
}
/* 11 发送失败:感叹号放在气泡朝里的一侧(右侧消息在气泡左边,左侧消息在气泡右边) */
.zzph-fail {
  width: 18px;
  min-width: 18px;
  height: 18px;
  margin: 9px 6px 0 0;
  color: var(--zzph-dot);
}
.zzph-l .zzph-fail {
  margin: 9px 0 0 6px;
}
.zzph-fail svg {
  display: block;
}
/* 输入栏 */
.zzph-input {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 10px;
  background: var(--zzph-bar);
  border-top: 1px solid var(--zzph-line);
  color: #4a4a52;
}
.zzph-field {
  width: 62%;
  height: 32px;
  border-radius: 6px;
  background: #fff;
}
/* 12 表情面板:整条输入栏是 summary,点开在下方展开 */
.zzph-kb {
  display: block;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: var(--zzph-bar);
  box-shadow: none;
}
.zzph-kb > summary {
  list-style: none;
  margin: 0;
  font-weight: normal;
  cursor: pointer;
}
.zzph-kb > summary::-webkit-details-marker {
  display: none;
}
.zzph-kb > summary::marker {
  content: "";
}
.zzph-kb[open] .zzph-kb-emo {
  color: var(--zzph-accent);
}
.zzph-emo {
  padding: 8px 8px 2px;
  border-top: 1px solid var(--zzph-line);
}
.zzph-emo-head {
  padding: 0 4px 6px;
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 表情格子:App 上全部摊开;网页端限高两行半、在面板里滚动,写在下面 @supports 里 */
.zzph-emo-grid {
  font-size: 0;
  scrollbar-width: none;
}
.zzph-emo-grid::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.zzph-emo-item {
  display: inline-block;
  width: 25%;
  padding: 4px;
  vertical-align: top;
  text-align: center;
}
.zzph-emo-item .zzph-sk {
  display: block;
  width: 64px;
  height: 64px;
  margin: 0 auto;
}
.zzph-emo-no {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
/* 只给网页端:聊天区固定高度、在手机里滚动;面板打开时缩短聊天区,手机总高度不变(App 会忽略这一整段) */
@supports (display: block) {
  .zzph-body {
    max-height: 460px;
    overflow-y: auto;
  }
  .zzph-emo-grid {
    max-height: 168px;
    overflow-y: auto;
  }
  .zzph:has(.zzph-kb[open]) .zzph-body {
    max-height: 260px;
  }
}
.zzph-home {
  border-radius: 0 0 28px 28px;
  padding: 4px 0 8px;
  background: var(--zzph-bar);
}
.zzph-home div {
  width: 110px;
  height: 4px;
  margin: 0 auto;
  border-radius: 999px;
  background: var(--zzph-frame);
}

/* ===== 头像对照表:卡里自带角色的默认头像。照下面的格式一人一行,名字要和 AI 输出里的完全一样,如果一个人ai生成那个的名字可能不同(例如外国char)就把所有可能的名字都写一遍 ===== */
.zzph-av.av-char {
  background-image: url("https://photos.251125.xyz/avatar/IMG_2801.jpeg");
  color: transparent;
}
.zzph-av.av-我 {
  background-image: url("https://photos.251125.xyz/avatar/default.png");
  color: transparent;
}

/* ===== 表情对照表:加表情就在这里加一行,序号接着往下排 ===== */
/* 注意:App 上,文件名以数字开头的图片不显示。把文件名的第一个数字换成「%3+这个数字」就行,比如 /177.png 写成 /%3177.png(1 写成 %31,2 写成 %32……),还是同一张图 */
/* 面板里显示几个表情:把 23 改成「表情总数 + 1」。现在有 22 个表情,所以是 23 */
.zzph-emo-grid .zzph-emo-item:nth-child(n + 23) {
  display: none;
}
.zzph-sk-1 {
  background-image: url("https://photos.251125.xyz/emoji/emoji1.jpeg");
}
.zzph-sk-2 {
  background-image: url("https://photos.251125.xyz/emoji/emoji2.png");
}
.zzph-sk-3 {
  background-image: url("https://photos.251125.xyz/emoji/emoji3.png");
}
.zzph-sk-4 {
  background-image: url("https://photos.251125.xyz/emoji/emoji4.png");
}
.zzph-sk-5 {
  background-image: url("https://photos.251125.xyz/emoji/emoji5.jpeg");
}
.zzph-sk-6 {
  background-image: url("https://photos.251125.xyz/emoji/emoji6.jpeg");
}
.zzph-sk-7 {
  background-image: url("https://photos.251125.xyz/emoji/emoji7.jpeg");
}
.zzph-sk-8 {
  background-image: url("https://photos.251125.xyz/emoji/emoji8.jpeg");
}
.zzph-sk-9 {
  background-image: url("https://photos.251125.xyz/emoji/emoji9.png");
}
.zzph-sk-10 {
  background-image: url("https://photos.251125.xyz/emoji/emoji10.png");
}
.zzph-sk-11 {
  background-image: url("https://photos.251125.xyz/emoji/emoji11.png");
}
.zzph-sk-12 {
  background-image: url("https://photos.251125.xyz/emoji/emoji12.png");
}
.zzph-sk-13 {
  background-image: url("https://photos.251125.xyz/emoji/emoji13.png");
}
.zzph-sk-14 {
  background-image: url("https://photos.251125.xyz/emoji/emoji14.jpeg");
}
.zzph-sk-15 {
  background-image: url("https://photos.251125.xyz/emoji/emoji15.jpeg");
}
.zzph-sk-16 {
  background-image: url("https://photos.251125.xyz/emoji/emoji16.jpeg");
}
.zzph-sk-17 {
  background-image: url("https://photos.251125.xyz/emoji/emoji17.gif");
}
.zzph-sk-18 {
  background-image: url("https://photos.251125.xyz/emoji/emoji18.jpeg");
}
.zzph-sk-19 {
  background-image: url("https://photos.251125.xyz/emoji/emoji19.png");
}
.zzph-sk-20 {
  background-image: url("https://photos.251125.xyz/emoji/emoji20.gif");
}
.zzph-sk-21 {
  background-image: url("https://photos.251125.xyz/emoji/emoji21.jpg");
}
.zzph-sk-22 {
  background-image: url("https://photos.251125.xyz/emoji/emoji22.jpg");
}

朋友圈 CSS贴在上面那段小手机 CSS 的后面。它要用小手机的外框和色板,不能单独贴

朋友圈 App 兼容更新:替换本节整段朋友圈 CSS,并更新正则 第 34 条「朋友圈·点赞」、第 38 条「朋友圈·一条」、第 39 条「朋友圈·外壳」。其中「朋友圈·一条」的表达式和替换内容都要更新,另外两条更新替换内容。长文直接完整显示;App 随页面展开,网页在手机内滚动。

朋友圈的颜色全部取自小手机的色板,自己没有单独的配色。所以不管你用的是通用版、玫瑰版,还是自己改过色板,都不用另做一份朋友圈 CSS,把下面这段直接跟在小手机 CSS 后面就行,颜色会自动跟着变。

/* ===== 朋友圈 通用版 ===== 依赖「小手机 通用版.css」的外框和色板,贴在它后面 */
/* 色板:朋友圈(颜色都取自小手机色板。用玫瑰版或自己改过色板的,不用另做一份,直接把这段跟在小手机 CSS 后面,颜色会自动跟着变) */
.zzph {
  --zzpm-page: var(--zzph-other);
  --zzpm-box: var(--zzph-bg);
  --zzpm-name: var(--zzph-accent);
  /* 没有配背景图的人(下面对照表里没写、AI 也没写 <cv>),背景用这个渐变 */
  --zzpm-cover: linear-gradient(160deg, var(--zzph-av-me), var(--zzph-accent));
}
/* 朋友圈页面:App 不支持内部滚动,默认随内容变长;网页端的固定高度写在下面 @supports 里 */
.zzpm-body {
  background: var(--zzpm-page);
  scrollbar-width: none;
}
.zzpm-body::-webkit-scrollbar {
  width: 0;
  height: 0;
}
/* 封面容器完整容纳头像,父级放图片,资料行单独画底部页面色分界。 */
.zzpm-cover {
  height: 224px;
  padding: 160px 0 0;
  background-color: var(--zzph-av-me);
  background-image: var(--zzpm-cover);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.zzpm-profile {
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  height: 64px;
  padding: 0 14px;
  background-image: linear-gradient(to bottom, transparent 0px, transparent 40px, var(--zzpm-page) 40px, var(--zzpm-page) 64px);
}
.zzph .zzpm-owner {
  width: 160px;
  margin: 0 12px 0 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
  text-align: right;
  word-break: break-all;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.zzph-av.zzpm-owner-av {
  width: 64px;
  min-width: 64px;
  height: 64px;
  border-radius: 10px;
  font-size: 26px;
  line-height: 64px;
  box-shadow: 0 0 0 2px var(--zzpm-page);
}
.zzpm-sign {
  min-height: 16px;
  padding: 6px 14px 6px 50px;
  text-align: right;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
/* 每一条朋友圈 */
.zzpm-post {
  display: flex;
  align-items: flex-start;
  padding: 14px 12px;
  border-bottom: 1px solid var(--zzph-line);
  animation: zzph-in 0.35s ease-out both;
}
.zzph-av.zzpm-av {
  width: 40px;
  min-width: 40px;
  height: 40px;
  margin-right: 10px;
  line-height: 40px;
}
/* App 正文里 flex:1 无效,先给固定百分比;网页端在 @supports 里改成 flex:1 */
.zzpm-main {
  width: 82%;
}
.zzpm-name {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--zzpm-name);
}
.zzpm-text {
  margin: 3px 0 6px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  word-break: break-word;
}
/* 配图:沿用小手机的【图片】规则(zzph-img / zzph-pic),在朋友圈里改成 72px 的九宫格;只有一张时自动放大 */
.zzpm-pics {
  margin-top: 8px;
  font-size: 0;
}
.zzpm-pics.is-4 {
  width: 156px;
}
.zzpm-pics .zzph-img,
.zzpm-pics .zzph-pic {
  display: inline-block;
  vertical-align: top;
  width: 72px;
  max-width: none;
  height: 72px;
  min-height: 0;
  margin: 0 4px 4px 0;
  border-radius: 4px;
  object-fit: cover;
}
/* 文字描述版配图 */
.zzpm-pics .zzph-pic {
  padding: 7px 6px;
  overflow: hidden;
  font-size: 10px;
  line-height: 1.35;
}
.zzpm-pics .zzph-pic svg {
  display: block;
  width: 16px;
  height: 16px;
  margin: 0 auto 3px;
}
.zzpm-pics .zzph-pic-txt {
  margin-top: 0;
  font-size: 9px;
}
.zzpm-pics > .zzph-img:only-child {
  width: auto;
  height: auto;
  max-width: 170px;
  max-height: 210px;
}
.zzpm-pics > .zzph-pic:only-child {
  width: 150px;
  height: auto;
  min-height: 112px;
  padding: 18px 12px 12px;
  font-size: 12px;
  line-height: 1.5;
}
.zzpm-pics > .zzph-pic:only-child svg {
  width: 26px;
  height: 26px;
  margin-bottom: 6px;
}
.zzpm-pics > .zzph-pic:only-child .zzph-pic-txt {
  font-size: 11px;
}
/* 文案、评论里的序号表情包缩小一点 */
.zzpm-post .zzph-sk {
  width: 56px;
  height: 56px;
}
/* 位置:没写位置时整行不占地方 */
.zzpm-loc {
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzpm-name);
}
.zzpm-loc:empty {
  display: none;
}
/* 时间行采用 AD 分组,长时间允许换行。删除文字仅在输入已有该字段时显示。 */
.zzpm-meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
.zzpm-meta-left {
  display: flex;
  align-items: flex-start;
  width: 82%;
}
.zzpm-time {
  display: block;
  max-width: 70%;
  word-break: break-word;
}
.zzpm-delete {
  display: block;
  width: 28px;
  margin-left: 10px;
  color: var(--zzpm-name);
  white-space: nowrap;
}
.zzpm-delete:empty {
  display: none;
}
.zzpm-more {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  min-width: 30px;
  height: 20px;
  border-radius: 4px;
  background: var(--zzpm-box);
  color: var(--zzpm-name);
}
.zzpm-more svg,
.zzpm-more circle {
  fill: var(--zzpm-name);
}
/* 点赞 + 评论区:上方的小三角是用边框画的。padding-top 的 1px 不能删,没有它三角的负 margin 会和外层合并,三角就缩回去了 */
.zzpm-box {
  margin-top: 10px;
  padding: 1px 9px 4px;
  border-radius: 4px;
  background: var(--zzpm-box);
  font-size: 13px;
  line-height: 1.5;
}
.zzpm-box::before {
  content: "";
  display: block;
  width: 0;
  height: 0;
  margin: -7px 0 3px 3px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid var(--zzpm-box);
}
/* 没人点赞也没人评论时,整个框不显示 */
.zzpm-box:empty {
  display: none;
}
.zzpm-likes {
  display: flex;
  align-items: flex-start;
  padding: 1px 0 3px;
  color: var(--zzpm-name);
  font-weight: 600;
  word-break: break-word;
}
.zzpm-likes svg {
  display: block;
  width: 14px;
  min-width: 14px;
  height: 14px;
  margin: 3px 5px 0 0;
  stroke: var(--zzpm-name);
}
.zzpm-likes path {
  stroke: var(--zzpm-name);
}
.zzpm-like-names {
  display: block;
  width: 88%;
  color: var(--zzpm-name);
  font-size: 13px;
  line-height: 1.5;
  word-break: break-word;
}
.zzpm-cmt {
  padding: 1px 0;
  word-break: break-word;
}
/* 既有点赞又有评论时,中间加一条分隔线 */
.zzpm-likes + .zzpm-cmt {
  margin: 0 -9px;
  padding: 4px 9px 1px;
  border-top: 1px solid var(--zzph-line);
}
.zzpm-who {
  color: var(--zzpm-name);
  font-weight: 600;
}
.zzpm-rp {
  margin: 0 2px;
}
/* 只给网页端:朋友圈固定高度、在手机里滚动;正文区用 flex:1 撑满(App 会忽略这一整段) */
@supports (display: block) {
  .zzpm-body {
    max-height: 520px;
    overflow-y: auto;
  }
  .zzpm-main {
    width: auto;
    flex: 1;
    min-width: 0;
  }
}

/* ===== 朋友圈背景对照表:卡里自带角色的默认背景。一人一行,名字要和 AI 输出里的完全一样 ===== */
/* 玩家自己的背景不写在这里:让 AI 在朋友圈里写 <cv>名字=链接</cv>。都没有的人用上面色板里的渐变 */
.zzpm-cover.cv-char {
  background-image: url("https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800");
}

第 2 步 正则(小手机 28 条 + 朋友圈 11 条)

打开 美化&正则 → 正则,按下面的编号依次新建。每一条都这样填:

名称:复制「名称」
应用于:所有消息
匹配范围:原始内容(含 HTML 标签)
表达式:复制「表达式」
替换内容:复制「替换内容」
之前已经装好小手机正则、现在要加朋友圈的:先更新第 1、2 两条。把「小手机·清理空行」和「小手机·头像表」的表达式换成下面的新版,替换内容不用改。旧版的表达式结尾是 <\/zzph>),只在小手机里生效;新版结尾是 <\/(?:zzph|zzpm)>),朋友圈里也生效。不更新的话,朋友圈里的 <av> 头像不显示,AI 多空一行时某条朋友圈会显示成原文。小手机的其余 26 条不用动,再把朋友圈的 11 条接在「小手机·外壳」下面就行。

准备先做两件准备:去掉空行、读取头像表。

01

小手机·清理空行

把小手机和朋友圈里的空行去掉,防止 AI 多空一行把整个手机拆散。替换内容是空的,什么都不填。

名称
小手机·清理空行
表达式
/\n[ \t]*(?=\n)(?=(?:(?!<(?:zzph|zzpm)>)[\s\S])*?<\/(?:zzph|zzpm)>)/g
替换内容

空着,什么都不填。

02

小手机·头像表

把 名字=链接 变成这一个手机里的头像设置。朋友圈也用这一条。

名称
小手机·头像表
表达式
/<av>\s*([^\s<【::!!]+)\s*[==]\s*(https?:\/\/[^\s<"')]+)\s*<\/av>(?=(?:(?!<(?:zzph|zzpm)>)[\s\S])*?<\/(?:zzph|zzpm)>)/gi
替换内容
<style>.zzph .zzph-av.av-$1{background-image:url("$2");color:transparent;}</style>
03

小手机·群聊

不限小手机

群聊时 AI 会多写一行【群聊】,这条把它变成「显示左侧名字」的开关。放在哪个位置都行。

名称
小手机·群聊
表达式
/^[ \t]*【群聊】[ \t]*$/gm
替换内容
<style>.zzph .zzph-name{display:block;}</style>

独立行居中显示、没有头像的行。

04

小手机·时间

名称
小手机·时间
表达式
/^[ \t]*【时间[::]([^】\n]*)】[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<div class="zzph-time"><span>$1</span></div>
05

小手机·提示

名称
小手机·提示
表达式
/^[ \t]*【提示[::]([^】\n]*)】[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<div class="zzph-tip"><span>$1</span></div>
06

小手机·撤回·我

名称
小手机·撤回·我
表达式
/^[ \t]*我[::][ \t]*【撤回[::]([^】\n]+)】[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<details class="zzph-recall"><summary>你撤回了一条消息<span class="zzph-tip-act">重新编辑</span></summary><div class="zzph-recall-txt"><span class="zzph-recall-tag">已撤回</span>$1</div></details>
07

小手机·撤回

名称
小手机·撤回
表达式
/^[ \t]*([^\s<【::!!]+)[::][ \t]*【撤回[::]([^】\n]+)】[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<details class="zzph-recall"><summary>“$1”撤回了一条消息</summary><div class="zzph-recall-txt"><span class="zzph-recall-tag">已撤回</span>$2</div></details>

消息内容把【】里的特殊消息换成卡片。

08

小手机·语音·长

10 秒以上的语音,气泡更长。

名称
小手机·语音·长
表达式
/【语音\s*(\d{2,})\s*[″"”'′秒s]*\s*(?:[::]([^】\n]*))?】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-vwrap"><details class="zzph-voice is-m"><summary><div class="zzph-bub"><svg class="zzph-vic-l" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="5" cy="12" r="1.6" fill="currentColor" stroke="none"/><path d="M8.5 8.5a5 5 0 0 1 0 7"/><path d="M12 5a10 10 0 0 1 0 14"/></svg><span class="zzph-sec">$1″</span><svg class="zzph-vic-r" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="5" cy="12" r="1.6" fill="currentColor" stroke="none"/><path d="M8.5 8.5a5 5 0 0 1 0 7"/><path d="M12 5a10 10 0 0 1 0 14"/></svg></div></summary><div class="zzph-voice-txt">$2</div></details><span class="zzph-dot"></span></div>
09

小手机·语音

名称
小手机·语音
表达式
/【语音\s*(\d)\s*[″"”'′秒s]*\s*(?:[::]([^】\n]*))?】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-vwrap"><details class="zzph-voice"><summary><div class="zzph-bub"><svg class="zzph-vic-l" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="5" cy="12" r="1.6" fill="currentColor" stroke="none"/><path d="M8.5 8.5a5 5 0 0 1 0 7"/><path d="M12 5a10 10 0 0 1 0 14"/></svg><span class="zzph-sec">$1″</span><svg class="zzph-vic-r" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="5" cy="12" r="1.6" fill="currentColor" stroke="none"/><path d="M8.5 8.5a5 5 0 0 1 0 7"/><path d="M12 5a10 10 0 0 1 0 14"/></svg></div></summary><div class="zzph-voice-txt">$2</div></details><span class="zzph-dot"></span></div>
10

表情·序号

不限小手机

这一条不限于小手机:玩家在自己的消息里打【表情3】也会变成图片。

名称
表情·序号
表达式
/[【\[]表情\s*(\d+)[】\]]/g
替换内容
<span class="zzph-sk zzph-sk-$1"></span>
11

小手机·表情·描述

名称
小手机·表情·描述
表达式
/【表情[::]([^】\n]+)】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-stk zzph-stk-txt"><svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><path d="M8.5 14.5a4.5 4.5 0 0 0 7 0"/><circle cx="9" cy="10" r=".9" fill="currentColor"/><circle cx="15" cy="10" r=".9" fill="currentColor"/></svg><div>$1</div></div>
12

小手机·图片·链接

名称
小手机·图片·链接
表达式
/【图片[::]\s*(https?:\/\/[^\s】]+)\s*】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<img class="zzph-img" src="$1" alt="图片">
13

小手机·图片·描述

名称
小手机·图片·描述
表达式
/【图片[::]([^】\n]+)】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-pic"><svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2.5"/><circle cx="9" cy="9.5" r="1.6"/><path d="M21 16l-5-5-9 9"/></svg><div class="zzph-pic-txt">$1</div></div>
14

小手机·转账

名称
小手机·转账
表达式
/【转账\s*[¥¥]?\s*([\d.,]+)\s*(?:[::]([^】\n]*))?】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-tf"><div class="zzph-tf-main"><div class="zzph-tf-ic"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 9h13l-3.5-3.5"/><path d="M19 15H6l3.5 3.5"/></svg></div><div class="zzph-tf-info"><div class="zzph-tf-amt">¥$1</div><div class="zzph-tf-note">$2</div></div></div><div class="zzph-tf-foot">转账</div></div>
15

小手机·收款

名称
小手机·收款
表达式
/【收款\s*[¥¥]?\s*([\d.,]+)[^】\n]*】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-tf is-done"><div class="zzph-tf-main"><div class="zzph-tf-ic"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></div><div class="zzph-tf-info"><div class="zzph-tf-amt">¥$1</div><div class="zzph-tf-note">已收款</div></div></div><div class="zzph-tf-foot">转账</div></div>
16

小手机·通话·未接

状态里有「未接、取消、拒、无人、失败、忙」任一个词,就显示成红色。

名称
小手机·通话·未接
表达式
/【(语音|视频)通话[::]([^】\n]*(?:未接|取消|拒|无人|失败|忙)[^】\n]*)】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-bub zzph-call zzph-call-$1 is-miss"><svg class="zzph-ic-phone" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 4h3l2 5-2.5 1.5a11 11 0 0 0 6 6L15 14l5 2v3a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z"/></svg><svg class="zzph-ic-video" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12" height="12" rx="2"/><path d="M15 10l6-3v10l-6-3z"/></svg><span>$2</span></div>
17

小手机·通话

名称
小手机·通话
表达式
/【(语音|视频)通话[::]([^】\n]+)】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-bub zzph-call zzph-call-$1"><svg class="zzph-ic-phone" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 4h3l2 5-2.5 1.5a11 11 0 0 0 6 6L15 14l5 2v3a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z"/></svg><svg class="zzph-ic-video" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12" height="12" rx="2"/><path d="M15 10l6-3v10l-6-3z"/></svg><span>$2</span></div>
18

小手机·链接·带图

名称
小手机·链接·带图
表达式
/【链接[::]([^||】\n]*)[||]([^||】\n]*)[||]([^||】\n]*)[||]\s*(https?:\/\/[^\s】]+)\s*】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-link"><div class="zzph-link-title">$1</div><div class="zzph-link-body"><div class="zzph-link-desc">$2</div><img class="zzph-link-thumb" src="$4" alt=""></div><div class="zzph-link-foot"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1"/><path d="M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1"/></svg><span>$3</span></div></div>
19

小手机·链接

名称
小手机·链接
表达式
/【链接[::]([^||】\n]*)(?:[||]([^||】\n]*))?(?:[||]([^||】\n]*))?】(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-link"><div class="zzph-link-title">$1</div><div class="zzph-link-body"><div class="zzph-link-desc">$2</div><div class="zzph-link-thumb"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M5 5h14v10H9l-4 4z"/><path d="M9 9h6M9 12h4"/></svg></div></div><div class="zzph-link-foot"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1"/><path d="M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1"/></svg><span>$3</span></div></div>
20

小手机·转发·条目

必须排在「转发·外壳」上面。

名称
小手机·转发·条目
表达式
/《([^《》::\n]*?(?:\s*\d{1,2}[::]\d{2})?)\s*[::]([^《》\n]+)》(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/g
替换内容
<div class="zzph-fw-item"><span class="zzph-fw-who">$1</span>$2</div>
21

小手机·转发·外壳

名称
小手机·转发·外壳
表达式
/【转发[::]([^】\n]+)】[ \t]*([^\n]*?)[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<details class="zzph-fw"><summary><div class="zzph-fw-title">$1</div><div class="zzph-fw-meta">点击查看</div><div class="zzph-fw-foot"><span>聊天记录</span><svg class="zzph-fw-arrow" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg></div></summary><div class="zzph-fw-list">$2</div></details>
22

小手机·引用

名称
小手机·引用
表达式
/([::])[ \t]*([^\n【<]*?)[ \t]*【引用[::]([^】\n]+)】[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
$1<div class="zzph-bub">$2</div><div class="zzph-quote"><span>$3</span></div>

消息行把「名字:内容」做成左右两边的气泡行。

23

小手机·文字气泡

冒号后面还是普通文字的,套上气泡。

名称
小手机·文字气泡
表达式
/^([ \t]*[^\s<【::]+[::][ \t]*)([^<\s][^\n]*?)[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
$1<div class="zzph-bub">$2</div>
24

小手机·我·发送失败

名称
小手机·我·发送失败
表达式
/^[ \t]*我[!!][::][ \t]*(.*?)[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<div class="zzph-row zzph-r"><div class="zzph-fail"><svg width="18" height="18" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M12 7v6" stroke="#fff" stroke-width="2.2" stroke-linecap="round"/><circle cx="12" cy="16.6" r="1.3" fill="#fff"/></svg></div><div class="zzph-col">$1</div><div class="zzph-av av-我">我</div></div>
25

小手机·我

名称
小手机·我
表达式
/^[ \t]*我[::][ \t]*(.*?)[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<div class="zzph-row zzph-r"><div class="zzph-col">$1</div><div class="zzph-av av-我">我</div></div>
26

小手机·对方·发送失败

名称
小手机·对方·发送失败
表达式
/^[ \t]*(([^\s<【::!!])[^\s<【::!!]*)[!!][::][ \t]*(.*?)[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<div class="zzph-row zzph-l"><div class="zzph-av av-$1">$2</div><div class="zzph-col"><div class="zzph-name">$1</div>$3</div><div class="zzph-fail"><svg width="18" height="18" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M12 7v6" stroke="#fff" stroke-width="2.2" stroke-linecap="round"/><circle cx="12" cy="16.6" r="1.3" fill="#fff"/></svg></div></div>
27

小手机·对方

名称
小手机·对方
表达式
/^[ \t]*(([^\s<【::!!])[^\s<【::!!]*)[::][ \t]*(.*?)[ \t]*$(?=(?:(?!<zzph>)[\s\S])*?<\/zzph>)/gm
替换内容
<div class="zzph-row zzph-l"><div class="zzph-av av-$1">$2</div><div class="zzph-col"><div class="zzph-name">$1</div>$3</div></div>

外壳把整段套进手机外框。

28

小手机·外壳

不限小手机

必须排在小手机这部分的最后一条。朋友圈的正则接在它下面。

名称
小手机·外壳
表达式
/<zzph>[ \t]*\n?(?:[ \t]*<pt>([^||<\n]*)(?:[||]([^||<\n]*))?(?:[||]([^||<\n]*))?<\/pt>[ \t]*\n?)?([\s\S]*?)\n?[ \t]*<\/zzph>/gi
替换内容
<div class="zzph"><div class="zzph-status"><div class="zzph-clock">$3</div><div class="zzph-island"></div><div class="zzph-sig"><svg width="16" height="11" viewBox="0 0 16 11" fill="currentColor"><rect x="0" y="7" width="3" height="4" rx="1"/><rect x="4.3" y="5" width="3" height="6" rx="1"/><rect x="8.6" y="2.5" width="3" height="8.5" rx="1"/><rect x="12.9" y="0" width="3" height="11" rx="1"/></svg><svg width="15" height="11" viewBox="0 0 24 18" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round"><path d="M2 6.5a15 15 0 0 1 20 0"/><path d="M5.5 10.2a10 10 0 0 1 13 0"/><path d="M9 13.8a5 5 0 0 1 6 0"/><circle cx="12" cy="16.5" r=".8" fill="currentColor"/></svg><svg width="24" height="12" viewBox="0 0 26 13" fill="none"><rect x=".75" y=".75" width="21.5" height="11.5" rx="3.2" stroke="currentColor" stroke-width="1.3" opacity=".5"/><rect x="2.6" y="2.6" width="15" height="7.8" rx="1.8" fill="currentColor"/><path d="M24 4.5v4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" opacity=".5"/></svg></div></div><div class="zzph-head"><div class="zzph-head-side"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></div><div class="zzph-head-mid"><div class="zzph-title">$1</div><div class="zzph-subtitle">$2</div></div><div class="zzph-head-side is-r"><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="1.8"/><circle cx="12" cy="12" r="1.8"/><circle cx="19" cy="12" r="1.8"/></svg></div></div><div class="zzph-body">$4</div><details class="zzph-kb"><summary class="zzph-input"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><circle cx="12" cy="12" r="9.5"/><circle cx="8.5" cy="12" r="1" fill="currentColor" stroke="none"/><path d="M11 9.5a3.5 3.5 0 0 1 0 5"/><path d="M13.5 7.5a6.5 6.5 0 0 1 0 9"/></svg><div class="zzph-field"></div><svg class="zzph-kb-emo" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><circle cx="12" cy="12" r="9.5"/><path d="M8.5 14.5a4.5 4.5 0 0 0 7 0"/><circle cx="9" cy="10" r=".9" fill="currentColor"/><circle cx="15" cy="10" r=".9" fill="currentColor"/></svg><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><circle cx="12" cy="12" r="9.5"/><path d="M12 8v8M8 12h8"/></svg></summary><div class="zzph-emo"><div class="zzph-emo-head">发送时输入【表情+序号】</div><div class="zzph-emo-grid"><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-1"></span><span class="zzph-emo-no">1</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-2"></span><span class="zzph-emo-no">2</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-3"></span><span class="zzph-emo-no">3</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-4"></span><span class="zzph-emo-no">4</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-5"></span><span class="zzph-emo-no">5</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-6"></span><span class="zzph-emo-no">6</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-7"></span><span class="zzph-emo-no">7</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-8"></span><span class="zzph-emo-no">8</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-9"></span><span class="zzph-emo-no">9</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-10"></span><span class="zzph-emo-no">10</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-11"></span><span class="zzph-emo-no">11</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-12"></span><span class="zzph-emo-no">12</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-13"></span><span class="zzph-emo-no">13</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-14"></span><span class="zzph-emo-no">14</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-15"></span><span class="zzph-emo-no">15</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-16"></span><span class="zzph-emo-no">16</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-17"></span><span class="zzph-emo-no">17</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-18"></span><span class="zzph-emo-no">18</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-19"></span><span class="zzph-emo-no">19</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-20"></span><span class="zzph-emo-no">20</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-21"></span><span class="zzph-emo-no">21</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-22"></span><span class="zzph-emo-no">22</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-23"></span><span class="zzph-emo-no">23</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-24"></span><span class="zzph-emo-no">24</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-25"></span><span class="zzph-emo-no">25</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-26"></span><span class="zzph-emo-no">26</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-27"></span><span class="zzph-emo-no">27</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-28"></span><span class="zzph-emo-no">28</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-29"></span><span class="zzph-emo-no">29</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-30"></span><span class="zzph-emo-no">30</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-31"></span><span class="zzph-emo-no">31</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-32"></span><span class="zzph-emo-no">32</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-33"></span><span class="zzph-emo-no">33</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-34"></span><span class="zzph-emo-no">34</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-35"></span><span class="zzph-emo-no">35</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-36"></span><span class="zzph-emo-no">36</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-37"></span><span class="zzph-emo-no">37</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-38"></span><span class="zzph-emo-no">38</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-39"></span><span class="zzph-emo-no">39</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-40"></span><span class="zzph-emo-no">40</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-41"></span><span class="zzph-emo-no">41</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-42"></span><span class="zzph-emo-no">42</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-43"></span><span class="zzph-emo-no">43</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-44"></span><span class="zzph-emo-no">44</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-45"></span><span class="zzph-emo-no">45</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-46"></span><span class="zzph-emo-no">46</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-47"></span><span class="zzph-emo-no">47</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-48"></span><span class="zzph-emo-no">48</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-49"></span><span class="zzph-emo-no">49</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-50"></span><span class="zzph-emo-no">50</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-51"></span><span class="zzph-emo-no">51</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-52"></span><span class="zzph-emo-no">52</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-53"></span><span class="zzph-emo-no">53</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-54"></span><span class="zzph-emo-no">54</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-55"></span><span class="zzph-emo-no">55</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-56"></span><span class="zzph-emo-no">56</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-57"></span><span class="zzph-emo-no">57</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-58"></span><span class="zzph-emo-no">58</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-59"></span><span class="zzph-emo-no">59</span></div><div class="zzph-emo-item"><span class="zzph-sk zzph-sk-60"></span><span class="zzph-emo-no">60</span></div></div></div></details><div class="zzph-home"><div></div></div></div>
朋友圈部分第 29–39 条,整块接在「小手机·外壳」下面。不用朋友圈的话,这部分可以不加。
之前装过小手机正则的,记得先把第 1、2 条更新成上面的新版。

朋友圈·准备读取背景图设置。

29

朋友圈·背景表

把 名字=链接 变成这一个朋友圈的背景图。

名称
朋友圈·背景表
表达式
/<cv>\s*([^\s<【::!!]+)\s*[==]\s*(https?:\/\/[^\s<"')]+)\s*<\/cv>(?=(?:(?!<zzpm>)[\s\S])*?<\/zzpm>)/gi
替换内容
<style>.zzph .zzpm-cover.cv-$1{background-image:url("$2");}</style>

朋友圈·配图把一整行【图片】包成一组九宫格,再把每张图换成图片或文字描述卡。

30

朋友圈·配图·4张

一行刚好 4 张图时排成两行两列。必须排在「朋友圈·配图」上面。

名称
朋友圈·配图·4张
表达式
/^[ \t]*((?:【图片[::][^】\n]+】[ \t]*){4})$(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/gm
替换内容
<div class="zzpm-pics is-4">$1</div>
31

朋友圈·配图

整行都是【图片】时包成一组配图。必须排在「朋友圈·图片·链接」「朋友圈·图片·描述」上面。

名称
朋友圈·配图
表达式
/^[ \t]*((?:【图片[::][^】\n]+】[ \t]*)+)$(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/gm
替换内容
<div class="zzpm-pics">$1</div>
32

朋友圈·图片·链接

名称
朋友圈·图片·链接
表达式
/【图片[::]\s*(https?:\/\/[^\s】]+)\s*】(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/g
替换内容
<img class="zzph-img" src="$1" alt="图片">
33

朋友圈·图片·描述

名称
朋友圈·图片·描述
表达式
/【图片[::]([^】\n]+)】(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/g
替换内容
<div class="zzph-pic"><svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2.5"/><circle cx="9" cy="9.5" r="1.6"/><path d="M21 16l-5-5-9 9"/></svg><div class="zzph-pic-txt">$1</div></div>

朋友圈·条目把一条朋友圈里的点赞、评论、文案分别做好。

34

朋友圈·点赞

名称
朋友圈·点赞
表达式
/^[ \t]*赞[::][ \t]*(.+?)[ \t]*$(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/gm
替换内容
<div class="zzpm-likes"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linejoin="round"><path d="M12 20s-7.5-4.6-7.5-10.2A4.3 4.3 0 0 1 12 7.3a4.3 4.3 0 0 1 7.5 2.5C19.5 15.4 12 20 12 20z"/></svg><div class="zzpm-like-names">$1</div></div>
35

朋友圈·评论·回复

必须排在「朋友圈·评论」上面。

名称
朋友圈·评论·回复
表达式
/^[ \t]*评[::][ \t]*([^\s<【::!!]+?)[ \t]*回复[ \t]*([^\s<【::!!]+)[ \t]*[::][ \t]*(.*?)[ \t]*$(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/gm
替换内容
<div class="zzpm-cmt"><span class="zzpm-who">$1</span><span class="zzpm-rp">回复</span><span class="zzpm-who">$2</span>:$3</div>
36

朋友圈·评论

名称
朋友圈·评论
表达式
/^[ \t]*评[::][ \t]*([^\s<【::!!]+)[ \t]*[::][ \t]*(.*?)[ \t]*$(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/gm
替换内容
<div class="zzpm-cmt"><span class="zzpm-who">$1</span>:$2</div>
37

朋友圈·文案

一条朋友圈里剩下的普通文字行都是文案。带竖线的是抬头,不算。

名称
朋友圈·文案
表达式
/^[ \t]*([^<\s||][^||\n]*?)[ \t]*$(?=(?:(?!<pyq>)[\s\S])*?<\/pyq>)/gm
替换内容
<div class="zzpm-text">$1</div>

朋友圈·外壳先拼好每一条,再套进朋友圈外框。

38

朋友圈·一条

第一行「名字|时间|位置」拆成抬头;时间末尾已有「删除」时单独显示该文字,仅为展示;末尾连着的点赞、评论装进评论框。必须排在「朋友圈·点赞」「朋友圈·评论」「朋友圈·文案」下面。

名称
朋友圈·一条
表达式
/<pyq>[ \t]*\n[ \t]*(([^\s<【::!!||])[^\s<【::!!||]*)[ \t]*[||][ \t]*([^||\n]*?)(?:[ \t]*(删除))?[ \t]*(?:[||][ \t]*([^||\n]*?)[ \t]*)?\n([\s\S]*?)((?:[ \t]*<div class="zzpm-(?:likes|cmt)">.*\n?)*)[ \t]*<\/pyq>/gi
替换内容
<div class="zzpm-post"><div class="zzph-av av-$1 zzpm-av">$2</div><div class="zzpm-main"><div class="zzpm-name">$1</div>$6<div class="zzpm-loc">$5</div><div class="zzpm-meta"><span class="zzpm-meta-left"><span class="zzpm-time">$3</span><span class="zzpm-delete">$4</span></span><span class="zzpm-more"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><circle cx="8" cy="12" r="2"/><circle cx="16" cy="12" r="2"/></svg></span></div><div class="zzpm-box">$7</div></div></div>
39

朋友圈·外壳

写「朋友圈主人|签名|时间」。必须排在「朋友圈·一条」下面,是全部正则的最后一条。

名称
朋友圈·外壳
表达式
/<zzpm>\s*<pt>[ \t]*(([^\s<【::!!||])[^\s<【::!!||]*)[ \t]*(?:[||]([^||<\n]*))?(?:[||]([^||<\n]*))?<\/pt>([\s\S]*?)<\/zzpm>/gi
替换内容
<div class="zzph"><div class="zzph-status"><div class="zzph-clock">$4</div><div class="zzph-island"></div><div class="zzph-sig"><svg width="16" height="11" viewBox="0 0 16 11" fill="currentColor"><rect x="0" y="7" width="3" height="4" rx="1"/><rect x="4.3" y="5" width="3" height="6" rx="1"/><rect x="8.6" y="2.5" width="3" height="8.5" rx="1"/><rect x="12.9" y="0" width="3" height="11" rx="1"/></svg><svg width="15" height="11" viewBox="0 0 24 18" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round"><path d="M2 6.5a15 15 0 0 1 20 0"/><path d="M5.5 10.2a10 10 0 0 1 13 0"/><path d="M9 13.8a5 5 0 0 1 6 0"/><circle cx="12" cy="16.5" r=".8" fill="currentColor"/></svg><svg width="24" height="12" viewBox="0 0 26 13" fill="none"><rect x=".75" y=".75" width="21.5" height="11.5" rx="3.2" stroke="currentColor" stroke-width="1.3" opacity=".5"/><rect x="2.6" y="2.6" width="15" height="7.8" rx="1.8" fill="currentColor"/><path d="M24 4.5v4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" opacity=".5"/></svg></div></div><div class="zzph-head"><div class="zzph-head-side"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></div><div class="zzph-head-mid"><div class="zzph-title">朋友圈</div></div><div class="zzph-head-side is-r"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8h3l2-3h6l2 3h3v11H4z"/><circle cx="12" cy="13" r="3.5"/></svg></div></div><div class="zzpm-body"><div class="zzpm-cover cv-$1"><div class="zzpm-profile"><div class="zzpm-owner">$1</div><div class="zzph-av av-$1 zzpm-owner-av">$2</div></div></div><div class="zzpm-sign">$3</div>$5</div><div class="zzph-home"><div></div></div></div>

全部正则一览

加完以后,拿 Rubii 里的正则列表和下面对一遍。

小手机(第 1–28 条)

  1. 小手机·清理空行
  2. 小手机·头像表
  3. 小手机·群聊
  4. 小手机·时间
  5. 小手机·提示
  6. 小手机·撤回·我
  7. 小手机·撤回
  8. 小手机·语音·长
  9. 小手机·语音
  10. 表情·序号
  11. 小手机·表情·描述
  12. 小手机·图片·链接
  13. 小手机·图片·描述
  14. 小手机·转账
  15. 小手机·收款
  16. 小手机·通话·未接
  17. 小手机·通话
  18. 小手机·链接·带图
  19. 小手机·链接
  20. 小手机·转发·条目
  21. 小手机·转发·外壳
  22. 小手机·引用
  23. 小手机·文字气泡
  24. 小手机·我·发送失败
  25. 小手机·我
  26. 小手机·对方·发送失败
  27. 小手机·对方
  28. 小手机·外壳(小手机的最后一条)

朋友圈(第 29–39 条,接在小手机后面)

  1. 朋友圈·背景表
  2. 朋友圈·配图·4张
  3. 朋友圈·配图
  4. 朋友圈·图片·链接
  5. 朋友圈·图片·描述
  6. 朋友圈·点赞
  7. 朋友圈·评论·回复
  8. 朋友圈·评论
  9. 朋友圈·文案
  10. 朋友圈·一条
  11. 朋友圈·外壳(全部的最后一条)
「小手机·外壳」必须是小手机部分的最后一条。前面的规则都只处理 <zzph> 和 </zzph> 之间的内容,外壳一处理,这两个标签就没了。外壳要是排在中间,它下面的小手机规则全都不生效,那些消息会显示成原文。以后再新加小手机的规则,也要放在它上面。
朋友圈的 11 条整块接在「小手机·外壳」下面,「朋友圈·外壳」排在全部的最后。道理一样:朋友圈的规则只处理 <zzpm> 里面的内容,朋友圈外壳一处理,标签就没了。朋友圈会用到小手机部分里的「清理空行」「头像表」,所以只装朋友圈、不装小手机是不行的。

第 3 步 输出设定

把下面整段贴进 时刻设定。AI 就是照着这段来写小手机和朋友圈的。前半是【小手机】,后半是【朋友圈】;不用朋友圈的话,把【朋友圈】开始的后半段删掉。

第六部分「表情列表」写了每张表情图的内容。AI 看不见图片,只能靠这些文字挑表情。

【小手机】
剧情里出现手机聊天时(收发消息、翻看聊天记录、偷看手机等),在回复里插入一个小手机。
注意区分状态栏里的信息和群聊。状态栏里的私信和群聊仅是为了丰富趣味,不参与正文。而下面的手机则必须正文里提到才生成。外层禁止被任何标签包裹。

格式如下:

<zzph>
<pt>聊天对象|状态|时间</pt>
名字:内容
</zzph>

一、外壳
1. <zzph> 和 </zzph> 各占一行,必须成对出现。
2. <pt> 写在 <zzph> 的下一行,格式是「聊天对象|状态|时间」。状态可以空着,但两个竖线都要保留,例如 <pt>{{char}}||23:14</pt>。
3. 小手机里只写消息,不写旁白;旁白写在 <zzph> 外面。
4. 群聊时,<pt> 的聊天对象写群名和人数,如 <pt>相亲相爱一家人(5)||23:14</pt>;再单独写一行【群聊】,放在 <pt>(或头像行)的下一行。
二、消息
1. 每条消息单独一行,写成「名字:内容」。一条消息不换行,消息之间不空行。
2. {{user}} 发出的消息一律写「我:」;其他人写本人的名字,名字里不要有空格和标点。
3. 消息发送失败(被拉黑、被拒收)时,名字后面加「!」,如「我!:……」「{{char}}!:……」,并在下一行用【提示:……】写明原因。

三、特殊消息(写在冒号后面,只能用下面这些格式)
- 语音:【语音秒数:语音内容】,如【语音12:刚下班】
- 表情包:【表情序号】,如【表情3】,序号只能从第六部分的列表里选。表情包单独一条消息。
- 列表里没有合适的表情:【表情:表情画面描述】
- 图片:【图片:画面描述】;只有 {{user}} 给过图片链接时,才写【图片:链接】
- 转账:【转账金额:备注】,如【转账18.00:馄饨钱】
- 收款:【收款金额】,如【收款18.00】
- 通话:【语音通话:状态】或【视频通话:状态】,如【语音通话:通话时长 12:08】【视频通话:对方未接听】
- 分享链接或推文:【链接:标题|摘要|来源】或【链接:标题|摘要|来源|配图url】
- 转发聊天记录:【转发:标题】,后面在同一行接每一条《发言人 时间:内容》,如【转发:{{char}}和周叙的聊天记录】《周叙 22:47:又不吃饭?》《{{char}} 22:50:有人陪我吃。》
- 引用回复:先正常写回复,末尾加【引用:被引用的人:原句】
- 撤回:「名字:【撤回:原本的内容】」,{{user}} 撤回也一样,写「我:【撤回:原本的内容】」。

四、独立行(不写名字,单独占一行)
- 时间分隔:【时间:昨天 23:14】
- 系统提示:【提示:“{{char}}”拍了拍你】

五、头像
如果 {{user}} 的用户设定里有【头像表】,就在 <pt> 的下一行,把这次小手机里会出现的人按「<av>名字=链接</av>」一人一行原样抄写。链接一个字符都不能改,名字必须和消息里写的完全一样({{user}} 写「我」)。没有头像表就不写这一行。

六、表情列表(只能用这些序号)
格式:序号:图上的内容|风格。
挑表情看两点:一是和这句话的情绪对得上;二是风格和角色性格对得上——高冷、正经的角色少发搞笑的,嘴硬或爱逗人的角色可以多发。
表情1:「闪亮登场」,橘白猫从帘子后面探出身子|搞笑
表情2:「拿豆橛子抽烂恁的腚」,橘猫举着一把豆角|搞笑
表情3:橘猫水汪汪的大眼睛含着泪,挂着鼻涕泡|可爱
表情4:「嚣张」,简笔小白人踢开门|搞笑
表情5:「很不高兴为你服务」,戴麦当劳帽和耳麦的绒毛小熊|搞笑
表情6:粉白小兔举着写「彳亍」(行)的牌子,表答应、好的、可以、勉强同意|可爱
表情7:小橘猫一脸懵,头顶转着加载圈,表反应不过来、没听懂、脑子转不动|可爱
表情8:「唯唯诺诺」,灰白猫缩着身子小心往前挪|搞笑
表情9:「Don't dell me what do do」,留胡子的印度大叔面无表情盯着镜头|搞笑
表情10:「可爱的猫猫」,看似是简笔猫猫举手,但实际是手指插到pussy里|色情且搞笑
表情11:「后荡后荡」(谐音 hold on),小狗站起来举着两只手向后退|搞笑
表情12:「你们两个!动作幅度大一点!屁股对准镜头!」,猫扶着摄像机当导演|搞笑微色情
表情13:海绵宝宝里的卡通鱼妈妈惊恐大叫,伸手捂住小孩的眼睛|搞笑
表情14:橘猫从背后死死勒住灰猫,灰猫张嘴挣扎,表强行抱抱、黏人不撒手、被抱得喘不过气|搞笑
表情15:「我忘光光了」,橘猫挠头|可爱
表情16:「你要我收款码不」,橘白猫捧着手机睁大眼睛|可爱又搞笑
表情17:线条小狗皱着眉、浑身发抖,表委屈、害怕、快哭了|可爱
表情18:「在干嘛 有没有想咪」,小奶猫歪头看镜头|可爱
表情19:「立马要了你」,QQ 企鹅瞪大眼睛|搞笑
表情20:线条小狗从黄色小被子里钻出来(动图)|可爱
表情21:橘猫瞪圆眼睛张大嘴,爪子抱着毯子,表震惊、不敢相信、被吓到|搞笑
表情22:「我拒绝」,猫用爪子推开另一只猫的脸|搞笑

七、示例(假设 {{user}} 有头像表)
<zzph>
<pt>{{char}}|对方正在输入…|23:14</pt>
<av>我=https://photos.251125.xyz/avatar/IMG_2805.jpeg</av>
【时间:昨天 23:14】
{{char}}:睡了吗?楼下那家馄饨店还开着。
我:还没,你又加班到现在?
{{char}}:【语音12:刚下班,路过的时候看见灯还亮着。】
我:【表情3】
{{char}}:【转账18.00:馄饨钱,不许退】
我:【收款18.00】
【提示:“{{char}}”拍了拍你】
{{char}}:嗯,今天值了。【引用:我:还没,你又加班到现在?】
{{char}}:【撤回:其实我在楼下等了半小时。】
我:【撤回:其实我也没睡】
我!:你到底什么意思?
【提示:消息已发出,但被对方拒收了。】
</zzph>

群聊示例:
<zzph>
<pt>相亲相爱一家人(4)||21:30</pt>
【群聊】
妈妈:周末都回家吃饭吗?
{{char}}:我回。
小林:我也回!
小林:【表情6】
我:我加班,不一定。
</zzph>

【朋友圈】
剧情里出现刷朋友圈、翻看某人的朋友圈时,在回复里插入一个朋友圈。正文里没提到就不生成。外层禁止被任何标签包裹。

格式如下:

<zzpm>
<pt>朋友圈主人|个性签名|时间</pt>
<pyq>
发布人|发布时间|位置
文案
【图片:画面描述】【图片:画面描述】
赞:名字,名字
评:名字:评论内容
评:名字回复名字:评论内容
</pyq>
</zzpm>

一、外壳
1. <zzpm> 和 </zzpm> 各占一行,必须成对出现。
2. <pt> 写在 <zzpm> 的下一行,格式是「朋友圈主人|个性签名|时间」,不能省略。
   - {{user}} 在刷自己的朋友圈(首页)时,主人写 {{user}};翻看某个人的朋友圈时,主人写那个人。
   - 个性签名可以空着,但两个竖线都要保留,例如 <pt>{{user}}||23:40</pt>。

二、每一条朋友圈
1. 每条用 <pyq> 和 </pyq> 包起来,各占一行。条与条之间不空行。
2. <pyq> 的下一行是抬头:「发布人|发布时间|位置」。位置可以不写,写成「发布人|发布时间」。
3. 抬头下面按顺序写:文案、配图、点赞、评论。没有的部分直接不写,不要写「无」。
4. 文案:可以写几行,每行一段。文案里不要用竖线「|」。
5. 配图:所有图片写在同一行,最多 9 张。格式和小手机一样:【图片:画面描述】;只有 {{user}} 给过图片链接时,才写【图片:链接】。
6. 点赞:一行,「赞:」后面写点赞的人,用「,」隔开。
7. 评论:每条评论单独一行,以「评:」开头。直接评论写「评:名字:内容」;回复别人写「评:名字回复名字:内容」。
8. 点赞和评论必须写在这一条的最后面。

三、名字
1. 朋友圈里 {{user}} 一律写 {{user}} 的名字(或昵称),不写「我」。
2. 所有名字里不要有空格和标点;同一个人在发布人、点赞、评论里的写法必须完全一样。

四、头像和背景
1. 如果 {{user}} 的用户设定里有【头像表】,就在 <pt> 的下一行,把这次朋友圈里会出现的人按「<av>名字=链接</av>」一人一行原样抄写。头像表里「我」那一行,在朋友圈里把名字换成 {{user}},链接不变。链接一个字符都不能改。
2. 如果 {{user}} 的用户设定里有【朋友圈背景】,而这次的朋友圈主人在里面,就在头像那几行后面写一行「<cv>主人名字=链接</cv>」。没有就不写。

第 4 步 玩家头像(可选)

想换头像的玩家,在自己的 用户设定 里加一张头像表。左边写名字,右边写图片链接,一人一行:

【头像表】
我=https://photos.251125.xyz/avatar/IMG_2805.jpeg
小林=https://图片链接/xiaolin.jpg

「我」就是玩家自己。也可以给卡里的角色、自己捏的 NPC 换头像。名字里不要有空格、冒号、感叹号和英文半角标点,汉字和中文标点可以,详见 给卡里的角色设默认头像。

没写进头像表的人:如果作者在全局 CSS 里设了默认头像,就用默认头像;都没有的话,会显示灰底加名字的第一个字。

朋友圈里玩家用自己的名字(或昵称),不叫「我」。AI 会自动把头像表里「我」那一行改成玩家的名字,玩家不用多写。没写头像表的玩家,朋友圈里显示灰底加名字的第一个字。

想给自己的朋友圈换背景,再加一张朋友圈背景表,写法一样,名字写自己的名字:

【朋友圈背景】
林夏=https://图片链接/cover.jpg
链接越短越好。AI 每次都要把链接原样抄一遍,链接越长越容易抄错。中文文件名会变成一长串 %E6%B2%88 这样的编码,尽量用英文短文件名,或者用短链。

检查效果

在正则页面打开 预览,把下面四段分别贴进「预览文本」。每加几条规则就看一次,最后四段都应该和说明一致。

① 完整测试应该显示成一个完整的手机,所有类型都有。手机外面的两行保持原样

他把手机扣在桌上,又拿起来。
char:这一行在手机外面,不应该变成气泡。
<zzph>
<pt>char|对方正在输入…|23:14</pt>
<av>我=https://photos.251125.xyz/avatar/IMG_2805.jpeg</av>

【时间:昨天 23:14】
char:睡了吗?楼下那家馄饨店还开着。
我:还没,你又加班到现在?
char:【语音12:刚下班,路过的时候看见灯还亮着。】
我:【语音4″:要,加辣。】
char:【表情:小狗点头】
我:【表情3】
char:【图片:一碗冒着热气的馄饨,旁边放着两只塑料勺】
我:【图片:https://picsum.photos/id/1060/320/240】
char:【转账18.00:馄饨钱,不许退】
我:【收款¥18.00】
【提示:“char”拍了拍你】
char:【转发:char和周叙的聊天记录】《周叙 22:47:你今天又不吃晚饭?》《char:等会儿有人陪我吃。》
char:【链接:深夜还开着的小店|凌晨一点的馄饨摊、二十四小时的旧书店。|城市夜读|https://picsum.photos/id/292/120/120】
我:【链接:@周叙:有些人吃个馄饨也要发朋友圈|评论区已沦陷。|推文】
char:【撤回:其实我在楼下等了半小时。】
我:【撤回:其实我看见了】
char:嗯,今天值了。【引用:我:还没,你又加班到现在?】
【时间:00:12】
char:【语音通话:通话时长 12:08】
我:【视频通话:对方未接听】
我!:你到底什么意思?读过《三体》吗
【提示:消息已发出,但被对方拒收了。】
char!:我错了,你接电话好不好
char!:【表情20】
</zzph>
他盯着屏幕,没再说话。
玩家消息里的【表情10】也要变图。

② 没有顶栏、表情序号超出范围照样显示成手机,顶栏是空的;【表情99】显示成一块灰色方块

<zzph>
char:没有顶栏也能显示。
我:【表情99】
</zzph>

③ 忘了写 </zzph>整段显示成原文,不会乱掉

<zzph>
<pt>char||23:14</pt>
char:这一个手机忘了写结尾。
我:那它应该整个显示成原文。

④ 群聊左边每条消息上方显示发言人的名字;去掉【群聊】那一行,名字就不显示

<zzph>
<pt>相亲相爱一家人(4)||21:30</pt>
【群聊】
【时间:21:30】
妈妈:周末都回家吃饭吗?
char:我回。
小林:我也回!【表情10】
我:我加班,不一定。
妈妈:【语音5:加什么班,回来】
</zzph>

⑤ 朋友圈:完整测试两个朋友圈:玩家自己刷的,和翻看 char 的。有多图、单图、4 张图、点赞、评论和回复

她靠在沙发上,随手点开了朋友圈。
<zzpm>
<pt>林夏||23:40</pt>
<av>林夏=https://photos.251125.xyz/avatar/IMG_2805.jpeg</av>
<pyq>
char|18分钟前|上海·静安区
加班到现在,楼下那家馄饨店居然还亮着灯。
【图片:https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=400&h=400&fit=crop】【图片:https://images.unsplash.com/photo-1470770841072-f978cf4d019e?w=400&h=400&fit=crop】【图片:便利店门口的猫,蹲在纸箱上不肯走】
赞:张三,林夏,李四
评:张三:又加班?
评:char回复张三:习惯了
评:林夏:下次带我一份,加辣【表情6】
</pyq>
<pyq>
张三|1小时前
今天终于把搬家的事情弄完了。
新家的窗户朝东,明天早上大概会被太阳晒醒。
【图片:新家的客厅,地上堆满纸箱,窗台上放着一盆绿萝】
赞:char
</pyq>
<pyq>
林夏|2小时前
谁能告诉我明天到底会不会下雨。
评:李四:天气预报说百分之六十
评:林夏回复李四:那就是不会
</pyq>
<pyq>
李四|昨天
【图片:https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=600】
</pyq>
</zzpm>
她盯着那张馄饨店的照片看了很久。
<zzpm>
<pt>char|不常更新,有事打电话。|09:12</pt>
<pyq>
char|3天前
周末回了一趟老家。
【图片:https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?w=400&h=400&fit=crop】【图片:院子里的柿子树,挂满了橙色的果子】【图片:https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=400&h=400&fit=crop】【图片:外婆做的一桌菜】
赞:林夏,张三
</pyq>
<pyq>
char|1月1日
新的一年,少喝咖啡。
</pyq>
</zzpm>

⑥ 朋友圈:空格子、很多赞和评论没图没赞的那条不显示评论框;没写位置时不留空行;背景换成 <cv> 里的图

<zzpm>
<pt>周叙|这个人很懒,什么都没写</pt>
<cv>周叙=https://images.unsplash.com/photo-1501785888041-af3ef285b470?w=800</cv>

<pyq>
周叙|刚刚|
只有一句话,没有图,没有赞。
</pyq>

<pyq>
周叙|5分钟前
【图片:凌晨的江边,路灯一盏一盏连到很远】
赞:甲,乙,丙,丁,戊,己,庚,辛,壬,癸,子丑寅卯,辰巳午未
评:甲:好看
评:乙:哪里
评:周叙回复乙:外滩
评:丙:凌晨还不睡
评:周叙回复丙:睡不着
评:丁:+1
</pyq>
</zzpm>

⑦ 朋友圈:故意写错没写 <pt>:外框套不上,但每一条照样显示;某一条没写抬头:只剩文案,前后不受影响

<zzpm>
<pyq>
char|刚刚
这一个朋友圈忘了写 pt:外框套不上,但这一条本身照样显示。
</pyq>
</zzpm>
<zzpm>
<pt>char||10:00</pt>
<pyq>
这一条忘了写抬头,没有头像和时间,只剩文案;外框和下一条不受影响。
</pyq>
<pyq>
char|刚刚
这一条是正常的。
</pyq>
</zzpm>

还没加完所有规则时,后面的规则管的那部分会暂时显示成原文,这是正常的。全部加完再看最终效果。

你需要改的东西

除了玩家头像,下面这些全都在你选用的那段小手机 CSS 里改(默认是第 1 步的通用版,其他风格在文末「其他样式」)。

换聊天背景

在 CSS 开头的色板里找到这一行:

--zzph-wall: none;

把 none 换成图片链接:

--zzph-wall: url("https://你的背景图.jpg");

背景图太花、字看不清的话,可以在链接前面加一层半透明白色,数字越大越白:

--zzph-wall: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.5)), url("https://你的背景图.jpg");

换颜色

色板在 CSS 最开头,改冒号后面的颜色值就行:

名字管什么
--zzph-frame手机外框、灵动岛、底部横条
--zzph-bg聊天区底色(没有背景图时看到的颜色)
--zzph-bar状态栏、顶栏、输入栏的底色
--zzph-text主要文字
--zzph-sub次要文字:时间、提示、名字
--zzph-line分隔线
--zzph-other对方的气泡、卡片底色
--zzph-me我的气泡底色
--zzph-me-text我的气泡文字
--zzph-av对方头像的底色(没图时显示)
--zzph-av-me我的头像底色
--zzph-tf转账卡片
--zzph-tf-done已收款卡片
--zzph-dot红色:未读点、未接来电、发送失败
--zzph-accent强调色:「重新编辑」、打开表情面板时的图标
--zzph-wall聊天背景图

朋友圈的颜色默认跟着上面的色板走,换了小手机的颜色,朋友圈也会变。想单独改的话,在朋友圈 CSS 开头改这几个:

名字管什么
--zzpm-page朋友圈页面底色,默认跟 --zzph-other 一样
--zzpm-box点赞评论框、「··」按钮的底色,默认跟 --zzph-bg 一样
--zzpm-name名字、位置、点赞人的颜色,默认跟 --zzph-accent 一样
--zzpm-cover没配背景图的人用的背景渐变

给卡里的角色设朋友圈背景

在朋友圈 CSS 末尾找到「朋友圈背景对照表」,一人写一行,名字的写法规则和头像一样:

.zzpm-cover.cv-char { background-image: url("https://背景图链接.jpg"); }

没设背景的人,用色板里的渐变。玩家在朋友圈背景表里写了同一个人的话,以玩家的为准。

给卡里的角色设默认头像

在 CSS 末尾找到「头像对照表」,照着示例一人写一行:

.zzph-av.av-char { background-image: url("https://头像链接.jpg"); color: transparent; }

点号后面的 av-char 里,名字要和 AI 消息里写的完全一样。玩家在头像表里写了同一个人的话,以玩家的为准。

AI 对同一个人的叫法可能不止一种,比如外国角色有时写中文名、有时写英文名。每种叫法都写一行,用同一个链接。

名字里能写什么:

加表情包

在 CSS 末尾的「表情对照表」里,接着最后一个序号往下加一行:

.zzph-sk-23 { background-image: url("https://表情图链接.png"); }

然后把表情对照表上面那条 nth-child(n + 23) 里的数字改成「表情总数 + 1」,比如现在是 22 个、写的是 23,加到 23 个就改成 24,面板里才会多显示一格。最多支持 60 个。

文件名以数字开头的图,App 上不显示。比如 …/emoji/177778366100279.jpeg。最好直接用 emoji23.png 这样字母开头的文件名。实在改不了名,就把斜杠后面的第一个数字换成「%3 + 这个数字」:…/emoji/%3177778366100279.jpeg(1 写成 %31,7 写成 %37)。打开还是同一张图,网页端也照常显示。头像链接也一样。

最后别忘了在第 3 步的输出设定里,把这个表情的意思加进表情列表。

换掉某个表情

改表情对照表里那一行的链接就行,序号不变,AI 也不用改。

玩家怎么发表情

点开小手机底部的输入栏会弹出表情面板,每个表情下面有序号。玩家在 Rubii 的输入框里打【表情3】,发出去就会变成图片,不用放在小手机里也行。

出问题了

整个小手机显示成一堆文字
先看 AI 有没有写结尾的 </zzph>,缺了的话整段都不处理。
某一条消息显示成带【】的原文
说明 AI 没按格式写,比如把【语音12:…】写成了【语音:12秒…】。只影响这一条,不影响其他消息。频繁出现的话,在输出设定里把那一类的例子写得更具体。
有的消息没有变成气泡,显示成「名字:内容」
多半是名字里有空格或标点(比如 Dr.Li),把角色名改成不带标点的写法。
头像显示成灰底加首字
头像表里的名字和消息里的名字不一致,或者链接抄错、图片失效。把链接粘到浏览器里打开看看。
表情显示成灰色方块
序号超出了表情对照表的范围,或者全局 CSS 还是旧版,没有这个表情。
手机被拆成好几块
检查第 01 条「清理空行」是否存在。如果 Rubii 不允许替换内容留空,就删掉这一条,在输出设定里强调「消息之间不空行」。
朋友圈显示成一堆文字
看 AI 有没有写结尾的 </zzpm>。如果每一条都正常、只是没有外框和背景,就是漏写了 <pt> 那一行。
朋友圈里某一条没有头像和时间
这一条的抬头「名字|时间」漏写了,或者名字里有空格、标点。
朋友圈的评论显示成「评:……」原文
评论里的名字带了空格或标点,或者少了一个冒号。正确写法是「评:名字:内容」「评:名字回复名字:内容」。
朋友圈的评论跑到了文案位置,没进灰底框
点赞和评论要写在这一条的最后面,后面不能再有文案或配图。
网页上正常,App 上不正常
见下面「App 上的情况」。

App 上的情况

已经在 iOS App 上确认:全局 CSS 能读到,正则生成的 <style> 会保留,玩家头像能正常显示。下面几项有所不同:

其他样式

第一次安装:选好样式,复制完整小手机 CSS,粘贴到 美化&正则 → 全局 CSS 的最后面;需要朋友圈时,再贴配套的朋友圈 CSS,然后回到第 2 步继续。

以后换样式:从目录直接来这里,把原来的小手机 CSS 整段替换成新样式。正则和输出设定继续沿用;朋友圈 CSS 已经装过就不用重复贴,颜色会自动跟着变。

换样式前:先备份你自己改过的角色头像、表情包、聊天背景和朋友圈背景设置,替换后再补回新 CSS 中。

通用版默认样式

清爽灰白与浅蓝气泡,适合日常聊天。

通用版 · 完整小手机 CSS

/* ===== 小手机 通用版 ===== 贴在全局 CSS 最后面 */
/* 色板:小手机 */
.zzph {
  --zzph-frame: #1c1c1e;
  --zzph-bg: #f2f2f5;
  --zzph-bar: #f8f8fa;
  --zzph-text: #1f1f24;
  --zzph-sub: #8a8a93;
  --zzph-line: #e2e2e8;
  --zzph-other: #ffffff;
  --zzph-me: #cfe4fa;
  --zzph-me-text: #16324f;
  --zzph-av: #b9c0cc;
  --zzph-av-me: #8fa8c8;
  --zzph-tf: #f0a04b;
  --zzph-tf-done: #f5c999;
  --zzph-dot: #e5484d;
  --zzph-accent: #4f6f9f;
  /* 聊天背景:none 表示不用图;换图就把 none 换成 url("图片链接") */
  --zzph-wall: none;
}
/* 外框 */
.zzph {
  width: 100%;
  max-width: 340px;
  margin: 8px auto;
  box-sizing: border-box;
  border: 8px solid var(--zzph-frame);
  border-radius: 36px;
  background: var(--zzph-bg);
  overflow: hidden;
  color: var(--zzph-text);
  font-family:
    -apple-system, "PingFang SC", "Helvetica Neue", "Microsoft YaHei",
    sans-serif;
  font-size: 14px;
  line-height: 1.5;
  text-align: left;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
/* text-shadow: none:Rubii 默认样式「文字阴影」在手机上会给正文加阴影。
   头像首字虽然设成透明,阴影还在,会在头像图上留下一个淡淡的字;手机里的文字也会发虚 */
.zzph,
.zzph * {
  box-sizing: border-box;
  text-shadow: none;
}
.zzph svg {
  display: inline-block;
  vertical-align: middle;
}
.zzph .rubii-default-quote {
  background: none;
  -webkit-text-fill-color: currentColor;
  filter: none;
  color: inherit;
  font-weight: inherit;
}
/* 状态栏:App 不会按外框圆角裁切里面的内容,所以最上、最下两块自己带圆角(36px 外框 - 8px 边框 = 28px) */
.zzph-status {
  border-radius: 28px 28px 0 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 32px;
  padding: 0 18px;
  background: var(--zzph-bar);
  font-size: 12px;
  font-weight: 600;
}
/* 左右两块等宽,岛才能居中。右边三个图标共 55px,加上间距要 70px,宽度不能再小 */
.zzph-clock {
  width: 72px;
}
.zzph-island {
  width: 78px;
  height: 20px;
  border-radius: 999px;
  background: var(--zzph-frame);
}
.zzph-sig {
  width: 72px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
/* flex-shrink: 0:放不下时也不许把图标压扁(App 会压,网页端不会) */
.zzph-sig svg {
  flex-shrink: 0;
  margin-left: 5px;
}
/* 顶栏 */
.zzph-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 46px;
  padding: 0 10px;
  background: var(--zzph-bar);
  border-bottom: 1px solid var(--zzph-line);
}
.zzph-head-side {
  width: 40px;
  display: flex;
  align-items: center;
}
.zzph-head-side.is-r {
  justify-content: flex-end;
}
.zzph-head-mid {
  width: 64%;
  text-align: center;
}
.zzph-title {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zzph-subtitle {
  font-size: 10px;
  line-height: 1.2;
  color: var(--zzph-sub);
}
/* 聊天区:App 正文不支持内部滚动,所以默认不限高度,手机随消息变长;网页端的固定高度写在下面 @supports 里 */
.zzph-body {
  background-image: var(--zzph-wall);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  padding: 12px 10px 6px;
  scrollbar-width: none;
}
.zzph-body::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.zzph-time {
  margin: 4px 0 10px;
  text-align: center;
}
.zzph-time span {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-tip {
  text-align: center;
  margin: 4px 0 10px;
}
.zzph-tip span {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 消息行:zzph-l 对方 / zzph-r 自己 */
.zzph-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
  animation: zzph-in 0.35s ease-out both;
}
.zzph-l {
  justify-content: flex-start;
}
.zzph-r {
  justify-content: flex-end;
}
@keyframes zzph-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.zzph-av {
  display: block;
  width: 36px;
  min-width: 36px;
  height: 36px;
  border-radius: 6px;
  background-color: var(--zzph-av);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  line-height: 36px;
  text-align: center;
  overflow: hidden;
  object-fit: cover;
}
.zzph-l .zzph-av {
  margin-right: 8px;
}
.zzph-r .zzph-av {
  margin-left: 8px;
  background-color: var(--zzph-av-me);
}
.zzph-col {
  max-width: 72%;
}
.zzph-r .zzph-col {
  text-align: right;
}
/* 左侧发言人名字:默认不显示,群聊时由【群聊】那一行打开 */
.zzph-name {
  display: none;
  font-size: 11px;
  line-height: 1.2;
  color: var(--zzph-sub);
  margin: 0 0 3px 2px;
}
/* 1 文字 */
.zzph-bub {
  display: inline-block;
  text-align: left;
  padding: 8px 11px;
  border-radius: 4px 10px 10px 10px;
  background: var(--zzph-other);
  color: var(--zzph-text);
  word-break: break-word;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
}
.zzph-r .zzph-bub {
  border-radius: 10px 4px 10px 10px;
  background: var(--zzph-me);
  color: var(--zzph-me-text);
}
/* 2 语音(点开转文字) */
.zzph-voice {
  display: inline-block;
  vertical-align: top;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.zzph-voice summary {
  display: block;
  list-style: none;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font-weight: normal;
  cursor: pointer;
}
.zzph-voice summary::-webkit-details-marker {
  display: none;
}
.zzph-voice summary::marker {
  content: "";
}
/* 语音条和红点并排;App 正文里图标和秒数要用 flex 才排得成一行 */
.zzph-vwrap {
  display: flex;
  align-items: flex-start;
}
.zzph-r .zzph-vwrap {
  justify-content: flex-end;
}
.zzph-voice .zzph-bub {
  display: flex;
  align-items: center;
  width: 78px;
}
.zzph-voice.is-m .zzph-bub {
  width: 120px;
}
.zzph-voice.is-l .zzph-bub {
  width: 170px;
}
.zzph-r .zzph-voice .zzph-bub {
  justify-content: flex-end;
}
.zzph-l .zzph-vic-r,
.zzph-r .zzph-vic-l,
.zzph-r .zzph-dot {
  display: none;
}
.zzph-voice-txt:empty {
  display: none;
}
.zzph-r .zzph-voice .zzph-bub svg {
  transform: rotate(180deg);
}
.zzph-sec {
  margin: 0 6px;
  font-size: 13px;
}
.zzph-voice-txt {
  margin-top: 4px;
  padding: 6px 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.75);
  font-size: 13px;
  color: var(--zzph-text);
  text-align: left;
}
.zzph-dot {
  display: inline-block;
  vertical-align: top;
  width: 7px;
  height: 7px;
  margin: 15px 0 0 6px;
  border-radius: 999px;
  background: var(--zzph-dot);
}
.zzph-voice[open] + .zzph-dot {
  display: none;
}
/* 3 表情包:图片版 / 文字版 */
.zzph-stk {
  display: inline-block;
  width: 110px;
  height: auto;
  border-radius: 6px;
}
.zzph-stk-txt {
  width: 100px;
  height: 100px;
  padding-top: 20px;
  border: 1px dashed #c9ccd4;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.6);
  color: var(--zzph-sub);
  font-size: 11px;
  line-height: 1.4;
  text-align: center;
}
.zzph-stk-txt div {
  margin-top: 6px;
  padding: 0 6px;
}
/* 3b 表情包:序号版(【表情3】→ 正则换成 <span class="zzph-sk zzph-sk-3"></span>,图在文件末尾的对照表里) */
.zzph-sk {
  display: inline-block;
  width: 110px;
  height: 110px;
  border-radius: 6px;
  background-color: #e4e7ee;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  vertical-align: top;
}
/* 4 图片:图片版 / 文字描述版 */
.zzph-img {
  display: inline-block;
  width: 160px;
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}
.zzph-pic {
  display: inline-block;
  width: 160px;
  min-height: 118px;
  padding: 22px 12px 12px;
  border-radius: 8px;
  background: linear-gradient(135deg, #e4e7ee, #c9d0dc);
  color: #5d6675;
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}
.zzph-pic-txt {
  margin-top: 6px;
}
/* 5 转账 */
.zzph-tf {
  display: inline-block;
  width: 210px;
  text-align: left;
  border-radius: 8px;
  background: var(--zzph-tf);
  color: #fff;
  overflow: hidden;
}
.zzph-tf.is-done {
  background: var(--zzph-tf-done);
}
.zzph-tf-main {
  display: flex;
  align-items: center;
  padding: 12px 12px 10px;
}
.zzph-tf-ic {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 34px;
  min-width: 34px;
  height: 34px;
  margin-right: 10px;
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
}
.zzph-tf-info {
  width: 140px;
}
.zzph-tf-amt {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}
.zzph-tf-note {
  font-size: 11px;
  opacity: 0.9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zzph-tf-foot {
  padding: 4px 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
  font-size: 10px;
  opacity: 0.9;
}
/* 6 转发的聊天记录(点开看全部) */
.zzph-fw {
  display: inline-block;
  width: 220px;
  vertical-align: top;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: var(--zzph-other);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
  text-align: left;
  overflow: hidden;
  color: var(--zzph-text);
}
.zzph-fw summary {
  display: block;
  list-style: none;
  margin: 0;
  padding: 10px 12px 0;
  border: none;
  background: none;
  color: inherit;
  font-weight: normal;
  cursor: pointer;
}
.zzph-fw summary::-webkit-details-marker {
  display: none;
}
.zzph-fw summary::marker {
  content: "";
}
.zzph-fw-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.zzph-fw-meta {
  margin-top: 2px;
  font-size: 12px;
  color: var(--zzph-sub);
}
.zzph-fw-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
  padding: 5px 0 6px;
  border-top: 1px solid var(--zzph-line);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-fw[open] .zzph-fw-arrow {
  transform: rotate(180deg);
}
.zzph-fw-list {
  padding: 0 12px 6px;
  border-top: 1px solid var(--zzph-line);
}
.zzph-fw-item {
  padding: 7px 0;
  border-bottom: 1px dashed var(--zzph-line);
  font-size: 12px;
  line-height: 1.5;
}
.zzph-fw-item:last-child {
  border-bottom: none;
}
.zzph-fw-who {
  display: block;
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 7 分享链接(推文 / 文章):有链接用 <a>,没有就用 <div> */
.zzph-link {
  display: inline-block;
  width: 230px;
  vertical-align: top;
  padding: 10px 12px 0;
  border-radius: 8px;
  background: var(--zzph-other);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
  text-align: left;
  overflow: hidden;
}
.zzph .zzph-link {
  color: var(--zzph-text);
  text-decoration: none;
}
.zzph-link-title {
  max-height: 2.8em;
  overflow: hidden;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.zzph-link-body {
  display: flex;
  align-items: flex-start;
  margin-top: 6px;
}
.zzph-link-desc {
  width: 148px;
  max-height: 4.5em;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.5;
  color: var(--zzph-sub);
}
.zzph-link-thumb {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 48px;
  min-width: 48px;
  height: 48px;
  margin-left: 10px;
  border-radius: 4px;
  background: #e4e7ee;
  color: #8f98a8;
  object-fit: cover;
}
.zzph-link-foot {
  display: flex;
  align-items: center;
  margin-top: 8px;
  padding: 5px 0 6px;
  border-top: 1px solid var(--zzph-line);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-link-foot svg {
  margin-right: 4px;
}
/* 8 撤回:点开可看原文 */
.zzph-recall .zzph-tip-act {
  margin-left: 4px;
  padding: 0;
  background: none;
  color: var(--zzph-accent);
}
.zzph-recall {
  display: block;
  margin: 4px 0 10px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
  text-align: center;
}
.zzph-recall summary {
  display: inline-block;
  list-style: none;
  margin: 0;
  padding: 2px 8px;
  border: none;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  color: var(--zzph-sub);
  font-size: 11px;
  font-weight: normal;
  cursor: pointer;
}
.zzph-recall summary::-webkit-details-marker {
  display: none;
}
.zzph-recall summary::marker {
  content: "";
}
.zzph-recall-txt {
  display: inline-block;
  max-width: 80%;
  margin-top: 5px;
  padding: 6px 10px;
  border: 1px dashed #c9ccd4;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--zzph-sub);
  font-size: 12px;
  line-height: 1.5;
  text-align: left;
}
.zzph-recall-tag {
  margin-right: 4px;
  color: var(--zzph-dot);
}
/* 9 引用回复:挂在气泡下面 */
.zzph-quote {
  margin-top: 4px;
}
.zzph-quote span {
  display: inline-block;
  max-width: 100%;
  max-height: 2.8em;
  overflow: hidden;
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.72);
  color: var(--zzph-sub);
  font-size: 12px;
  line-height: 1.4;
  text-align: left;
}
/* 10 通话记录:is-miss 未接 / 取消 */
.zzph-call {
  display: flex;
  align-items: center;
}
.zzph-call svg {
  margin: 0 6px 0 0;
}
.zzph-call-语音 .zzph-ic-video,
.zzph-call-视频 .zzph-ic-phone {
  display: none;
}
.zzph-call.is-miss {
  color: var(--zzph-dot);
}
/* 11 发送失败:感叹号放在气泡朝里的一侧(右侧消息在气泡左边,左侧消息在气泡右边) */
.zzph-fail {
  width: 18px;
  min-width: 18px;
  height: 18px;
  margin: 9px 6px 0 0;
  color: var(--zzph-dot);
}
.zzph-l .zzph-fail {
  margin: 9px 0 0 6px;
}
.zzph-fail svg {
  display: block;
}
/* 输入栏 */
.zzph-input {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 10px;
  background: var(--zzph-bar);
  border-top: 1px solid var(--zzph-line);
  color: #4a4a52;
}
.zzph-field {
  width: 62%;
  height: 32px;
  border-radius: 6px;
  background: #fff;
}
/* 12 表情面板:整条输入栏是 summary,点开在下方展开 */
.zzph-kb {
  display: block;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: var(--zzph-bar);
  box-shadow: none;
}
.zzph-kb > summary {
  list-style: none;
  margin: 0;
  font-weight: normal;
  cursor: pointer;
}
.zzph-kb > summary::-webkit-details-marker {
  display: none;
}
.zzph-kb > summary::marker {
  content: "";
}
.zzph-kb[open] .zzph-kb-emo {
  color: var(--zzph-accent);
}
.zzph-emo {
  padding: 8px 8px 2px;
  border-top: 1px solid var(--zzph-line);
}
.zzph-emo-head {
  padding: 0 4px 6px;
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 表情格子:App 上全部摊开;网页端限高两行半、在面板里滚动,写在下面 @supports 里 */
.zzph-emo-grid {
  font-size: 0;
  scrollbar-width: none;
}
.zzph-emo-grid::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.zzph-emo-item {
  display: inline-block;
  width: 25%;
  padding: 4px;
  vertical-align: top;
  text-align: center;
}
.zzph-emo-item .zzph-sk {
  display: block;
  width: 64px;
  height: 64px;
  margin: 0 auto;
}
.zzph-emo-no {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
/* 只给网页端:聊天区固定高度、在手机里滚动;面板打开时缩短聊天区,手机总高度不变(App 会忽略这一整段) */
@supports (display: block) {
  .zzph-body {
    max-height: 460px;
    overflow-y: auto;
  }
  .zzph-emo-grid {
    max-height: 168px;
    overflow-y: auto;
  }
  .zzph:has(.zzph-kb[open]) .zzph-body {
    max-height: 260px;
  }
}
.zzph-home {
  border-radius: 0 0 28px 28px;
  padding: 4px 0 8px;
  background: var(--zzph-bar);
}
.zzph-home div {
  width: 110px;
  height: 4px;
  margin: 0 auto;
  border-radius: 999px;
  background: var(--zzph-frame);
}

/* ===== 头像对照表:卡里自带角色的默认头像。照下面的格式一人一行,名字要和 AI 输出里的完全一样,如果一个人ai生成那个的名字可能不同(例如外国char)就把所有可能的名字都写一遍 ===== */
.zzph-av.av-char {
  background-image: url("https://photos.251125.xyz/avatar/IMG_2801.jpeg");
  color: transparent;
}
.zzph-av.av-我 {
  background-image: url("https://photos.251125.xyz/avatar/default.png");
  color: transparent;
}

/* ===== 表情对照表:加表情就在这里加一行,序号接着往下排 ===== */
/* 注意:App 上,文件名以数字开头的图片不显示。把文件名的第一个数字换成「%3+这个数字」就行,比如 /177.png 写成 /%3177.png(1 写成 %31,2 写成 %32……),还是同一张图 */
/* 面板里显示几个表情:把 23 改成「表情总数 + 1」。现在有 22 个表情,所以是 23 */
.zzph-emo-grid .zzph-emo-item:nth-child(n + 23) {
  display: none;
}
.zzph-sk-1 {
  background-image: url("https://photos.251125.xyz/emoji/emoji1.jpeg");
}
.zzph-sk-2 {
  background-image: url("https://photos.251125.xyz/emoji/emoji2.png");
}
.zzph-sk-3 {
  background-image: url("https://photos.251125.xyz/emoji/emoji3.png");
}
.zzph-sk-4 {
  background-image: url("https://photos.251125.xyz/emoji/emoji4.png");
}
.zzph-sk-5 {
  background-image: url("https://photos.251125.xyz/emoji/emoji5.jpeg");
}
.zzph-sk-6 {
  background-image: url("https://photos.251125.xyz/emoji/emoji6.jpeg");
}
.zzph-sk-7 {
  background-image: url("https://photos.251125.xyz/emoji/emoji7.jpeg");
}
.zzph-sk-8 {
  background-image: url("https://photos.251125.xyz/emoji/emoji8.jpeg");
}
.zzph-sk-9 {
  background-image: url("https://photos.251125.xyz/emoji/emoji9.png");
}
.zzph-sk-10 {
  background-image: url("https://photos.251125.xyz/emoji/emoji10.png");
}
.zzph-sk-11 {
  background-image: url("https://photos.251125.xyz/emoji/emoji11.png");
}
.zzph-sk-12 {
  background-image: url("https://photos.251125.xyz/emoji/emoji12.png");
}
.zzph-sk-13 {
  background-image: url("https://photos.251125.xyz/emoji/emoji13.png");
}
.zzph-sk-14 {
  background-image: url("https://photos.251125.xyz/emoji/emoji14.jpeg");
}
.zzph-sk-15 {
  background-image: url("https://photos.251125.xyz/emoji/emoji15.jpeg");
}
.zzph-sk-16 {
  background-image: url("https://photos.251125.xyz/emoji/emoji16.jpeg");
}
.zzph-sk-17 {
  background-image: url("https://photos.251125.xyz/emoji/emoji17.gif");
}
.zzph-sk-18 {
  background-image: url("https://photos.251125.xyz/emoji/emoji18.jpeg");
}
.zzph-sk-19 {
  background-image: url("https://photos.251125.xyz/emoji/emoji19.png");
}
.zzph-sk-20 {
  background-image: url("https://photos.251125.xyz/emoji/emoji20.gif");
}
.zzph-sk-21 {
  background-image: url("https://photos.251125.xyz/emoji/emoji21.jpg");
}
.zzph-sk-22 {
  background-image: url("https://photos.251125.xyz/emoji/emoji22.jpg");
}
配套朋友圈 CSS(通用,颜色自动跟随)

需要朋友圈时,把这段贴在本节的小手机 CSS 后面。

/* ===== 朋友圈 通用版 ===== 依赖「小手机 通用版.css」的外框和色板,贴在它后面 */
/* 色板:朋友圈(颜色都取自小手机色板。用玫瑰版或自己改过色板的,不用另做一份,直接把这段跟在小手机 CSS 后面,颜色会自动跟着变) */
.zzph {
  --zzpm-page: var(--zzph-other);
  --zzpm-box: var(--zzph-bg);
  --zzpm-name: var(--zzph-accent);
  /* 没有配背景图的人(下面对照表里没写、AI 也没写 <cv>),背景用这个渐变 */
  --zzpm-cover: linear-gradient(160deg, var(--zzph-av-me), var(--zzph-accent));
}
/* 朋友圈页面:App 不支持内部滚动,默认随内容变长;网页端的固定高度写在下面 @supports 里 */
.zzpm-body {
  background: var(--zzpm-page);
  scrollbar-width: none;
}
.zzpm-body::-webkit-scrollbar {
  width: 0;
  height: 0;
}
/* 封面容器完整容纳头像,父级放图片,资料行单独画底部页面色分界。 */
.zzpm-cover {
  height: 224px;
  padding: 160px 0 0;
  background-color: var(--zzph-av-me);
  background-image: var(--zzpm-cover);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.zzpm-profile {
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  height: 64px;
  padding: 0 14px;
  background-image: linear-gradient(to bottom, transparent 0px, transparent 40px, var(--zzpm-page) 40px, var(--zzpm-page) 64px);
}
.zzph .zzpm-owner {
  width: 160px;
  margin: 0 12px 0 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
  text-align: right;
  word-break: break-all;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.zzph-av.zzpm-owner-av {
  width: 64px;
  min-width: 64px;
  height: 64px;
  border-radius: 10px;
  font-size: 26px;
  line-height: 64px;
  box-shadow: 0 0 0 2px var(--zzpm-page);
}
.zzpm-sign {
  min-height: 16px;
  padding: 6px 14px 6px 50px;
  text-align: right;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
/* 每一条朋友圈 */
.zzpm-post {
  display: flex;
  align-items: flex-start;
  padding: 14px 12px;
  border-bottom: 1px solid var(--zzph-line);
  animation: zzph-in 0.35s ease-out both;
}
.zzph-av.zzpm-av {
  width: 40px;
  min-width: 40px;
  height: 40px;
  margin-right: 10px;
  line-height: 40px;
}
/* App 正文里 flex:1 无效,先给固定百分比;网页端在 @supports 里改成 flex:1 */
.zzpm-main {
  width: 82%;
}
.zzpm-name {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--zzpm-name);
}
.zzpm-text {
  margin: 3px 0 6px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  word-break: break-word;
}
/* 配图:沿用小手机的【图片】规则(zzph-img / zzph-pic),在朋友圈里改成 72px 的九宫格;只有一张时自动放大 */
.zzpm-pics {
  margin-top: 8px;
  font-size: 0;
}
.zzpm-pics.is-4 {
  width: 156px;
}
.zzpm-pics .zzph-img,
.zzpm-pics .zzph-pic {
  display: inline-block;
  vertical-align: top;
  width: 72px;
  max-width: none;
  height: 72px;
  min-height: 0;
  margin: 0 4px 4px 0;
  border-radius: 4px;
  object-fit: cover;
}
/* 文字描述版配图 */
.zzpm-pics .zzph-pic {
  padding: 7px 6px;
  overflow: hidden;
  font-size: 10px;
  line-height: 1.35;
}
.zzpm-pics .zzph-pic svg {
  display: block;
  width: 16px;
  height: 16px;
  margin: 0 auto 3px;
}
.zzpm-pics .zzph-pic-txt {
  margin-top: 0;
  font-size: 9px;
}
.zzpm-pics > .zzph-img:only-child {
  width: auto;
  height: auto;
  max-width: 170px;
  max-height: 210px;
}
.zzpm-pics > .zzph-pic:only-child {
  width: 150px;
  height: auto;
  min-height: 112px;
  padding: 18px 12px 12px;
  font-size: 12px;
  line-height: 1.5;
}
.zzpm-pics > .zzph-pic:only-child svg {
  width: 26px;
  height: 26px;
  margin-bottom: 6px;
}
.zzpm-pics > .zzph-pic:only-child .zzph-pic-txt {
  font-size: 11px;
}
/* 文案、评论里的序号表情包缩小一点 */
.zzpm-post .zzph-sk {
  width: 56px;
  height: 56px;
}
/* 位置:没写位置时整行不占地方 */
.zzpm-loc {
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzpm-name);
}
.zzpm-loc:empty {
  display: none;
}
/* 时间行采用 AD 分组,长时间允许换行。删除文字仅在输入已有该字段时显示。 */
.zzpm-meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
.zzpm-meta-left {
  display: flex;
  align-items: flex-start;
  width: 82%;
}
.zzpm-time {
  display: block;
  max-width: 70%;
  word-break: break-word;
}
.zzpm-delete {
  display: block;
  width: 28px;
  margin-left: 10px;
  color: var(--zzpm-name);
  white-space: nowrap;
}
.zzpm-delete:empty {
  display: none;
}
.zzpm-more {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  min-width: 30px;
  height: 20px;
  border-radius: 4px;
  background: var(--zzpm-box);
  color: var(--zzpm-name);
}
.zzpm-more svg,
.zzpm-more circle {
  fill: var(--zzpm-name);
}
/* 点赞 + 评论区:上方的小三角是用边框画的。padding-top 的 1px 不能删,没有它三角的负 margin 会和外层合并,三角就缩回去了 */
.zzpm-box {
  margin-top: 10px;
  padding: 1px 9px 4px;
  border-radius: 4px;
  background: var(--zzpm-box);
  font-size: 13px;
  line-height: 1.5;
}
.zzpm-box::before {
  content: "";
  display: block;
  width: 0;
  height: 0;
  margin: -7px 0 3px 3px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid var(--zzpm-box);
}
/* 没人点赞也没人评论时,整个框不显示 */
.zzpm-box:empty {
  display: none;
}
.zzpm-likes {
  display: flex;
  align-items: flex-start;
  padding: 1px 0 3px;
  color: var(--zzpm-name);
  font-weight: 600;
  word-break: break-word;
}
.zzpm-likes svg {
  display: block;
  width: 14px;
  min-width: 14px;
  height: 14px;
  margin: 3px 5px 0 0;
  stroke: var(--zzpm-name);
}
.zzpm-likes path {
  stroke: var(--zzpm-name);
}
.zzpm-like-names {
  display: block;
  width: 88%;
  color: var(--zzpm-name);
  font-size: 13px;
  line-height: 1.5;
  word-break: break-word;
}
.zzpm-cmt {
  padding: 1px 0;
  word-break: break-word;
}
/* 既有点赞又有评论时,中间加一条分隔线 */
.zzpm-likes + .zzpm-cmt {
  margin: 0 -9px;
  padding: 4px 9px 1px;
  border-top: 1px solid var(--zzph-line);
}
.zzpm-who {
  color: var(--zzpm-name);
  font-weight: 600;
}
.zzpm-rp {
  margin: 0 2px;
}
/* 只给网页端:朋友圈固定高度、在手机里滚动;正文区用 flex:1 撑满(App 会忽略这一整段) */
@supports (display: block) {
  .zzpm-body {
    max-height: 520px;
    overflow-y: auto;
  }
  .zzpm-main {
    width: auto;
    flex: 1;
    min-width: 0;
  }
}

/* ===== 朋友圈背景对照表:卡里自带角色的默认背景。一人一行,名字要和 AI 输出里的完全一样 ===== */
/* 玩家自己的背景不写在这里:让 AI 在朋友圈里写 <cv>名字=链接</cv>。都没有的人用上面色板里的渐变 */
.zzpm-cover.cv-char {
  background-image: url("https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800");
}

回到第 2 步 →

玫瑰版

酒红外框、奶油底色,搭配玫瑰背景。

玫瑰版 · 完整小手机 CSS

/* ===== 小手机 玫瑰版 ===== 贴在全局 CSS 最后面 */
/* 色板:玫瑰(配红玫瑰 + 奶油底 + 暖金光的背景图) */
.zzph {
  --zzph-frame: #5a1a22; /* 外框:酒红 */
  --zzph-bg: #f6ece2; /* 没有背景图时的聊天底色:奶油 */
  --zzph-bar: #fbf4ec; /* 状态栏、顶栏、输入栏:象牙白 */
  --zzph-text: #3b2323;
  --zzph-sub: #a3837a;
  --zzph-line: #ecdccf;
  --zzph-other: #fffaf5; /* 对方气泡:暖白 */
  --zzph-me: #9e2a36; /* 我的气泡:玫瑰红 */
  --zzph-me-text: #fff4ea;
  --zzph-av: #d8bcae;
  --zzph-av-me: #b9838b;
  --zzph-tf: #c4925a; /* 转账:香槟金 */
  --zzph-tf-done: #e2c8a4;
  --zzph-dot: #c42a3b;
  --zzph-accent: #a8323f;
  /* 聊天背景:把「背景图链接」换成图片地址。前面那层半透明奶油色是为了让字看得清,数字越大越淡 */
  --zzph-wall:
    linear-gradient(rgba(251, 244, 236, 0.1), rgba(251, 244, 236, 0.1)),
    url("https://photos.251125.xyz/bg/Red%20Roses%20%26%20White%20Butterflies.jpeg");
}
/* 外框 */
.zzph {
  width: 100%;
  max-width: 340px;
  margin: 8px auto;
  box-sizing: border-box;
  border: 8px solid var(--zzph-frame);
  border-radius: 36px;
  background: var(--zzph-bg);
  overflow: hidden;
  color: var(--zzph-text);
  font-family:
    -apple-system, "PingFang SC", "Helvetica Neue", "Microsoft YaHei",
    sans-serif;
  font-size: 14px;
  line-height: 1.5;
  text-align: left;
  box-shadow: 0 10px 30px rgba(90, 26, 34, 0.28);
}
/* text-shadow: none:Rubii 默认样式「文字阴影」在手机上会给正文加阴影。
   头像首字虽然设成透明,阴影还在,会在头像图上留下一个淡淡的字;手机里的文字也会发虚 */
.zzph,
.zzph * {
  box-sizing: border-box;
  text-shadow: none;
}
.zzph svg {
  display: inline-block;
  vertical-align: middle;
}
.zzph .rubii-default-quote {
  background: none;
  -webkit-text-fill-color: currentColor;
  filter: none;
  color: inherit;
  font-weight: inherit;
}
/* 状态栏:App 不会按外框圆角裁切里面的内容,所以最上、最下两块自己带圆角(36px 外框 - 8px 边框 = 28px) */
.zzph-status {
  border-radius: 28px 28px 0 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 32px;
  padding: 0 18px;
  background: var(--zzph-bar);
  font-size: 12px;
  font-weight: 600;
}
/* 左右两块等宽,岛才能居中。右边三个图标共 55px,加上间距要 70px,宽度不能再小 */
.zzph-clock {
  width: 72px;
}
.zzph-island {
  width: 78px;
  height: 20px;
  border-radius: 999px;
  background: var(--zzph-frame);
}
.zzph-sig {
  width: 72px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
/* flex-shrink: 0:放不下时也不许把图标压扁(App 会压,网页端不会) */
.zzph-sig svg {
  flex-shrink: 0;
  margin-left: 5px;
}
/* 顶栏 */
.zzph-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 46px;
  padding: 0 10px;
  background: var(--zzph-bar);
  border-bottom: 1px solid var(--zzph-line);
}
.zzph-head-side {
  width: 40px;
  display: flex;
  align-items: center;
}
.zzph-head-side.is-r {
  justify-content: flex-end;
}
.zzph-head-mid {
  width: 64%;
  text-align: center;
}
.zzph-title {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zzph-subtitle {
  font-size: 10px;
  line-height: 1.2;
  color: var(--zzph-sub);
}
/* 聊天区:App 正文不支持内部滚动,所以默认不限高度,手机随消息变长;网页端的固定高度写在下面 @supports 里 */
.zzph-body {
  background-image: var(--zzph-wall);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  padding: 12px 10px 6px;
  scrollbar-width: none;
}
.zzph-body::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.zzph-time {
  margin: 4px 0 10px;
  text-align: center;
}
.zzph-time span {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 4px;
  background: rgba(251, 244, 236, 0.82);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-tip {
  text-align: center;
  margin: 4px 0 10px;
}
.zzph-tip span {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  background: rgba(251, 244, 236, 0.82);
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 消息行:zzph-l 对方 / zzph-r 自己 */
.zzph-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
  animation: zzph-in 0.35s ease-out both;
}
.zzph-l {
  justify-content: flex-start;
}
.zzph-r {
  justify-content: flex-end;
}
@keyframes zzph-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.zzph-av {
  display: block;
  width: 36px;
  min-width: 36px;
  height: 36px;
  border-radius: 6px;
  background-color: var(--zzph-av);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  line-height: 36px;
  text-align: center;
  overflow: hidden;
  object-fit: cover;
}
.zzph-l .zzph-av {
  margin-right: 8px;
}
.zzph-r .zzph-av {
  margin-left: 8px;
  background-color: var(--zzph-av-me);
}
.zzph-col {
  max-width: 72%;
}
.zzph-r .zzph-col {
  text-align: right;
}
/* 左侧发言人名字:默认不显示,群聊时由【群聊】那一行打开 */
.zzph-name {
  display: none;
  font-size: 11px;
  line-height: 1.2;
  color: var(--zzph-sub);
  margin: 0 0 3px 2px;
}
/* 1 文字 */
.zzph-bub {
  display: inline-block;
  text-align: left;
  padding: 8px 11px;
  border-radius: 4px 10px 10px 10px;
  background: var(--zzph-other);
  color: var(--zzph-text);
  word-break: break-word;
  box-shadow: 0 1px 1px rgba(110, 40, 40, 0.08);
}
.zzph-r .zzph-bub {
  border-radius: 10px 4px 10px 10px;
  background: var(--zzph-me);
  color: var(--zzph-me-text);
}
/* 2 语音(点开转文字) */
.zzph-voice {
  display: inline-block;
  vertical-align: top;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.zzph-voice summary {
  display: block;
  list-style: none;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font-weight: normal;
  cursor: pointer;
}
.zzph-voice summary::-webkit-details-marker {
  display: none;
}
.zzph-voice summary::marker {
  content: "";
}
/* 语音条和红点并排;App 正文里图标和秒数要用 flex 才排得成一行 */
.zzph-vwrap {
  display: flex;
  align-items: flex-start;
}
.zzph-r .zzph-vwrap {
  justify-content: flex-end;
}
.zzph-voice .zzph-bub {
  display: flex;
  align-items: center;
  width: 78px;
}
.zzph-voice.is-m .zzph-bub {
  width: 120px;
}
.zzph-voice.is-l .zzph-bub {
  width: 170px;
}
.zzph-r .zzph-voice .zzph-bub {
  justify-content: flex-end;
}
.zzph-l .zzph-vic-r,
.zzph-r .zzph-vic-l,
.zzph-r .zzph-dot {
  display: none;
}
.zzph-voice-txt:empty {
  display: none;
}
.zzph-r .zzph-voice .zzph-bub svg {
  transform: rotate(180deg);
}
.zzph-sec {
  margin: 0 6px;
  font-size: 13px;
}
.zzph-voice-txt {
  margin-top: 4px;
  padding: 6px 10px;
  border-radius: 8px;
  background: rgba(251, 244, 236, 0.85);
  font-size: 13px;
  color: var(--zzph-text);
  text-align: left;
}
.zzph-dot {
  display: inline-block;
  vertical-align: top;
  width: 7px;
  height: 7px;
  margin: 15px 0 0 6px;
  border-radius: 999px;
  background: var(--zzph-dot);
}
.zzph-voice[open] + .zzph-dot {
  display: none;
}
/* 3 表情包:图片版 / 文字版 */
.zzph-stk {
  display: inline-block;
  width: 110px;
  height: auto;
  border-radius: 6px;
}
.zzph-stk-txt {
  width: 100px;
  height: 100px;
  padding-top: 20px;
  border: 1px dashed #dcc3b4;
  border-radius: 12px;
  background: rgba(255, 250, 245, 0.88);
  color: var(--zzph-sub);
  font-size: 11px;
  line-height: 1.4;
  text-align: center;
}
.zzph-stk-txt div {
  margin-top: 6px;
  padding: 0 6px;
}
/* 3b 表情包:序号版(【表情3】→ 正则换成 <span class="zzph-sk zzph-sk-3"></span>,图在文件末尾的对照表里) */
.zzph-sk {
  display: inline-block;
  width: 110px;
  height: 110px;
  border-radius: 6px;
  background-color: #efe2d6;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  vertical-align: top;
}
/* 4 图片:图片版 / 文字描述版 */
.zzph-img {
  display: inline-block;
  width: 160px;
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}
.zzph-pic {
  display: inline-block;
  width: 160px;
  min-height: 118px;
  padding: 22px 12px 12px;
  border-radius: 8px;
  background: linear-gradient(135deg, #f3e6da, #e2cbbb);
  color: #8a5a52;
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}
.zzph-pic-txt {
  margin-top: 6px;
}
/* 5 转账 */
.zzph-tf {
  display: inline-block;
  width: 210px;
  text-align: left;
  border-radius: 8px;
  background: var(--zzph-tf);
  color: #fff;
  overflow: hidden;
}
.zzph-tf.is-done {
  background: var(--zzph-tf-done);
}
.zzph-tf-main {
  display: flex;
  align-items: center;
  padding: 12px 12px 10px;
}
.zzph-tf-ic {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 34px;
  min-width: 34px;
  height: 34px;
  margin-right: 10px;
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
}
.zzph-tf-info {
  width: 140px;
}
.zzph-tf-amt {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}
.zzph-tf-note {
  font-size: 11px;
  opacity: 0.9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zzph-tf-foot {
  padding: 4px 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
  font-size: 10px;
  opacity: 0.9;
}
/* 6 转发的聊天记录(点开看全部) */
.zzph-fw {
  display: inline-block;
  width: 220px;
  vertical-align: top;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: var(--zzph-other);
  box-shadow: 0 1px 1px rgba(110, 40, 40, 0.08);
  text-align: left;
  overflow: hidden;
  color: var(--zzph-text);
}
.zzph-fw summary {
  display: block;
  list-style: none;
  margin: 0;
  padding: 10px 12px 0;
  border: none;
  background: none;
  color: inherit;
  font-weight: normal;
  cursor: pointer;
}
.zzph-fw summary::-webkit-details-marker {
  display: none;
}
.zzph-fw summary::marker {
  content: "";
}
.zzph-fw-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.zzph-fw-meta {
  margin-top: 2px;
  font-size: 12px;
  color: var(--zzph-sub);
}
.zzph-fw-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
  padding: 5px 0 6px;
  border-top: 1px solid var(--zzph-line);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-fw[open] .zzph-fw-arrow {
  transform: rotate(180deg);
}
.zzph-fw-list {
  padding: 0 12px 6px;
  border-top: 1px solid var(--zzph-line);
}
.zzph-fw-item {
  padding: 7px 0;
  border-bottom: 1px dashed var(--zzph-line);
  font-size: 12px;
  line-height: 1.5;
}
.zzph-fw-item:last-child {
  border-bottom: none;
}
.zzph-fw-who {
  display: block;
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 7 分享链接(推文 / 文章):有链接用 <a>,没有就用 <div> */
.zzph-link {
  display: inline-block;
  width: 230px;
  vertical-align: top;
  padding: 10px 12px 0;
  border-radius: 8px;
  background: var(--zzph-other);
  box-shadow: 0 1px 1px rgba(110, 40, 40, 0.08);
  text-align: left;
  overflow: hidden;
}
.zzph .zzph-link {
  color: var(--zzph-text);
  text-decoration: none;
}
.zzph-link-title {
  max-height: 2.8em;
  overflow: hidden;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.zzph-link-body {
  display: flex;
  align-items: flex-start;
  margin-top: 6px;
}
.zzph-link-desc {
  width: 148px;
  max-height: 4.5em;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.5;
  color: var(--zzph-sub);
}
.zzph-link-thumb {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 48px;
  min-width: 48px;
  height: 48px;
  margin-left: 10px;
  border-radius: 4px;
  background: #efe2d6;
  color: #b08f82;
  object-fit: cover;
}
.zzph-link-foot {
  display: flex;
  align-items: center;
  margin-top: 8px;
  padding: 5px 0 6px;
  border-top: 1px solid var(--zzph-line);
  font-size: 11px;
  color: var(--zzph-sub);
}
.zzph-link-foot svg {
  margin-right: 4px;
}
/* 8 撤回:点开可看原文 */
.zzph-recall .zzph-tip-act {
  margin-left: 4px;
  padding: 0;
  background: none;
  color: var(--zzph-accent);
}
.zzph-recall {
  display: block;
  margin: 4px 0 10px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
  text-align: center;
}
.zzph-recall summary {
  display: inline-block;
  list-style: none;
  margin: 0;
  padding: 2px 8px;
  border: none;
  border-radius: 4px;
  background: rgba(251, 244, 236, 0.82);
  color: var(--zzph-sub);
  font-size: 11px;
  font-weight: normal;
  cursor: pointer;
}
.zzph-recall summary::-webkit-details-marker {
  display: none;
}
.zzph-recall summary::marker {
  content: "";
}
.zzph-recall-txt {
  display: inline-block;
  max-width: 80%;
  margin-top: 5px;
  padding: 6px 10px;
  border: 1px dashed #dcc3b4;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--zzph-sub);
  font-size: 12px;
  line-height: 1.5;
  text-align: left;
}
.zzph-recall-tag {
  margin-right: 4px;
  color: var(--zzph-dot);
}
/* 9 引用回复:挂在气泡下面 */
.zzph-quote {
  margin-top: 4px;
}
.zzph-quote span {
  display: inline-block;
  max-width: 100%;
  max-height: 2.8em;
  overflow: hidden;
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(251, 244, 236, 0.82);
  color: var(--zzph-sub);
  font-size: 12px;
  line-height: 1.4;
  text-align: left;
}
/* 10 通话记录:is-miss 未接 / 取消 */
.zzph-call {
  display: flex;
  align-items: center;
}
.zzph-call svg {
  margin: 0 6px 0 0;
}
.zzph-call-语音 .zzph-ic-video,
.zzph-call-视频 .zzph-ic-phone {
  display: none;
}
.zzph-call.is-miss {
  color: var(--zzph-dot);
}
/* 玫瑰版:我的气泡本身是红色,未接来电的红字会看不见,改用浅色 */
.zzph-r .zzph-call.is-miss {
  color: #ffd9cf;
}
/* 11 发送失败:感叹号放在气泡朝里的一侧(右侧消息在气泡左边,左侧消息在气泡右边) */
.zzph-fail {
  width: 18px;
  min-width: 18px;
  height: 18px;
  margin: 9px 6px 0 0;
  color: var(--zzph-dot);
}
.zzph-l .zzph-fail {
  margin: 9px 0 0 6px;
}
.zzph-fail svg {
  display: block;
}
/* 输入栏 */
.zzph-input {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 10px;
  background: var(--zzph-bar);
  border-top: 1px solid var(--zzph-line);
  color: #6b3a3a;
}
.zzph-field {
  width: 62%;
  height: 32px;
  border-radius: 6px;
  background: #fffaf5;
}
/* 12 表情面板:整条输入栏是 summary,点开在下方展开 */
.zzph-kb {
  display: block;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: var(--zzph-bar);
  box-shadow: none;
}
.zzph-kb > summary {
  list-style: none;
  margin: 0;
  font-weight: normal;
  cursor: pointer;
}
.zzph-kb > summary::-webkit-details-marker {
  display: none;
}
.zzph-kb > summary::marker {
  content: "";
}
.zzph-kb[open] .zzph-kb-emo {
  color: var(--zzph-accent);
}
.zzph-emo {
  padding: 8px 8px 2px;
  border-top: 1px solid var(--zzph-line);
}
.zzph-emo-head {
  padding: 0 4px 6px;
  font-size: 11px;
  color: var(--zzph-sub);
}
/* 表情格子:App 上全部摊开;网页端限高两行半、在面板里滚动,写在下面 @supports 里 */
.zzph-emo-grid {
  font-size: 0;
  scrollbar-width: none;
}
.zzph-emo-grid::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.zzph-emo-item {
  display: inline-block;
  width: 25%;
  padding: 4px;
  vertical-align: top;
  text-align: center;
}
.zzph-emo-item .zzph-sk {
  display: block;
  width: 64px;
  height: 64px;
  margin: 0 auto;
}
.zzph-emo-no {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
/* 只给网页端:聊天区固定高度、在手机里滚动;面板打开时缩短聊天区,手机总高度不变(App 会忽略这一整段) */
@supports (display: block) {
  .zzph-body {
    max-height: 460px;
    overflow-y: auto;
  }
  .zzph-emo-grid {
    max-height: 168px;
    overflow-y: auto;
  }
  .zzph:has(.zzph-kb[open]) .zzph-body {
    max-height: 260px;
  }
}
.zzph-home {
  border-radius: 0 0 28px 28px;
  padding: 4px 0 8px;
  background: var(--zzph-bar);
}
.zzph-home div {
  width: 110px;
  height: 4px;
  margin: 0 auto;
  border-radius: 999px;
  background: var(--zzph-frame);
}

/* ===== 头像对照表:卡里自带角色的默认头像。照下面的格式一人一行,名字要和 AI 输出里的完全一样,如果一个人ai生成那个的名字可能不同(例如外国char)就把所有可能的名字都写一遍 ===== */
.zzph-av.av-char {
  background-image: url("https://photos.251125.xyz/avatar/IMG_2801.jpeg");
  color: transparent;
}
.zzph-av.av-我 {
  background-image: url("https://photos.251125.xyz/avatar/default.png");
  color: transparent;
}

/* ===== 表情对照表:加表情就在这里加一行,序号接着往下排 ===== */
/* 注意:App 上,文件名以数字开头的图片不显示。把文件名的第一个数字换成「%3+这个数字」就行,比如 /177.png 写成 /%3177.png(1 写成 %31,2 写成 %32……),还是同一张图 */
/* 面板里显示几个表情:把 23 改成「表情总数 + 1」。现在有 22 个表情,所以是 23 */
.zzph-emo-grid .zzph-emo-item:nth-child(n + 23) {
  display: none;
}
.zzph-sk-1 {
  background-image: url("https://photos.251125.xyz/emoji/emoji1.jpeg");
}
.zzph-sk-2 {
  background-image: url("https://photos.251125.xyz/emoji/emoji2.png");
}
.zzph-sk-3 {
  background-image: url("https://photos.251125.xyz/emoji/emoji3.png");
}
.zzph-sk-4 {
  background-image: url("https://photos.251125.xyz/emoji/emoji4.png");
}
.zzph-sk-5 {
  background-image: url("https://photos.251125.xyz/emoji/emoji5.jpeg");
}
.zzph-sk-6 {
  background-image: url("https://photos.251125.xyz/emoji/emoji6.jpeg");
}
.zzph-sk-7 {
  background-image: url("https://photos.251125.xyz/emoji/emoji7.jpeg");
}
.zzph-sk-8 {
  background-image: url("https://photos.251125.xyz/emoji/emoji8.jpeg");
}
.zzph-sk-9 {
  background-image: url("https://photos.251125.xyz/emoji/emoji9.png");
}
.zzph-sk-10 {
  background-image: url("https://photos.251125.xyz/emoji/emoji10.png");
}
.zzph-sk-11 {
  background-image: url("https://photos.251125.xyz/emoji/emoji11.png");
}
.zzph-sk-12 {
  background-image: url("https://photos.251125.xyz/emoji/emoji12.png");
}
.zzph-sk-13 {
  background-image: url("https://photos.251125.xyz/emoji/emoji13.png");
}
.zzph-sk-14 {
  background-image: url("https://photos.251125.xyz/emoji/emoji14.jpeg");
}
.zzph-sk-15 {
  background-image: url("https://photos.251125.xyz/emoji/emoji15.jpeg");
}
.zzph-sk-16 {
  background-image: url("https://photos.251125.xyz/emoji/emoji16.jpeg");
}
.zzph-sk-17 {
  background-image: url("https://photos.251125.xyz/emoji/emoji17.gif");
}
.zzph-sk-18 {
  background-image: url("https://photos.251125.xyz/emoji/emoji18.jpeg");
}
.zzph-sk-19 {
  background-image: url("https://photos.251125.xyz/emoji/emoji19.png");
}
.zzph-sk-20 {
  background-image: url("https://photos.251125.xyz/emoji/emoji20.gif");
}
.zzph-sk-21 {
  background-image: url("https://photos.251125.xyz/emoji/emoji21.jpg");
}
.zzph-sk-22 {
  background-image: url("https://photos.251125.xyz/emoji/emoji22.jpg");
}
配套朋友圈 CSS(通用,颜色自动跟随)

需要朋友圈时,把这段贴在本节的小手机 CSS 后面。

/* ===== 朋友圈 通用版 ===== 依赖「小手机 通用版.css」的外框和色板,贴在它后面 */
/* 色板:朋友圈(颜色都取自小手机色板。用玫瑰版或自己改过色板的,不用另做一份,直接把这段跟在小手机 CSS 后面,颜色会自动跟着变) */
.zzph {
  --zzpm-page: var(--zzph-other);
  --zzpm-box: var(--zzph-bg);
  --zzpm-name: var(--zzph-accent);
  /* 没有配背景图的人(下面对照表里没写、AI 也没写 <cv>),背景用这个渐变 */
  --zzpm-cover: linear-gradient(160deg, var(--zzph-av-me), var(--zzph-accent));
}
/* 朋友圈页面:App 不支持内部滚动,默认随内容变长;网页端的固定高度写在下面 @supports 里 */
.zzpm-body {
  background: var(--zzpm-page);
  scrollbar-width: none;
}
.zzpm-body::-webkit-scrollbar {
  width: 0;
  height: 0;
}
/* 封面容器完整容纳头像,父级放图片,资料行单独画底部页面色分界。 */
.zzpm-cover {
  height: 224px;
  padding: 160px 0 0;
  background-color: var(--zzph-av-me);
  background-image: var(--zzpm-cover);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.zzpm-profile {
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  height: 64px;
  padding: 0 14px;
  background-image: linear-gradient(to bottom, transparent 0px, transparent 40px, var(--zzpm-page) 40px, var(--zzpm-page) 64px);
}
.zzph .zzpm-owner {
  width: 160px;
  margin: 0 12px 0 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
  text-align: right;
  word-break: break-all;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.zzph-av.zzpm-owner-av {
  width: 64px;
  min-width: 64px;
  height: 64px;
  border-radius: 10px;
  font-size: 26px;
  line-height: 64px;
  box-shadow: 0 0 0 2px var(--zzpm-page);
}
.zzpm-sign {
  min-height: 16px;
  padding: 6px 14px 6px 50px;
  text-align: right;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
/* 每一条朋友圈 */
.zzpm-post {
  display: flex;
  align-items: flex-start;
  padding: 14px 12px;
  border-bottom: 1px solid var(--zzph-line);
  animation: zzph-in 0.35s ease-out both;
}
.zzph-av.zzpm-av {
  width: 40px;
  min-width: 40px;
  height: 40px;
  margin-right: 10px;
  line-height: 40px;
}
/* App 正文里 flex:1 无效,先给固定百分比;网页端在 @supports 里改成 flex:1 */
.zzpm-main {
  width: 82%;
}
.zzpm-name {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--zzpm-name);
}
.zzpm-text {
  margin: 3px 0 6px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  word-break: break-word;
}
/* 配图:沿用小手机的【图片】规则(zzph-img / zzph-pic),在朋友圈里改成 72px 的九宫格;只有一张时自动放大 */
.zzpm-pics {
  margin-top: 8px;
  font-size: 0;
}
.zzpm-pics.is-4 {
  width: 156px;
}
.zzpm-pics .zzph-img,
.zzpm-pics .zzph-pic {
  display: inline-block;
  vertical-align: top;
  width: 72px;
  max-width: none;
  height: 72px;
  min-height: 0;
  margin: 0 4px 4px 0;
  border-radius: 4px;
  object-fit: cover;
}
/* 文字描述版配图 */
.zzpm-pics .zzph-pic {
  padding: 7px 6px;
  overflow: hidden;
  font-size: 10px;
  line-height: 1.35;
}
.zzpm-pics .zzph-pic svg {
  display: block;
  width: 16px;
  height: 16px;
  margin: 0 auto 3px;
}
.zzpm-pics .zzph-pic-txt {
  margin-top: 0;
  font-size: 9px;
}
.zzpm-pics > .zzph-img:only-child {
  width: auto;
  height: auto;
  max-width: 170px;
  max-height: 210px;
}
.zzpm-pics > .zzph-pic:only-child {
  width: 150px;
  height: auto;
  min-height: 112px;
  padding: 18px 12px 12px;
  font-size: 12px;
  line-height: 1.5;
}
.zzpm-pics > .zzph-pic:only-child svg {
  width: 26px;
  height: 26px;
  margin-bottom: 6px;
}
.zzpm-pics > .zzph-pic:only-child .zzph-pic-txt {
  font-size: 11px;
}
/* 文案、评论里的序号表情包缩小一点 */
.zzpm-post .zzph-sk {
  width: 56px;
  height: 56px;
}
/* 位置:没写位置时整行不占地方 */
.zzpm-loc {
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzpm-name);
}
.zzpm-loc:empty {
  display: none;
}
/* 时间行采用 AD 分组,长时间允许换行。删除文字仅在输入已有该字段时显示。 */
.zzpm-meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--zzph-sub);
}
.zzpm-meta-left {
  display: flex;
  align-items: flex-start;
  width: 82%;
}
.zzpm-time {
  display: block;
  max-width: 70%;
  word-break: break-word;
}
.zzpm-delete {
  display: block;
  width: 28px;
  margin-left: 10px;
  color: var(--zzpm-name);
  white-space: nowrap;
}
.zzpm-delete:empty {
  display: none;
}
.zzpm-more {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  min-width: 30px;
  height: 20px;
  border-radius: 4px;
  background: var(--zzpm-box);
  color: var(--zzpm-name);
}
.zzpm-more svg,
.zzpm-more circle {
  fill: var(--zzpm-name);
}
/* 点赞 + 评论区:上方的小三角是用边框画的。padding-top 的 1px 不能删,没有它三角的负 margin 会和外层合并,三角就缩回去了 */
.zzpm-box {
  margin-top: 10px;
  padding: 1px 9px 4px;
  border-radius: 4px;
  background: var(--zzpm-box);
  font-size: 13px;
  line-height: 1.5;
}
.zzpm-box::before {
  content: "";
  display: block;
  width: 0;
  height: 0;
  margin: -7px 0 3px 3px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid var(--zzpm-box);
}
/* 没人点赞也没人评论时,整个框不显示 */
.zzpm-box:empty {
  display: none;
}
.zzpm-likes {
  display: flex;
  align-items: flex-start;
  padding: 1px 0 3px;
  color: var(--zzpm-name);
  font-weight: 600;
  word-break: break-word;
}
.zzpm-likes svg {
  display: block;
  width: 14px;
  min-width: 14px;
  height: 14px;
  margin: 3px 5px 0 0;
  stroke: var(--zzpm-name);
}
.zzpm-likes path {
  stroke: var(--zzpm-name);
}
.zzpm-like-names {
  display: block;
  width: 88%;
  color: var(--zzpm-name);
  font-size: 13px;
  line-height: 1.5;
  word-break: break-word;
}
.zzpm-cmt {
  padding: 1px 0;
  word-break: break-word;
}
/* 既有点赞又有评论时,中间加一条分隔线 */
.zzpm-likes + .zzpm-cmt {
  margin: 0 -9px;
  padding: 4px 9px 1px;
  border-top: 1px solid var(--zzph-line);
}
.zzpm-who {
  color: var(--zzpm-name);
  font-weight: 600;
}
.zzpm-rp {
  margin: 0 2px;
}
/* 只给网页端:朋友圈固定高度、在手机里滚动;正文区用 flex:1 撑满(App 会忽略这一整段) */
@supports (display: block) {
  .zzpm-body {
    max-height: 520px;
    overflow-y: auto;
  }
  .zzpm-main {
    width: auto;
    flex: 1;
    min-width: 0;
  }
}

/* ===== 朋友圈背景对照表:卡里自带角色的默认背景。一人一行,名字要和 AI 输出里的完全一样 ===== */
/* 玩家自己的背景不写在这里:让 AI 在朋友圈里写 <cv>名字=链接</cv>。都没有的人用上面色板里的渐变 */
.zzpm-cover.cv-char {
  background-image: url("https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800");
}

回到第 2 步 →