产品方案 PPT 是交付物,之前只存在于本机,换开发机后会丢,所以入库。 - 3 份 pptx:智能测肤方案(正版 1.3MB / 深色版 1.3MB)+ 购物小程序方案模版(0.1MB); 模版是 build_taobao_proposal_from_template.py 的输入,必须一起入库 - 3 个生成脚本:把硬编码的 D:\juzi\... 改为相对仓库根(Path(__file__).parents[1]), 渲染用的截图素材 temp/ppt_assets 属临时产物,加进 .gitignore - build_taobao_proposal_pptx.py 是更早的一版(产物 AI智能测肤...pptx 当前不在仓库), 保留用于追溯版式 - 新增 .gitignore:/sdk-java-35479221/(淘宝开放平台自动生成的 Java SDK, 对应已废弃的 AppKey 35479221,当前架构走 HTTP 透传,不引 SDK)
401 lines
19 KiB
Python
401 lines
19 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Clone 淘宝购物小程序方案模板 -> AI智能测肤淘宝小程序产品方案(不出现公司名)。
|
||
|
||
模板设计语言(继承):
|
||
- 画布 26.67x15in;封面/致谢 FF5500->3768E2 渐变(原样保留)
|
||
- 章节页:白底 + DIN Condensed 120pt 大数字 + FF6F00 橙色标题(Heiti SC Light)
|
||
- 目录页:FF644E 珊瑚红圆圈编号(accent5),原样保留
|
||
新增元素仅使用:ORANGE 标题 / CORAL 强调 / 黑灰正文 / 浅灰卡片,保证视觉一致。
|
||
截图统一裁掉顶部 220px 导航栏(去除品牌名与微信胶囊按钮)。
|
||
"""
|
||
import copy
|
||
from pathlib import Path
|
||
|
||
from pptx import Presentation
|
||
from pptx.util import Inches, Pt
|
||
from pptx.dml.color import RGBColor
|
||
from pptx.enum.shapes import MSO_SHAPE
|
||
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
|
||
from pptx.oxml.ns import qn
|
||
|
||
# 路径相对仓库根,换机器无需改(截图素材在 temp/ppt_assets,属于本地临时产物,不入库)
|
||
_ROOT = Path(__file__).resolve().parents[1]
|
||
TPL = str(_ROOT / "购物小程序方案-模版.pptx")
|
||
OUT = str(_ROOT / "智能测肤-淘宝小程序产品方案.pptx")
|
||
AST = str(_ROOT / "temp" / "ppt_assets")
|
||
|
||
ORANGE = RGBColor(0xFF, 0x6F, 0x00)
|
||
CORAL = RGBColor(0xFF, 0x64, 0x4E)
|
||
INK = RGBColor(0x1A, 0x1A, 0x1A)
|
||
GREY = RGBColor(0x5E, 0x5E, 0x5E)
|
||
LGREY = RGBColor(0xD5, 0xD5, 0xD5)
|
||
CARD = RGBColor(0xF7, 0xF7, 0xF7)
|
||
BAND = RGBColor(0xF2, 0xF2, 0xF2)
|
||
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
|
||
|
||
NUM_F = "DIN Condensed" # 与模板大数字一致(缺失时由查看端统一替换)
|
||
|
||
|
||
# ---------- 基础设施 ----------
|
||
def set_font(run, size, bold=False, color=INK, latin="Helvetica Neue", ea="微软雅黑"):
|
||
f = run.font
|
||
f.size = Pt(size)
|
||
f.bold = bold
|
||
f.color.rgb = color
|
||
f.name = latin
|
||
rPr = run._r.get_or_add_rPr()
|
||
for tag, face in ((qn("a:latin"), latin), (qn("a:ea"), ea)):
|
||
e = rPr.find(tag)
|
||
if e is None:
|
||
e = rPr.makeelement(tag, {})
|
||
rPr.append(e)
|
||
e.set("typeface", face)
|
||
|
||
|
||
def tb(slide, x, y, w, h, paras, anchor=MSO_ANCHOR.TOP):
|
||
"""paras: list of dict(t,size,bold,color,latin,ea,sa,align)"""
|
||
box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
|
||
tf = box.text_frame
|
||
tf.word_wrap = True
|
||
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
|
||
tf.vertical_anchor = anchor
|
||
for i, pd in enumerate(paras):
|
||
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
|
||
p.alignment = pd.get("align", PP_ALIGN.LEFT)
|
||
if pd.get("sa"):
|
||
p.space_after = Pt(pd["sa"])
|
||
r = p.add_run()
|
||
r.text = pd["t"]
|
||
set_font(r, pd.get("size", 26), pd.get("bold", False), pd.get("color", INK),
|
||
pd.get("latin", "Helvetica Neue"), pd.get("ea", "微软雅黑"))
|
||
return box
|
||
|
||
|
||
def card(slide, x, y, w, h, fill=CARD, line=LGREY):
|
||
sp = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
|
||
sp.adjustments[0] = 0.055
|
||
sp.fill.solid()
|
||
sp.fill.fore_color.rgb = fill
|
||
if line:
|
||
sp.line.color.rgb = line
|
||
sp.line.width = Pt(1)
|
||
else:
|
||
sp.line.fill.background()
|
||
sp.shadow.inherit = False
|
||
return sp
|
||
|
||
|
||
def band(slide, x, y, w, h, fill=BAND):
|
||
sp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
|
||
sp.fill.solid()
|
||
sp.fill.fore_color.rgb = fill
|
||
sp.line.fill.background()
|
||
sp.shadow.inherit = False
|
||
return sp
|
||
|
||
|
||
def circle(slide, x, y, d, label, fill=CORAL, color=WHITE, size=26, latin=NUM_F):
|
||
sp = slide.shapes.add_shape(MSO_SHAPE.OVAL, Inches(x), Inches(y), Inches(d), Inches(d))
|
||
sp.fill.solid()
|
||
sp.fill.fore_color.rgb = fill
|
||
sp.line.fill.background()
|
||
sp.shadow.inherit = False
|
||
tf = sp.text_frame
|
||
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
|
||
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
|
||
p = tf.paragraphs[0]
|
||
p.alignment = PP_ALIGN.CENTER
|
||
r = p.add_run()
|
||
r.text = label
|
||
set_font(r, size, True, color, latin, "微软雅黑")
|
||
return sp
|
||
|
||
|
||
def pic(slide, path, x, y, w, h):
|
||
p = slide.shapes.add_picture(path, Inches(x), Inches(y), Inches(w), Inches(h))
|
||
p.line.color.rgb = LGREY
|
||
p.line.width = Pt(1)
|
||
return p
|
||
|
||
|
||
def find(slide, needle):
|
||
for sh in slide.shapes:
|
||
if sh.has_text_frame and needle in sh.text_frame.text:
|
||
return sh
|
||
raise KeyError(needle)
|
||
|
||
|
||
def drop(shape):
|
||
shape._element.getparent().remove(shape._element)
|
||
|
||
|
||
def replace_text(shape, new, widen=None):
|
||
tf = shape.text_frame
|
||
for p in tf.paragraphs[1:]:
|
||
p._p.getparent().remove(p._p)
|
||
p = tf.paragraphs[0]
|
||
runs = p.runs
|
||
runs[0].text = new
|
||
for r in runs[1:]:
|
||
r._r.getparent().remove(r._r)
|
||
if widen:
|
||
shape.width = Inches(widen)
|
||
|
||
|
||
def clone_slide(prs, src):
|
||
new = prs.slides.add_slide(src.slide_layout)
|
||
spTree = new.shapes._spTree
|
||
for el in list(spTree):
|
||
if el.tag.split("}")[-1] in ("sp", "pic", "graphicFrame", "grpSp", "cxnSp"):
|
||
spTree.remove(el)
|
||
for shp in src.shapes:
|
||
spTree.append(copy.deepcopy(shp._element))
|
||
return new
|
||
|
||
|
||
def move_slide(prs, from_idx, to_idx):
|
||
lst = prs.slides._sldIdLst
|
||
el = list(lst)[from_idx]
|
||
lst.remove(el)
|
||
lst.insert(to_idx, el)
|
||
|
||
|
||
# ---------- 构建 ----------
|
||
def build():
|
||
prs = Presentation(TPL)
|
||
s_cover, s_pos, s_toc, s_mkt, s_val, s_biz, s_thx = prs.slides
|
||
|
||
# 第 02 章需要 3 页:克隆「小程序方案及价值」两份
|
||
feat = clone_slide(prs, s_val) # 功能与链路(配截图)
|
||
diff = clone_slide(prs, s_val) # 差异与互补
|
||
# 顺序 -> [封面,定位,目录,01,02价值,02功能,02差异,03,致谢]
|
||
move_slide(prs, 7, 5)
|
||
move_slide(prs, 8, 6)
|
||
|
||
# 大数字框在字体替换后过窄导致竖排换行+顶部裁切:删除模板框,原位重画宽框数字
|
||
for sl, num in ((s_mkt, "01"), (s_val, "02"), (feat, "02"), (diff, "02"), (s_biz, "03")):
|
||
for sh in list(sl.shapes):
|
||
if sh.has_text_frame and sh.text_frame.text.strip() == num:
|
||
drop(sh)
|
||
break
|
||
tb(sl, 0.51, 0.24, 3.2, 1.9, [dict(t=num, size=120, color=INK, latin=NUM_F)])
|
||
# 字体替换后数字变宽,章节标题统一右移让出间距
|
||
for sl, keys in ((s_mkt, ["市场调研分析"]), (s_val, ["小程序方案及价值"]),
|
||
(feat, ["小程序方案及价值"]), (diff, ["小程序方案及价值"]),
|
||
(s_biz, ["商业化运营规划及目标"])):
|
||
for k in keys:
|
||
find(sl, k).left = Inches(2.75)
|
||
|
||
# ---- P1 封面 ----
|
||
replace_text(find(s_cover, "XXXX小程序方案"), "AI智能测肤小程序方案")
|
||
comp = find(s_cover, "XXX公司")
|
||
replace_text(comp, "西安巨子生物基因技术股份有限公司", widen=17)
|
||
comp.text_frame.paragraphs[0].runs[0].font.size = Pt(64)
|
||
comp.text_frame.word_wrap = False
|
||
tb(s_cover, 7.6, 10.8, 14, 0.55,
|
||
[dict(t="淘宝开放平台小程序产品方案 · 自研类型申请", size=26, color=WHITE)])
|
||
|
||
# ---- P2 公司背景与产品定位 ----
|
||
ttl = find(s_pos, "公司背景介绍")
|
||
replace_text(ttl, "公司背景与产品定位")
|
||
ttl.width = Inches(8.0)
|
||
tb(s_pos, 10.31, 3.2, 15.5, 0.5,
|
||
[dict(t="西安巨子生物基因技术股份有限公司 · 港交所上市 · 重组胶原蛋白", size=22, color=GREY)])
|
||
drop(find(s_pos, "请一页提炼"))
|
||
# 左:完整报告长图(已裁导航栏)
|
||
pic(s_pos, f"{AST}\\report-full.png", 2.7, 2.45, 3.34, 10.29)
|
||
tb(s_pos, 1.4, 12.95, 6.0, 0.5,
|
||
[dict(t="AI 肌肤检测报告(界面示意)", size=24, color=GREY, align=PP_ALIGN.CENTER)])
|
||
# 右:一句话定位 + 三条价值
|
||
tb(s_pos, 8.1, 4.7, 16.4, 2.1,
|
||
[dict(t="让每位消费者三分钟获得", size=40, bold=True, sa=6),
|
||
dict(t="一份可信赖的肌肤报告与护理方案", size=40, bold=True)],
|
||
anchor=MSO_ANCHOR.TOP)
|
||
rows = [
|
||
("1", "测得准", "AI 图像分析输出综合评分、肌龄、七项分项与三维指标,可解释、可回看"),
|
||
("2", "推得对", "按展示肌龄分档推荐适配精华,报告页直达商品,缩短决策路径"),
|
||
("3", "留得住", "历史报告沉淀与复访提醒,支撑会员运营与复购"),
|
||
]
|
||
for i, (n, lead, desc) in enumerate(rows):
|
||
y = 7.5 + i * 2.0
|
||
circle(s_pos, 8.1, y + 0.12, 0.72, n, size=28)
|
||
tb(s_pos, 9.3, y, 15.3, 1.8,
|
||
[dict(t=lead, size=30, bold=True, sa=6),
|
||
dict(t=desc, size=24, color=GREY)])
|
||
|
||
# ---- P3 目录:模板即为目标结构,保留 ----
|
||
|
||
# ---- P4 01 市场调研分析 ----
|
||
drop(find(s_mkt, "商家价值和痛点"))
|
||
cols = [
|
||
("商家痛点", "选品讲解靠经验,「适不适合我」难讲清;直播与详情页流量难沉淀为可复访的服务。"),
|
||
("消费者诉求", "想先弄清肤质与肌龄再决策;怕踩雷、要依据,希望报告能看懂、直接告诉我买什么。"),
|
||
]
|
||
xs = [1.5, 9.72, 17.94]
|
||
for i, (t, body) in enumerate(cols):
|
||
tb(s_mkt, xs[i], 2.6, 7.2, 0.6, [dict(t=t, size=32, bold=True, color=ORANGE)])
|
||
tb(s_mkt, xs[i], 3.45, 7.2, 4.4, [dict(t=body, size=26, color=GREY)])
|
||
tb(s_mkt, xs[2], 2.6, 7.2, 0.6, [dict(t="市场与商业化空间", size=32, bold=True, color=ORANGE)])
|
||
tb(s_mkt, xs[2], 3.45, 7.2, 1.0, [dict(t="4357亿", size=54, bold=True, color=ORANGE, latin=NUM_F)])
|
||
tb(s_mkt, xs[2], 4.5, 7.2, 0.5, [dict(t="2024 年全国化妆品类零售额", size=22, color=GREY)])
|
||
tb(s_mkt, xs[2], 5.35, 7.2, 1.0, [dict(t="1069亿", size=54, bold=True, color=CORAL, latin=NUM_F)])
|
||
tb(s_mkt, xs[2], 6.4, 7.2, 0.5, [dict(t="抗衰护肤品细分市场规模(2024)", size=22, color=GREY)])
|
||
tb(s_mkt, xs[2], 7.15, 7.2, 1.5,
|
||
[dict(t="高客单、高复购;线上「可解释的决策工具」仍是缺口", size=24, color=GREY)])
|
||
# 需求原声
|
||
tb(s_mkt, 1.5, 9.55, 10, 0.5, [dict(t="需求原声", size=24, bold=True, color=GREY)])
|
||
band(s_mkt, 0, 10.25, 26.67, 2.25)
|
||
quotes = ["「不知道自己适不适合这款抗老精华」", "「想先测一下再买,别乱试」", "「报告要能看懂,最好直接告诉我买什么」"]
|
||
for i, q in enumerate(quotes):
|
||
tb(s_mkt, 1.5 + i * 8.6, 10.25, 8.2, 2.25,
|
||
[dict(t=q, size=26, bold=True)], anchor=MSO_ANCHOR.MIDDLE)
|
||
tb(s_mkt, 1.5, 12.9, 24, 0.5,
|
||
[dict(t="数据来源:国家统计局社会消费品零售总额(化妆品类,2024);智研咨询《2024 年中国抗衰老行业研究》",
|
||
size=22, color=GREY)])
|
||
|
||
# ---- P5 02 方案与价值 ----
|
||
drop(find(s_val, "产品价值和商业价值"))
|
||
tb(s_val, 1.5, 2.55, 11.5, 0.6, [dict(t="产品价值与商业价值", size=32, bold=True, color=ORANGE)])
|
||
vals = [
|
||
("检测可信", "AI 图像分析替代主观猜测,输出可解释的检测报告"),
|
||
("决策提效", "报告直达适配商品,缩短「浏览—下单」路径,提升转化与客单匹配"),
|
||
("服务资产", "历史报告沉淀,支撑复访召回、换季关怀与复购运营"),
|
||
]
|
||
for i, (lead, desc) in enumerate(vals):
|
||
y = 3.45 + i * 1.95
|
||
sq = s_val.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(1.5), Inches(y + 0.16), Inches(0.26), Inches(0.26))
|
||
sq.fill.solid(); sq.fill.fore_color.rgb = CORAL; sq.line.fill.background(); sq.shadow.inherit = False
|
||
tb(s_val, 2.1, y, 10.6, 1.7,
|
||
[dict(t=lead, size=30, bold=True, sa=6), dict(t=desc, size=24, color=GREY)])
|
||
tb(s_val, 14.2, 2.55, 11, 0.6, [dict(t="适用行业与运用场景", size=32, bold=True, color=ORANGE)])
|
||
chips = [("护肤", 14.2, 3.5), ("功效型美妆", 19.3, 3.5), ("抗老精华", 14.2, 4.55), ("品牌会员中心", 19.3, 4.55)]
|
||
for t, cx, cy in chips:
|
||
sp = card(s_val, cx, cy, 4.7, 0.85, fill=WHITE, line=CORAL)
|
||
tf = sp.text_frame
|
||
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
|
||
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
|
||
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
|
||
r = p.add_run(); r.text = t
|
||
set_font(r, 26, False, CORAL)
|
||
scenes = ["· 店铺首页服务入口", "· 商品详情页挂载", "· 直播间互动测肤", "· 会员日与换季活动"]
|
||
tb(s_val, 14.2, 5.95, 11, 3.4,
|
||
[dict(t=s, size=26, sa=14) for s in scenes])
|
||
band(s_val, 0, 10.1, 26.67, 2.8)
|
||
tb(s_val, 1.5, 10.4, 10, 0.5, [dict(t="商业价值", size=24, bold=True, color=GREY)])
|
||
biz = [("提升转化", "把不确定变成可解释的购买理由"),
|
||
("优化客单", "按肌龄匹配商品,减少试错退货"),
|
||
("沉淀会员", "报告资产驱动复访与复购")]
|
||
for i, (t, d) in enumerate(biz):
|
||
x = 1.5 + i * 8.6
|
||
tb(s_val, x, 11.1, 7.8, 1.5,
|
||
[dict(t=t, size=28, bold=True, sa=6), dict(t=d, size=22, color=GREY)])
|
||
|
||
# ---- P6 02 产品核心功能与链路(配截图) ----
|
||
replace_text(find(feat, "小程序方案及价值"), "产品核心功能与链路", widen=9.5)
|
||
drop(find(feat, "产品价值和商业价值"))
|
||
feats = [
|
||
("01", "授权登录", "淘宝账号授权,协议确认后进入服务"),
|
||
("02", "基础档案", "出生年份、地区、肤质,一次填写本地缓存"),
|
||
("03", "三步拍摄", "正脸 / 左脸 / 右脸拍摄或相册选图"),
|
||
("04", "AI 检测报告", "综合评分、肌龄、七项分项与三维指标"),
|
||
("05", "护理与推荐", "护理关注选三,按肌龄推荐适配精华"),
|
||
("06", "历史报告", "最近多份完整报告,可回看对比"),
|
||
]
|
||
for i, (n, t, d) in enumerate(feats):
|
||
y = 2.35 + i * 1.12
|
||
circle(feat, 1.5, y + 0.06, 0.6, n, size=22)
|
||
tb(feat, 2.4, y, 9.9, 1.05,
|
||
[dict(t=t, size=28, bold=True, sa=3), dict(t=d, size=22, color=GREY)])
|
||
phones = [("phone-profile.png", "基础档案"), ("phone-camera.png", "正面拍摄引导"), ("phone-report.png", "AI 检测报告")]
|
||
for i, (f, cap) in enumerate(phones):
|
||
x = 13.3 + i * 3.85
|
||
pic(feat, f"{AST}\\{f}", x, 2.3, 3.3, 6.48)
|
||
tb(feat, x, 8.95, 3.3, 0.5, [dict(t=cap, size=24, color=GREY, align=PP_ALIGN.CENTER)])
|
||
steps = ["启动授权", "档案填写", "三步拍摄", "生成报告", "护理推荐", "商品转化"]
|
||
for i, st in enumerate(steps):
|
||
x = 2.1 + i * 3.9
|
||
circle(feat, x + 1.1, 10.3, 0.8, str(i + 1), size=24)
|
||
tb(feat, x, 11.3, 3.0, 0.5, [dict(t=st, size=24, bold=True, align=PP_ALIGN.CENTER)])
|
||
if i < len(steps) - 1:
|
||
tb(feat, x + 2.95, 10.42, 0.9, 0.6,
|
||
[dict(t="→", size=30, bold=True, color=GREY, align=PP_ALIGN.CENTER)])
|
||
tb(feat, 1.5, 12.35, 24.5, 1.6,
|
||
[dict(t="七项分析:轮廓紧致 · 皱纹细纹 · 肤色色素 · 平滑细腻 · 水分水润 · 敏感泛红 · 痘痘皮损", size=22, color=GREY, sa=6),
|
||
dict(t="三维指标:紧塑力 / 活力感 / 稳定力,支撑综合评分与展示肌龄", size=22, color=GREY, sa=6),
|
||
dict(t="推荐逻辑:按展示肌龄分档匹配精华组别,报告页可跳转商品详情", size=22, color=GREY)])
|
||
|
||
# ---- P7 02 与平台现有能力的差异与互补 ----
|
||
replace_text(find(diff, "小程序方案及价值"), "与平台现有能力的差异与互补", widen=10.5)
|
||
drop(find(diff, "产品价值和商业价值"))
|
||
heads = [("对比维度", 1.4, 4.6), ("平台现有货架与内容", 6.2, 9.8), ("本小程序互补价值", 16.2, 9.8)]
|
||
for t, x, w in heads:
|
||
tb(diff, x, 2.7, w, 0.6, [dict(t=t, size=28, bold=True, color=CORAL)])
|
||
table = [
|
||
("决策依据", "以图文、评价与直播讲解为主", "基于本人面部数据生成可解释报告"),
|
||
("选品方式", "用户自行对比商品与参数", "按肌龄与肤质状态主动匹配商品"),
|
||
("服务形态", "偏一次性浏览与成交", "报告沉淀可回看,支撑复访复购"),
|
||
("商家价值", "流量与成交工具丰富", "新增「专业测肤」信任入口,提升转化"),
|
||
]
|
||
for i, (lab, a, b) in enumerate(table):
|
||
y = 3.85 + i * 2.1
|
||
tb(diff, 1.4, y + 0.55, 4.6, 0.7, [dict(t=lab, size=28, bold=True)])
|
||
for txt, x in ((a, 6.2), (b, 16.2)):
|
||
card(diff, x, y, 9.8, 1.9, fill=CARD if x == 6.2 else WHITE,
|
||
line=LGREY if x == 6.2 else CORAL)
|
||
tb(diff, x + 0.45, y + 0.35, 8.9, 1.3,
|
||
[dict(t=txt, size=26, color=GREY if x == 6.2 else INK)],
|
||
anchor=MSO_ANCHOR.MIDDLE)
|
||
tb(diff, 1.4, 12.65, 24, 0.8,
|
||
[dict(t="「不做货架的替代,补足『专业解释 → 信任 → 决策』的服务缺口」", size=30, bold=True, color=ORANGE)])
|
||
|
||
# ---- P8 03 商业化运营规划及目标 ----
|
||
replace_text(find(s_biz, "商业化运营规划及目标"), "商业化运营规划及目标")
|
||
drop(find(s_biz, "目标覆盖商家数"))
|
||
tb(s_biz, 2.75, 1.78, 14, 0.5, [dict(t="自研类型申请 · 西安巨子生物 · 首期服务自有旗舰店", size=22, color=GREY)])
|
||
tb(s_biz, 1.5, 2.6, 10, 0.6, [dict(t="目标覆盖", size=32, bold=True, color=ORANGE)])
|
||
goals = [
|
||
("首期(0–6 个月)", "服务自有淘宝旗舰店与核心精华线,验证「测肤—推荐—购买」闭环"),
|
||
("扩展(6 个月以上)", "复制至品牌矩阵店铺,沉淀为会员中心的标准服务能力"),
|
||
]
|
||
for i, (t, d) in enumerate(goals):
|
||
x = 1.5 + i * 12.22
|
||
card(s_biz, x, 3.4, 11.45, 1.85)
|
||
tb(s_biz, x + 0.45, 3.7, 10.6, 1.35,
|
||
[dict(t=t, size=28, bold=True, sa=5), dict(t=d, size=24, color=GREY)])
|
||
tb(s_biz, 1.5, 5.65, 10, 0.6, [dict(t="上线后的运营节奏", size=32, bold=True, color=ORANGE)])
|
||
phases = [
|
||
("上线期(0–1 月)", "店铺首页与详情页入口曝光;引导完成首测;紧盯拍摄成功率与报告完成率。"),
|
||
("成长期(1–3 月)", "大促与直播挂载测肤互动;会员专属复测提醒;持续优化推荐与话术转化。"),
|
||
("沉淀期(3 月以上)", "历史报告召回与换季护理活动;A/B 优化推荐规则;提升复测率与连带购买。"),
|
||
]
|
||
for i, (t, d) in enumerate(phases):
|
||
x = 1.5 + i * 8.13
|
||
card(s_biz, x, 6.45, 7.4, 3.2)
|
||
tb(s_biz, x + 0.45, 6.8, 6.5, 2.5,
|
||
[dict(t=t, size=28, bold=True, sa=8), dict(t=d, size=24, color=GREY)])
|
||
tb(s_biz, 1.5, 10.1, 10, 0.6, [dict(t="关键指标", size=32, bold=True, color=ORANGE)])
|
||
kpis = [
|
||
("体验", "拍摄完成率 · 报告完成率 · 报告回访时长"),
|
||
("转化", "推荐点击率 · 详情跳转率 · 测肤后下单转化"),
|
||
("运营", "复测率 · 连带购买 · 会员渗透"),
|
||
("合规", "数据按账号隔离 · 权限按需申请 · 不作医疗诊断承诺"),
|
||
]
|
||
for i, (t, d) in enumerate(kpis):
|
||
x = 1.5 + i * 5.99
|
||
card(s_biz, x, 10.9, 5.71, 2.35)
|
||
tb(s_biz, x + 0.4, 11.2, 4.95, 1.8,
|
||
[dict(t=t, size=28, bold=True, sa=6), dict(t=d, size=22, color=GREY)])
|
||
|
||
# ---- P9 致谢 ----
|
||
tb(s_thx, 4.85, 8.35, 16, 0.6,
|
||
[dict(t="西安巨子生物基因技术股份有限公司", size=26, color=WHITE)])
|
||
tb(s_thx, 4.85, 9.2, 16, 0.5,
|
||
[dict(t="AI 智能测肤 · 淘宝小程序产品方案", size=22, color=WHITE)])
|
||
|
||
prs.save(OUT)
|
||
print("saved:", OUT, "slides:", len(prs.slides))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
build()
|