跳到主要内容

自定义和配置

本指南解释了如何自定义和配置 OmniCRM,以匹配您的品牌形象、操作要求和集成需求。

环境变量 (.env 文件)

OmniCRM 使用环境变量来配置后端 API 和前端 UI。有两个单独的 .env 文件控制系统的不同方面。

后端 API 配置 (.env)

位于 OmniCRM 目录的根目录,此文件配置数据库连接和 CGRates 集成。

位置: /OmniCRM/.env

数据库配置:

# MySQL/MariaDB 数据库 (CRM 数据)
MYSQL_ROOT_PASSWORD=your_secure_password
MYSQL_USER=omnitouch
MYSQL_PASSWORD=your_database_password
MYSQL_DATABASE=crm
DB_SERVER=db

# PostgreSQL 数据库 (CGRates 数据)
POSTGRES_USER=cgrates
POSTGRES_PASSWORD=cgrates_password
POSTGRES_DB=cgrates_db

CGRates 配置:

# CGRates API 凭证
CGRATES_API_USER=admin
CGRATES_API_PASS=secret
CGRATES_DB_USER=cgrates
CGRATES_DB_PASS=cgrates_password
CGRATES_DB_NAME=cgrates_db
CGRATES_DB_PORT=5432

安全考虑:

  • 绝不要将 .env 文件提交到版本控制 - 使用 .env.example 作为模板
  • 使用强密码 - 至少 16 个字符,包含大小写字母、数字和符号
  • 定期更换凭证 - 尤其是在生产部署中
  • 限制数据库访问 - 使用 IP 白名单和防火墙规则

前端 UI 配置 (.env)

位于 OmniCRM-UI 目录,此文件控制品牌、外观、集成和功能标志。

位置: /OmniCRM/OmniCRM-UI/.env

API 密钥和集成:

# Google Maps API (用于地址自动完成和地理编码)
REACT_APP_GOOGLE_API_KEY=your_google_api_key

# Stripe 支付网关
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_test_xxxxx

# 在 npm start 时禁用浏览器自动启动
BROWSER=none

品牌和公司信息:

# 公司品牌
REACT_APP_COMPANY_NAME="ShellFone"
REACT_APP_PORTAL_NAME="ShellManager"
REACT_APP_SELF_CARE_NAME="ShellCare"
REACT_APP_COMPANY_TAGLINE="Phones with Shells"

这些值在 UI 中的各个地方出现:

  • COMPANY_NAME - 显示在页面标题、电子邮件和客户通信中
  • PORTAL_NAME - 管理员/员工门户的名称(例如,"ShellManager")
  • SELF_CARE_NAME - 客户自助服务门户的名称(例如,"ShellCare")
  • COMPANY_TAGLINE - 出现在登录屏幕和营销材料中

本地化和区域设置:

# 语言和区域
# 支持的语言:ar, ch, en, fr, gr, it, ru, sp
REACT_APP_DEFAULT_LANGUAGE=en
REACT_APP_LOCALE="en-GB"

# 默认位置 (用于地址自动完成)
REACT_APP_DEFAULT_LOCATION="Sydney, Australia"
REACT_APP_DEFAULT_COUNTRY="Australia"

# 货币设置
REACT_APP_CURRENCY_CODE="GBP"
REACT_APP_CURRENCY_SYMBOL="£"

颜色方案自定义:

# 主色 (主要品牌颜色)
REACT_APP_PRIMARY_COLOR=#405189

# 其他颜色选项 (注释示例)
# REACT_APP_SECONDARY_COLOR=#2bFFcf
# REACT_APP_TERTIARY_COLOR=#1a9fbf
# REACT_APP_SUCCESS_COLOR=#28a745
# REACT_APP_INFO_COLOR=#17a2b8
# REACT_APP_WARNING_COLOR=#ffc107
# REACT_APP_DANGER_COLOR=#dc3545

主色应用于:

  • 导航标题
  • 操作按钮
  • 链接和高亮
  • 活动状态
  • 品牌元素

Web 应用集成:

配置最多 6 个快速访问的 Web 应用程序,这些应用程序出现在管理员仪表板中:

