160 lines
9.8 KiB
Python
160 lines
9.8 KiB
Python
"""企业开站模板。仅创建缺失内容,不修改或重新发布已有页面。"""
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import transaction
|
|
from django.utils import timezone
|
|
from django.utils.html import format_html
|
|
from wagtail.models import Page, Site
|
|
|
|
from apps.blog.models import BlogIndexPage, BlogPage
|
|
from apps.cases.models import CaseStudyIndexPage, CaseStudyPage
|
|
from apps.core.management.commands.seed_contact_page import CONTACT_FORM_FIELDS
|
|
from apps.core.models import (
|
|
ContactPage, NavigationMenu, NavigationMenuItem, SimpleContentPage, SiteSettings,
|
|
)
|
|
from apps.forms.models import FormDefinition
|
|
from apps.home.models import HomePage
|
|
from apps.products.models import ProductIndexPage, ProductPage
|
|
from apps.solutions.models import SolutionIndexPage, SolutionPage
|
|
|
|
COMPANY_FIELDS = ("company_name", "contact_phone", "contact_email", "address", "icp_number")
|
|
|
|
|
|
def default_site():
|
|
site = Site.objects.filter(is_default_site=True).first()
|
|
if site is None:
|
|
raise ValidationError("未配置默认站点,请先在“设置 → 站点”中配置默认站点。")
|
|
return site
|
|
|
|
|
|
def _ensure_page(parent, model, slug, title, created, **fields):
|
|
existing = parent.get_children().filter(slug=slug).first()
|
|
if existing is not None:
|
|
if not isinstance(existing.specific, model):
|
|
raise ValidationError(f"路径 {slug} 已被其他类型的页面占用,请先调整页面路径。")
|
|
return existing.specific
|
|
page = model(title=title, slug=slug, **fields)
|
|
parent.add_child(instance=page)
|
|
page.save_revision().publish()
|
|
created.append(title)
|
|
return page
|
|
|
|
|
|
def _cta():
|
|
return ("cta", {
|
|
"heading": "一起讨论您的项目需求",
|
|
"description": "告诉我们业务目标、当前挑战与期望交付时间。",
|
|
"button": {"text": "预约项目咨询", "link": "/contact/"},
|
|
})
|
|
|
|
|
|
def _detail_body(heading, description):
|
|
return [
|
|
("richtext", str(format_html("<h2>{}</h2><p>{}</p>", heading, description))),
|
|
("feature_grid", {"heading": "服务流程", "items": [
|
|
{"icon": "1", "title": "需求梳理", "description": "明确业务场景、范围与验收标准。"},
|
|
{"icon": "2", "title": "迭代交付", "description": "分阶段演示并收集使用反馈。"},
|
|
{"icon": "3", "title": "持续维护", "description": "按约定提供培训、维护与优化支持。"},
|
|
]}),
|
|
_cta(),
|
|
]
|
|
|
|
|
|
def _create_template(site, company_name):
|
|
created = []
|
|
home = site.root_page.specific
|
|
if not isinstance(home, HomePage):
|
|
# 只允许接管全新 Wagtail 安装的空白通用欢迎页,不重绑定已有业务站点。
|
|
if type(home) is not Page or home.depth != 2 or home.get_children().exists() or home.slug != "home":
|
|
raise ValidationError("默认站点根页面不是企业首页。请先配置 HomePage,现有站点不会被替换。")
|
|
home = _ensure_page(home.get_parent(), HomePage, "company-home", "首页", created, body=[
|
|
("hero", {
|
|
"title": f"{company_name} · 软件与技术服务",
|
|
"subtitle": "从需求分析到软件交付,帮助企业构建适合自身业务的数字化系统。",
|
|
"background_image": None,
|
|
"buttons": [{"text": "了解服务", "link": "/products/"}, {"text": "项目咨询", "link": "/contact/"}],
|
|
}),
|
|
("feature_grid", {"heading": "我们可以帮助您", "items": [
|
|
{"icon": "", "title": "软件定制", "description": "围绕业务流程设计与开发应用。"},
|
|
{"icon": "", "title": "系统集成", "description": "连接现有系统,减少重复录入。"},
|
|
{"icon": "", "title": "运维支持", "description": "提供上线培训与持续维护服务。"},
|
|
]}),
|
|
("product_card", {"heading": "产品与服务", "items": [
|
|
{"title": "企业内容平台", "description": "统一管理官网内容与咨询入口。", "image": None, "link": "/products/content-platform/"},
|
|
{"title": "定制开发服务", "description": "从原型到交付,适配实际业务场景。", "image": None, "link": "/products/custom-development/"},
|
|
]}),
|
|
("faq", {"items": [
|
|
{"question": "如何开始合作?", "answer": "<p>通过咨询表单描述需求,我们会进一步确认范围与交付安排。</p>"},
|
|
{"question": "能否对接现有系统?", "answer": "<p>需要先评估现有接口、数据要求与安全边界,再确定实施方案。</p>"},
|
|
]}),
|
|
_cta(),
|
|
])
|
|
site.root_page = home
|
|
site.save(update_fields=["root_page"])
|
|
|
|
def ensure(parent, model, slug, title, **fields):
|
|
return _ensure_page(parent, model, slug, title, created, **fields)
|
|
|
|
products = ensure(home, ProductIndexPage, "products", "产品与服务", intro="探索企业内容平台与软件定制服务。")
|
|
for slug, title, summary in [
|
|
("content-platform", "企业内容平台", "集中管理品牌官网、产品内容、客户案例与咨询表单。"),
|
|
("custom-development", "定制开发服务", "根据业务流程提供 Web 应用、接口集成与运维支持。"),
|
|
]:
|
|
ensure(products, ProductPage, slug, title, summary=summary, body=_detail_body(title, summary))
|
|
solutions = ensure(home, SolutionIndexPage, "solutions", "解决方案", intro="以业务场景为起点,规划可落地的数字化方案。")
|
|
ensure(solutions, SolutionPage, "digital-workplace", "企业数字化协同", industry="企业服务",
|
|
summary="连接内容、流程与数据,减少团队之间的信息断层。",
|
|
body=_detail_body("从业务流程出发", "先梳理现有工具与协作瓶颈,再规划分阶段实施方案。"))
|
|
cases = ensure(home, CaseStudyIndexPage, "cases", "客户案例", intro="以下案例为模板演示,请上线前替换为获得授权的真实案例。")
|
|
ensure(cases, CaseStudyPage, "demo-content-project", "示例案例:企业内容管理项目(虚构)",
|
|
client_name="虚构示例企业", industry="企业服务", published_at=timezone.now(),
|
|
summary="仅用于展示案例结构,不代表真实客户、交付成果或业绩。",
|
|
body=_detail_body("示例内容,请勿作为真实业绩发布", "展示需求背景、实施过程与验收方式;请替换为客户授权的真实材料。"))
|
|
blog = ensure(home, BlogIndexPage, "blog", "技术与洞察", intro="分享技术实践、产品思考与项目经验。")
|
|
ensure(blog, BlogPage, "website-content-checklist", "示例文章:企业官网上线内容清单",
|
|
published_at=timezone.now(), intro="上线前核对品牌资料、产品信息、联系渠道与隐私说明。",
|
|
body=[("richtext", "<h2>上线前检查</h2><ul><li>替换所有示例内容与图片。</li><li>检查手机端布局与页面链接。</li><li>提交测试咨询,确认通知可达。</li><li>按实际情况审核备案和隐私说明。</li></ul>")])
|
|
about = ensure(home, SimpleContentPage, "about", "关于我们", body=str(format_html(
|
|
"<h2>关于 {}</h2><p>我们提供软件开发、系统集成与技术服务。</p>"
|
|
"<h2>我们的工作方式</h2><p>明确需求、迭代交付、持续支持。</p>"
|
|
"<p>模板提示:请补充真实的公司介绍、团队与资质,不要发布未经核实的业绩。</p>", company_name)))
|
|
privacy = ensure(home, SimpleContentPage, "privacy-policy", "隐私政策(待完善)",
|
|
body="<p>这是隐私说明占位内容。上线前请根据实际收集的数据、处理目的、保存期限、联系与删除方式完善,并完成必要审核。</p>")
|
|
contact = home.get_children().filter(slug="contact").first()
|
|
if contact is not None and not isinstance(contact.specific, ContactPage):
|
|
raise ValidationError("路径 contact 已被其他类型的页面占用,请先调整页面路径。")
|
|
if contact is None:
|
|
form = FormDefinition.objects.create(name="官网项目咨询", notification_email=SiteSettings.for_site(site).contact_email)
|
|
for order, field in enumerate(CONTACT_FORM_FIELDS):
|
|
form.fields.create(sort_order=order, **field)
|
|
contact = ensure(home, ContactPage, "contact", "联系我们", body=[
|
|
("richtext", "<h2>项目咨询</h2><p>请描述您的业务需求与预期,我们将与您进一步沟通。</p>"),
|
|
("form", {"form": form}),
|
|
])
|
|
else:
|
|
contact = contact.specific
|
|
for name, entries in [
|
|
("main", [("首页", home), ("产品与服务", products), ("解决方案", solutions), ("案例", cases), ("技术博客", blog), ("关于我们", about), ("联系咨询", contact)]),
|
|
("footer", [("关于我们", about), ("联系我们", contact), ("隐私政策", privacy)]),
|
|
]:
|
|
menu, is_new = NavigationMenu.objects.get_or_create(name=name)
|
|
if is_new:
|
|
for order, (label, page) in enumerate(entries):
|
|
if page.live:
|
|
NavigationMenuItem.objects.create(menu=menu, sort_order=order, label=label, link_page=page)
|
|
return created
|
|
|
|
|
|
@transaction.atomic
|
|
def setup_company_site(company_data, create_demo=False):
|
|
site = default_site()
|
|
# 序列化同一站点的初始化请求,避免重复页面/表单。
|
|
site = Site.objects.select_for_update().get(pk=site.pk)
|
|
settings = SiteSettings.for_site(site)
|
|
for field in COMPANY_FIELDS:
|
|
setattr(settings, field, company_data[field])
|
|
settings.full_clean()
|
|
settings.save()
|
|
site.site_name = settings.company_name
|
|
site.save(update_fields=["site_name"])
|
|
return _create_template(site, settings.company_name) if create_demo else []
|