# Web 应用 1:GitHub
REACT_APP_WEB_APP_1_NAME="GitHub"
REACT_APP_WEB_APP_1_URL="https://github.com"
REACT_APP_WEB_APP_1_ICON_PATH="resources/webapp_icons/github.png"

# Web 应用 2:Xero
REACT_APP_WEB_APP_2_NAME="Xero"
REACT_APP_WEB_APP_2_URL="https://go.xero.com/"
REACT_APP_WEB_APP_2_ICON_PATH="resources/webapp_icons/xero.png"

# Web 应用 3-6:其他集成
# (类似配�� NAME、URL 和 ICON_PATH)

监控和分析:

# Grafana 仪表板集成
REACT_APP_GRAFANA_URLS=url1,url2,url3
REACT_APP_GRAFANA_LABELS=label1,label2,label3
REACT_APP_GRAFANA_API_KEY=your-api-key

功能标志:

# 支持和文档 URL
REACT_APP_FAQS_URL=https://docs.yourcompany.com/faqs
REACT_APP_SUPPORT_URL=https://support.yourcompany.com

# 社交登录 (Google、Facebook 等)
REACT_APP_ALLOW_SOCIAL_LOGINS=yes

徽标和启动图像自定义

OmniCRM 允许您用公司的徽标和启动屏幕替换默认的品牌图像,而无需修改代码。

徽标文件

徽标存储在 /OmniCRM-UI/src/assets/images/omnitouch/ 中,并使用回退系统:

默认徽标(始终存在):

  • DefaultLogoDark.png - 深色主题徽标(用于浅色背景)
  • DefaultLogoLight.png - 浅色主题徽标(用于深色背景)

自定义徽标(可选,存在时优先):

  • logoSm.png - 用于折叠侧边栏的小徽标(推荐:100x100px)
  • logoDark.png - 用于标题的全尺寸深色徽标(推荐:200x50px)
  • logoLight.png - 用于身份验证屏幕的全尺寸浅色徽标(推荐:200x50px)

徽标回退工作原理:

系统首先尝试加载自定义徽标。如果自定义徽标文件不存在,则回退到���认:

// 来自 Header.js
const tryImport = (filename) => {
try {
return require(`../assets/images/omnitouch/${filename}`);
} catch (err) {
return null; // 回退到默认
}
};

const userLogoSm = tryImport("logoSm.png");
const userLogoDark = tryImport("logoDark.png");
const userLogoLight = tryImport("logoLight.png");

徽标出现的位置:

  • logoSm.png - 折叠侧边栏、移动导航、小标题显示
  • logoDark.png - 主标题栏(浅色模式)、管理员仪表板标题
  • logoLight.png - 登录/注册屏幕、深色背景、身份验证轮播

替换徽标:

  1. 创建您的徽标文件:

    • 使用 PNG 格式以支持透明度
    • 符合上述推荐尺寸
    • 确保徽标在常规和视网膜分辨率下清晰可见
  2. 添加到 OmniCRM:

    # 将您的徽标文件复制到 omnitouch 图像目录
    cp /path/to/your/logoSm.png OmniCRM-UI/src/assets/images/omnitouch/
    cp /path/to/your/logoDark.png OmniCRM-UI/src/assets/images/omnitouch/
    cp /path/to/your/logoLight.png OmniCRM-UI/src/assets/images/omnitouch/
  3. 重建 UI:

    cd OmniCRM-UI
    npm run build
  4. 验证更改:

    • 检查浅色模式标题(应��示 logoDark.png
    • 检查深色模式标题(应显示 logoLight.png
    • 检查折叠侧边栏(应显示 logoSm.png
    • 检查登录屏幕(应显示 logoLight.png

徽标设计最佳实践:

  • 对比度 - 确保徽标在浅色和深色背景上都可见
  • 简洁性 - 徽标在小尺寸下应易于识别
  • 格式 - 使用带透明背景的 PNG
  • 视网膜 - 为高 DPI 显示器提供 2 倍分辨率
  • 一致性 - 在所有徽标变体中使用相同的品牌颜色

启动屏幕和身份验证背景

身份验证屏幕(登录、注册、密码重置)使用可自定义图像的轮播背景。

位置: /OmniCRM-UI/src/pages/AuthenticationInner/authCarousel.js

默认配置:

import logoLight from "../../assets/images/logo-light.png";

// 在身份验证屏幕上显示的徽标
<img src={logoLight} alt="" height="18" />

自定义身份验证屏幕:

  1. 替换 /OmniCRM-UI/src/assets/images/ 中的 logo-light.png
  2. 将自定义背景 CSS 添加到 .auth-one-bg
  3. 修改 authCarousel.js 中的轮播引用,以匹配您的品牌语音

示例自定义:

/* 添加到您的自定义 CSS */
.auth-one-bg {
background-image: url('/assets/images/custom-auth-bg.jpg');
background-size: cover;
background-position: center;
}

CRM 配置文件 (crm_config.yaml)

crm_config.yaml 文件是 OmniCRM API 的中心配置,控制集成、供应、电子邮件模板和外部服务。

位置: /OmniCRM/OmniCRM-API/crm_config.yaml

数据库配置

database:
username: omnitouch
password: omnitouch2024
server: localhost

注意: 这应与您的 .env 数据库凭证匹配。在容器化部署中,服务器通常是 db(Docker 服务名称)。

服务类型

定义您部署的有效服务类型:

service_types:
- omnicharge
- mobile
- fixed
- fixed-voice
- hotspot
- dongle

这些在系统中用于:

  • 产品分类
  • 附加组件过滤(附加组件匹配服务类型)
  • 供应工作流
  • 报告和分析

HSS 集成(家庭用户服务器)

对于具有 HSS 集成的移动网络运营商:

hss:
hss_peers:
- 'http://10.179.2.140:8080'
apn_list: "1,2,3,4,5,6"

配置:

  • hss_peers - 用于用户供应的 HSS 端点列表
  • apn_list - 可用于供应的 APN ID 的逗号分隔列表

Mailjet 电子邮件模板配置

OmniCRM 使用 Mailjet 发送事务性电子邮件。每种电子邮件类型都有自己的模���配置:

mailjet:
api_key: your_mailjet_api_key
api_secret: your_mailjet_api_secret

# 客户欢迎电子邮件
api_crmCommunicationCustomerWelcome:
from_email: "support@yourcompany.com"
from_name: "Your Company Support"
template_id: 5977509
subject: "Welcome to YourCompany"

# 客户发票电子邮件
api_crmCommunicationCustomerInvoice:
from_email: "billing@yourcompany.com"
from_name: "Your Company Billing"
template_id: 6759851
subject: "Your Invoice - "

# 发票提醒
api_crmCommunicationCustomerInvoiceReminder:
from_email: "billing@yourcompany.com"
from_name: "Your Company Billing"
template_id: 5977570
subject: "Invoice Payment Reminder"

# 用户欢迎电子邮件(员工/管理员)
api_crmCommunicationUserWelcome:
from_email: "admin@yourcompany.com"
from_name: "Your Company Admin"
template_id: 6118112
subject: "Welcome to the Team"

# 密码重置请求
api_crmCommunicationUserPasswordReset:
from_email: "security@yourcompany.com"
from_name: "Your Company Security"
template_id: 6735666
subject: "Password Reset Request"

# 密码重置成功确认
api_crmCommunicationUserPasswordResetSuccess:
from_email: "security@yourcompany.com"
from_name: "Your Company Security"
template_id: 6118378
subject: "Password Reset Successful"

# 密码更改通知
api_crmCommunicationUserPasswordChange:
from_email: "security@yourcompany.com"
from_name: "Your Company Security"
template_id: 6118423
subject: "Password Changed"

# 电子邮件验证
api_crmCommunicationEmailVerification:
from_email: "verify@yourcompany.com"
from_name: "Your Company Verification"
template_id: 6267350
subject: "Verify Your Email Address"

# 余额过期通知
api_crmCommunicationsBalanceExpired:
from_email: "alerts@yourcompany.com"
from_name: "Your Company Alerts"
template_id: 7238252
subject: "Service Balance Expired"

# 余额不足警告
api_crmCommunicationsBalanceLow:
from_email: "alerts@yourcompany.com"
from_name: "Your Company Alerts"
template_id: 7238263
subject: "Low Balance Warning"

创建 Mailjet 模板:

  1. 登录 Mailjet 仪表板 (<https://app.mailjet.com>)
  2. 导航到 TransactionalTemplates
  3. 创建新模板或克隆现有模板
  4. 记下 模板 ID(数字值)
  5. 添加与 OmniCRM 数据结构匹配的模板变量
  6. 使用模板 ID 更新 crm_config.yaml

可用模板变量:

每种电子邮件类���接收特定变量。常见示例:

  • {{customer_name}} - 客户或用户姓名
  • {{service_name}} - 服务或产品名称
  • {{invoice_id}} - 发票编号
  • {{invoice_amount}} - 发票总金额
  • {{due_date}} - 付款截止日期
  • {{reset_link}} - 密码重置 URL
  • {{verification_link}} - 电子邮件验证 URL
  • {{balance}} - 当前账户余额
  • {{expiry_date}} - 余额或服务到期日期

供应配置

provisioning:
failure_list: ['admin@yourcompany.com', 'ops@yourcompany.com']

目的:

  • failure_list - 当 Ansible 供应失败时通知的电子邮件地址
  • 通知包括剧本名称、错误详细信息和客户信息
  • 允许运维团队快速响应供应问题

发票配置

invoice:
template_filename: 'yourcompany_invoice_template.html'

目的:

指定用于 PDF 发票生成的 Jinja2 HTML 模板。

模板位置: /OmniCRM-API/invoice_templates/

有关创建自定义模板的详细信息,请参见 发票 PDF 生成 部分。

CRM 基础 URL

crm:
base_url: 'http://localhost:5000'

目的:

  • 由 Ansible 剧本用于进行 API 回调
  • 在电子邮件模板中用于生成指向 CRM 的链接
  • 应为您 API 的公共可访问 URL(而不是内部容器名称)

示例:

  • 开发:http://localhost:5000
  • 生产:https://api.yourcompany.com
  • Docker:http://omnicrm-api:5000(内部容器通信)

OCS 和 CGRates 配置

ocs:
ocsApi: 'http://10.179.2.142:8080/api'
ocsTenant: 'mnc380.mcc313.3gppnetwork.org'
cgrates: 'localhost:2080'

配置:

  • ocsApi - 用于用户管理的 OCS API 端点
  • ocsTenant - 多租户 OCS 部署的租户标识符
  • cgrates - CGRates JSON-RPC API 端点(主机:端口)

SMSC 配置 (SMS 网关)

smsc:
source_msisdn: 'YourCompany'
smsc_url: 'http://10.179.2.216/SMSc/'
api_key: 'your_smsc_api_key'

目的:

  • 向客户发送 SMS 通知(余额不足、服务警报、2FA 代码)
  • source_msisdn - 显示给收件人的发件人 ID(字母数字或电话号码)
  • smsc_url - SMSC 网关 API 端点
  • api_key - SMSC API 的身份验证

JWT 密钥

jwt_secret: '2b93110f723db60172c8e9a1eaa80027a9a9c3f05b44e50dc3fcf38dba68d87e'

安全性:

  • 用于签名和验证身份验证令牌
  • 在生产中必须更改默认值
  • 生成一个安全的随机字符串(至少 64 个字符)
  • 切勿共享或提交到版本控制

生成新 JWT 密钥:

# 生成一个加密安全的随机密钥
python3 -c "import secrets; print(secrets.token_hex(32))"

Stripe 支付配置

stripe:
secret_key: 'sk_live_xxxxxxxxxx'
publishable_key: 'pk_live_xxxxxxxxxx'
currency: 'aud'
statement_descriptor_suffix: 'YOURCOMPANY'

配置:

  • secret_key - Stripe 秘密 API 密钥(服务器端,保密)
  • publishable_key - Stripe 可发布密钥(客户端,安全暴露)
  • currency - ISO 4217 货币代码(aud、usd、gbp、eur 等)
  • statement_descriptor_suffix - 出现在客户信用卡对账单上的内容

对账单描述符的使用:

  • 在客户银行对账单上显示为 "YOURCOMPANY"
  • 最大 22 个字符
  • 帮助客户识别费用
  • 也用于发票 PDF 文件名(例如,YOURCOMPANY_12345.pdf

API 密钥和 IP 白名单

定义具有基于角色的访问和 IP 限制的 API 密钥:

api_keys:
"YOUR_API_KEY_1":
roles: ["admin"]
ips: ["127.0.0.1", "::1"]
"YOUR_API_KEY_2":
roles: ["customer_service_agent_1"]
ips: ["127.0.0.1", "::1", "10.0.1.0/24"]

# IP 白名单(独立,无需 API 密钥)
ip_whitelist:
"10.179.2.142":
roles: ["admin"]

目的:

  • 允许外部系统通过 API 密钥进行身份验证
  • 按 IP 地址限制访问
  • 授予 API 消费者特定角色
  • 对于集成(计费系统、监控、自动化)非常有用

安全最佳实践:

  • 使用长且随机的 API 密钥(至少 32 个字符)
  • 将 IP 限制为已知来源
  • 授予最低必要���色
  • 定期轮换 API 密钥
  • 在日志中监控 API 密钥使用情况

发票 PDF 生成

OmniCRM 使用 Jinja2 HTML 模板和 WeasyPrint PDF 渲染生成专业的 PDF 发票。

PDF 生成工作原理

  1. 模板选择:
    • 模板文件名在 crm_config.yaml 中的 invoice.template_filename 下指定
    • 模板从 /OmniCRM-API/invoice_templates/ 目录加载
  2. 数据准备:
    • 从数据库获取发票数据(ID、日期、金额、状态)
    • 检索客户信息(姓名、地址)
    • 编译交易列表(发票上的所有费用/信用)
  3. 模板渲染:
    • Jinja2 使用发票数据渲染 HTML 模板
    • {{ invoice_number }}{{ total_amount }} 等变量被替换
    • 渲染的 HTML 保存到 invoice_templates/rendered/ 以便调试
  4. PDF 生成:
    • WeasyPrint 将渲染的 HTML 转换为 PDF
    • PDF 支持 CSS 样式、图像、分页、页眉/页脚
    • PDF 二进制数据在内存中生成
  5. 缓存:
    • PDF 被 Base64 编码并存储在 Invoice_PDF_Cache 表中
    • 计算 SHA256 哈希以进行完整性验证
    • 随后请求返回缓存的 PDF(即时交付)
  6. 缓存失效:
    • 当发票被修改、作废或退款时,缓存失效
    • 模板更改不会自动使现有缓存失效

发票模板结构

发票模板是带有嵌入变量和逻辑的 Jinja2 HTML 文件。

模板位置: /OmniCRM-API/invoice_templates/yourcompany_invoice_template.html

可用变量:

{
'invoice_number': 12345,
'date': '2025-01-04',
'client': {
'name': 'John Smith',
'address': {
'address_line_1': '123 Main St',
'city': 'Sydney',
'state': 'NSW',
'zip_code': '2000',
'country': 'Australia'
}
},
'transaction_list': [
[
{
'transaction_id': 1,
'title': 'Mobile Service - Monthly Fee',
'retail_cost': 30.00,
'wholesale_cost': 10.00,
'created': '2025-01-01'
},
{
'transaction_id': 2,
'title': 'Data Addon - 5GB',
'retail_cost': 15.00,
'wholesale_cost': 5.00,
'created': '2025-01-15'
}
]
],
'total_amount': 45.00,
'due_date': '2025-01-31',
'start_date': '2025-01-01',
'end_date': '2025-01-31',
'paid': False,
'void': False
}

示例模板片段:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Invoice {{ invoice_number }}</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.invoice-details {
margin-bottom: 20px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
th {
background-color: #405189;
color: white;
}
.total {
text-align: right;
font-size: 18px;
font-weight: bold;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="header">
<img src="file:///path/to/logo.png" alt="Company Logo" height="60">
<h1>INVOICE</h1>
</div>

<div class="invoice-details">
<p><strong>Invoice Number:</strong> {{ invoice_number }}</p>
<p><strong>Date:</strong> {{ date }}</p>
<p><strong>Due Date:</strong> {{ due_date }}</p>
<p><strong>Billing Period:</strong> {{ start_date }} to {{ end_date }}</p>
</div>

<div class="customer-details">
<h3>Bill To:</h3>
<p>{{ client.name }}</p>
<p>{{ client.address.address_line_1 }}</p>
<p>{{ client.address.city }}, {{ client.address.state }} {{ client.address.zip_code }}</p>
<p>{{ client.address.country }}</p>
</div>

<table>
<thead>
<tr>
<th>Description</th>
<th>Date</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for transaction in transaction_list[0] %}
<tr>
<td>{{ transaction.title }}</td>
<td>{{ transaction.created }}</td>
<td>${{ "%.2f"|format(transaction.retail_cost) }}</td>
</tr>
{% endfor %}
</tbody>
</table>

<div class="total">
<p>Total Amount Due: ${{ "%.2f"|format(total_amount) }}</p>
</div>

{% if paid %}
<div style="text-align: center; color: green; font-weight: bold;">
PAID
</div>
{% endif %}

{% if void %}
<div style="text-align: center; color: red; font-weight: bold;">
VOID
</div>
{% endif %}
</body>
</html>

模板最佳实践:

  • 使用绝对路径的图像 - file:///absolute/path/to/image.png
  • 内联 CSS - WeasyPrint 不可靠地加载外部样式表
  • 使用示例数据进行测试 - 使用 invoice_templates/rendered/ 检查 HTML
  • 分页 - 使用 <div style="page-break-after: always;"></div> 处理多页发票
  • 页眉和页脚 - 使用 @page CSS 规则处理重复元素
  • 货币格式化 - 使用 Jinja2 过滤器: {{ "%.2f"|format(amount) }}

创建自定义发票模板

  1. 复制示例模板:

    cd /OmniCRM/OmniCRM-API/invoice_templates
    cp norfone_invoice_template.html yourcompany_invoice_template.html
  2. 编辑模板:

    • 替换公司名称、徽标、联系信息
    • 调整样式(颜色、字体、布局)以匹配品牌
    • 根据需要添加或删除部分(税收明细、付款说明等)
  3. 更新配置:

    编辑 crm_config.yaml

    invoice:
    template_filename: 'yourcompany_invoice_template.html'
  4. 测试发票生成:

    • 在 CRM 中创建测试发票
    • 下载 PDF 并验证格式
    • 检查 invoice_templates/rendered/{invoice_id}.html 以便调试
  5. 使旧缓存失效(如有需要):

    如果您已更改模板并希望重新生成现有发票:

    -- 清除所有缓存的 PDF(强制重新生成)
    DELETE FROM Invoice_PDF_Cache;

PDF 缓存系统

为了提高性能,OmniCRM 缓存生成的 PDF:

缓存行为:

  • 第一次请求 - 生成 PDF,缓存并返回
  • 后续请求 - 立即返回缓存的 PDF(无需重新生成)
  • 缓存失效 - 当发票被修改、作废或退款时发生
  • 缓存清理 - 旧缓存在 30 天不活动后自动清除

缓存存储:

  • Base64 编码的 PDF 存储在 Invoice_PDF_Cache 表中
  • 用于完整性验证的 SHA256 内容哈希
  • 包括文件名、创建时间戳、最后访问时间戳

手动缓存管理:

# 在 OmniCRM API 或 Python shell 中
from services.invoice_service import cleanup_old_pdf_cache, invalidate_invoice_cache
from utils.db_helpers import get_db_session

session = get_db_session()

# 清理超过 30 天的缓存
result = cleanup_old_pdf_cache(session, days_old=30)
print(result) # {'status': 'success', 'deleted_count': 15}

# 使特定发票缓存失效
invalidate_invoice_cache(session, invoice_id='12345')

API 端点:

生成/下载发票 PDF:

GET /invoice/pdf/{invoice_id}

响应: PDF 文件下载,文件名来自 Stripe 对账单描述符

缓存头:

  • 第一次请求:响应较慢(生成时间)
  • 缓存请求:即时响应
  • 缓存命��/未命中对用户是透明的

故障排除

PDF 生成失败:

  • 检查 WeasyPrint 是否已安装:pip install weasyprint
  • 验证模板文件名是否与 crm_config.yaml 匹配
  • 检查 invoice_templates/rendered/ 以获取 HTML 渲染错误
  • 查看 API 日志以获取 Jinja2 模板错误

PDF 中未出现图像:

  • 使用绝对文件路径:file:///full/path/to/image.png
  • 确保图像文件存在且可读
  • 检查图像格式(PNG 和 JPEG 效果最佳)
  • 验证图像路径中不包含特殊字符

样式问题:

  • 所有 CSS 内联(不支持外部样式表)
  • 避免复杂的 CSS 特性(flexbox、grid 可能无法正确渲染)
  • 首先测试简单布局,逐渐增加复杂性
  • 尽可能使用表格进行布局,而不是 div

缓存未失效:

  • 验证在发票修改时是否调用 invalidate_invoice_cache()
  • 检查交易更新是否触发缓存失效
  • 如有需要,手动从 Invoice_PDF_Cache 表中删除

配置检查清单

在部署 OmniCRM 时使用此检查清单:

后端配置

  • [ ] 复制 .env.example.env
  • [ ] 设置强大的数据库密码
  • [ ] 配置 CGRates 凭证
  • [ ] 使用您的设置更新 crm_config.yaml
    • [ ] 数据库连接
    • [ ] 服务类型
    • [ ] Mailjet API 密钥和模板 ID
    • [ ] 供应失败通知电子邮件
    • [ ] 发票模板文件名
    • [ ] CRM 基础 URL(公共可访问)
    • [ ] OCS/CGRates 端点
    • [ ] SMSC 配置
    • [ ] 生成新的 JWT 密钥
    • [ ] Stripe 密钥(生产,不是测试)
    • [ ] API 密钥和 IP 白名单

前端配置

  • [ ] 复制 OmniCRM-UI/.env.exampleOmniCRM-UI/.env
  • [ ] 设置 Google Maps API 密钥
  • [ ] 设置 Stripe 可发布密钥
  • [ ] 更新公司品牌:
    • [ ] 公司名称
    • [ ] 门户名称
    • [ ] 自助服务名称
    • [ ] 公司标语
  • [ ] 配置本地化:
    • [ ] 默认语言
    • [ ] 区域
    • [ ] 默认位置和国家
    • [ ] 货币代码和符号
  • [ ] 设置主要品牌颜色
  • [ ] 配置 Web 应用集成(可选)
  • [ ] 添加支持和常见问题 URL(可选)

品牌资产

  • [ ] 创建徽标文件(logoSm.png、logoDark.png、logoLight.png)
  • [ ] 将徽标上传到 OmniCRM-UI/src/assets/images/omnitouch/
  • [ ] 创建自定义发票模板 HTML
  • [ ] 将发票模板上传到 OmniCRM-API/invoice_templates/
  • [ ] ��用发票模板文件名更新 crm_config.yaml
  • [ ] 测试发票 PDF 生成
  • [ ] 重建 UI:npm run build

安全

  • [ ] 更改所有默认密码
  • [ ] 生成唯一的 JWT 密钥
  • [ ] 使用生产 Stripe 密钥(不是测试密钥)
  • [ ] 轮换 Mailjet API 密钥
  • [ ] 启用防火墙规则
  • [ ] 配置 API 访问的 IP 白名单
  • [ ] 设置 SSL/TLS 证书
  • [ ] 为所有端点启用 HTTPS
  • [ ] 审查 CORS 设置
  • [ ] 实施速率限制
  • [ ] 配置备份和恢复程序

测试

  • [ ] 测试客户注册流程
  • [ ] 测试服务供应的端到端
  • [ ] 验证电子邮件通知是否正确发送
  • [ ] 测试发票生成和 PDF 下载
  • [ ] 验证支付处理(Stripe)
  • [ ] 检查用户身份验证和 2FA
  • [ ] 测试冒充和审计日志
  • [ ] 验证 OCS 的使用数据同步
  • [ ] 测试 ActionPlan 创建和续订
  • [ ] 确认库存分配正常工作

部署

  • [ ] 构建 Docker 镜像或部署到服务器
  • [ ] 启动数据库容器(MySQL、PostgreSQL)
  • [ ] 启动 CGRates
  • [ ] 启动 OmniCRM API
  • [ ] 启动 OmniCRM UI
  • [ ] 配置反向代理(nginx、traefik)
  • [ ] 设置监控(Grafana、Prometheus)
  • [ ] 配置日志聚合
  • [ ] 设置自动备份
  • [ ] 文档部署架构
  • [ ] 培训员工使用系统

相关文档