galaxy-opc-plugin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -0
- package/index.ts +145 -0
- package/openclaw.plugin.json +17 -0
- package/package.json +47 -0
- package/skills/basic-crm/SKILL.md +81 -0
- package/skills/basic-finance/SKILL.md +100 -0
- package/skills/business-monitoring/SKILL.md +120 -0
- package/skills/company-lifecycle/SKILL.md +99 -0
- package/skills/company-registration/SKILL.md +80 -0
- package/skills/finance-tax/SKILL.md +150 -0
- package/skills/hr-assistant/SKILL.md +127 -0
- package/skills/investment-management/SKILL.md +101 -0
- package/skills/legal-assistant/SKILL.md +113 -0
- package/skills/media-ops/SKILL.md +101 -0
- package/skills/procurement-management/SKILL.md +91 -0
- package/skills/project-management/SKILL.md +125 -0
- package/src/api/companies.ts +193 -0
- package/src/api/dashboard.ts +25 -0
- package/src/api/routes.ts +14 -0
- package/src/db/index.ts +63 -0
- package/src/db/migrations.ts +67 -0
- package/src/db/schema.ts +518 -0
- package/src/db/sqlite-adapter.ts +366 -0
- package/src/opc/company-manager.ts +82 -0
- package/src/opc/context-injector.ts +186 -0
- package/src/opc/reminder-service.ts +289 -0
- package/src/opc/types.ts +330 -0
- package/src/opc/workspace-factory.ts +189 -0
- package/src/tools/acquisition-tool.ts +150 -0
- package/src/tools/asset-package-tool.ts +283 -0
- package/src/tools/finance-tool.ts +244 -0
- package/src/tools/hr-tool.ts +211 -0
- package/src/tools/investment-tool.ts +201 -0
- package/src/tools/legal-tool.ts +191 -0
- package/src/tools/lifecycle-tool.ts +251 -0
- package/src/tools/media-tool.ts +174 -0
- package/src/tools/monitoring-tool.ts +207 -0
- package/src/tools/opb-tool.ts +193 -0
- package/src/tools/opc-tool.ts +206 -0
- package/src/tools/procurement-tool.ts +191 -0
- package/src/tools/project-tool.ts +203 -0
- package/src/tools/schemas.ts +163 -0
- package/src/tools/staff-tool.ts +211 -0
- package/src/utils/tool-helper.ts +16 -0
- package/src/web/config-ui.ts +3501 -0
- package/src/web/landing-page.ts +269 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 星环OPC中心 — 自动提醒后台服务
|
|
3
|
+
*
|
|
4
|
+
* 定期扫描数据库,自动生成以下类型的告警:
|
|
5
|
+
* - 税务申报到期提醒(7天内)
|
|
6
|
+
* - 合同到期提醒(30天内)
|
|
7
|
+
* - 现金流预警(近30天净流为负且低于阈值)
|
|
8
|
+
*
|
|
9
|
+
* 防重复:同一公司同一类别同一周期内不重复写入。
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import https from "node:https";
|
|
13
|
+
import http from "node:http";
|
|
14
|
+
import type { OpcDatabase } from "../db/index.js";
|
|
15
|
+
|
|
16
|
+
type AlertRow = { id: string; company_id: string; category: string; title: string };
|
|
17
|
+
type TaxRow = { id: string; company_id: string; period: string; tax_type: string; due_date: string; amount: number };
|
|
18
|
+
type ContractRow = { id: string; company_id: string; title: string; end_date: string; counterparty: string };
|
|
19
|
+
type FinRow = { income: number; expense: number };
|
|
20
|
+
type CompanyRow = { id: string; name: string };
|
|
21
|
+
|
|
22
|
+
/** 计算今天到目标日期的天数差(负数=已过期),日期无效时返回 null */
|
|
23
|
+
function daysUntil(dateStr: string): number | null {
|
|
24
|
+
if (!dateStr) return null;
|
|
25
|
+
const target = new Date(dateStr);
|
|
26
|
+
if (isNaN(target.getTime())) return null;
|
|
27
|
+
const today = new Date();
|
|
28
|
+
today.setHours(0, 0, 0, 0);
|
|
29
|
+
target.setHours(0, 0, 0, 0);
|
|
30
|
+
return Math.round((target.getTime() - today.getTime()) / 86400000);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** 今天的日期字符串 YYYY-MM-DD */
|
|
34
|
+
function today(): string {
|
|
35
|
+
return new Date().toISOString().slice(0, 10);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 30天前的日期字符串 */
|
|
39
|
+
function daysAgo(n: number): string {
|
|
40
|
+
const d = new Date();
|
|
41
|
+
d.setDate(d.getDate() - n);
|
|
42
|
+
return d.toISOString().slice(0, 10);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 检查近期是否已存在同类告警(防重复) */
|
|
46
|
+
function alertExists(db: OpcDatabase, companyId: string, category: string, titleKeyword: string): boolean {
|
|
47
|
+
const cutoff = daysAgo(3); // 3天内不重复
|
|
48
|
+
const rows = db.query(
|
|
49
|
+
`SELECT id FROM opc_alerts WHERE company_id = ? AND category = ? AND title LIKE ? AND status = 'active' AND created_at >= ?`,
|
|
50
|
+
companyId, category, `%${titleKeyword}%`, cutoff,
|
|
51
|
+
) as AlertRow[];
|
|
52
|
+
return rows.length > 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 写入告警 */
|
|
56
|
+
function createAlert(db: OpcDatabase, params: {
|
|
57
|
+
companyId: string;
|
|
58
|
+
title: string;
|
|
59
|
+
message: string;
|
|
60
|
+
severity: "info" | "warning" | "critical";
|
|
61
|
+
category: string;
|
|
62
|
+
}): void {
|
|
63
|
+
const now = new Date().toISOString();
|
|
64
|
+
db.execute(
|
|
65
|
+
`INSERT INTO opc_alerts (id, company_id, title, severity, category, status, message, resolved_at, created_at)
|
|
66
|
+
VALUES (?, ?, ?, ?, ?, 'active', ?, '', ?)`,
|
|
67
|
+
db.genId(), params.companyId, params.title, params.severity, params.category, params.message, now,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** 向飞书/企业微信 Webhook 推送一条文本消息(fire-and-forget) */
|
|
72
|
+
function sendWebhook(url: string, text: string, log: (msg: string) => void): void {
|
|
73
|
+
try {
|
|
74
|
+
const isFeishu = url.includes("feishu.cn") || url.includes("larksuite.com");
|
|
75
|
+
const body = isFeishu
|
|
76
|
+
? JSON.stringify({ msg_type: "text", content: { text } })
|
|
77
|
+
: JSON.stringify({ msgtype: "text", text: { content: text } });
|
|
78
|
+
|
|
79
|
+
const parsed = new URL(url);
|
|
80
|
+
const transport = parsed.protocol === "https:" ? https : http;
|
|
81
|
+
const req = transport.request(
|
|
82
|
+
{
|
|
83
|
+
hostname: parsed.hostname,
|
|
84
|
+
port: parsed.port || (parsed.protocol === "https:" ? 443 : 80),
|
|
85
|
+
path: parsed.pathname + parsed.search,
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) },
|
|
88
|
+
},
|
|
89
|
+
(res) => {
|
|
90
|
+
res.resume(); // drain response
|
|
91
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
92
|
+
log(`opc-reminder: Webhook 响应异常 (${res.statusCode})`);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
req.on("error", (err) => log(`opc-reminder: Webhook 请求失败: ${err.message}`));
|
|
97
|
+
req.write(body);
|
|
98
|
+
req.end();
|
|
99
|
+
} catch (err) {
|
|
100
|
+
log(`opc-reminder: Webhook 发送异常: ${err instanceof Error ? err.message : String(err)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ── 检查项 1:税务申报到期提醒 ────────────────────────────────
|
|
105
|
+
|
|
106
|
+
function checkTaxDeadlines(db: OpcDatabase, log: (msg: string) => void, webhookUrl?: string): number {
|
|
107
|
+
let count = 0;
|
|
108
|
+
const rows = db.query(
|
|
109
|
+
`SELECT t.*, c.name as company_name FROM opc_tax_filings t
|
|
110
|
+
LEFT JOIN opc_companies c ON t.company_id = c.id
|
|
111
|
+
WHERE t.status = 'pending' AND t.due_date <= ?`,
|
|
112
|
+
daysAgo(-7), // due within 7 days
|
|
113
|
+
) as (TaxRow & { company_name: string })[];
|
|
114
|
+
|
|
115
|
+
for (const row of rows) {
|
|
116
|
+
const days = daysUntil(row.due_date);
|
|
117
|
+
if (days === null) continue; // 日期格式异常,跳过
|
|
118
|
+
const keyword = `${row.tax_type}-${row.period}`;
|
|
119
|
+
if (alertExists(db, row.company_id, "tax", keyword)) continue;
|
|
120
|
+
|
|
121
|
+
const overdue = days < 0;
|
|
122
|
+
const severity = overdue ? "critical" : days <= 3 ? "warning" : "info";
|
|
123
|
+
const title = overdue
|
|
124
|
+
? `税务申报逾期: ${row.tax_type} (${row.period})`
|
|
125
|
+
: `税务申报即将到期: ${row.tax_type} (${row.period})`;
|
|
126
|
+
const message = overdue
|
|
127
|
+
? `${row.company_name} 的 ${row.tax_type} 申报已逾期 ${Math.abs(days)} 天,请立即处理!到期日: ${row.due_date}`
|
|
128
|
+
: `${row.company_name} 的 ${row.tax_type} 申报将在 ${days} 天后到期 (${row.due_date}),请及时完成申报。`;
|
|
129
|
+
|
|
130
|
+
createAlert(db, { companyId: row.company_id, title, message, severity, category: "tax" });
|
|
131
|
+
count++;
|
|
132
|
+
log(`opc-reminder: 税务提醒 [${row.company_name}] ${title}`);
|
|
133
|
+
if (webhookUrl) sendWebhook(webhookUrl, `【税务提醒】${title}\n${message}`, log);
|
|
134
|
+
}
|
|
135
|
+
return count;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── 检查项 2:合同到期提醒 ─────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
function checkContractExpiry(db: OpcDatabase, log: (msg: string) => void, webhookUrl?: string): number {
|
|
141
|
+
let count = 0;
|
|
142
|
+
const rows = db.query(
|
|
143
|
+
`SELECT t.*, c.name as company_name FROM opc_contracts t
|
|
144
|
+
LEFT JOIN opc_companies c ON t.company_id = c.id
|
|
145
|
+
WHERE t.status = 'active' AND t.end_date != '' AND t.end_date <= ?`,
|
|
146
|
+
daysAgo(-30),
|
|
147
|
+
) as (ContractRow & { company_name: string })[];
|
|
148
|
+
|
|
149
|
+
for (const row of rows) {
|
|
150
|
+
const days = daysUntil(row.end_date);
|
|
151
|
+
if (days === null) continue; // 日期格式异常,跳过
|
|
152
|
+
const keyword = row.title.slice(0, 20);
|
|
153
|
+
if (alertExists(db, row.company_id, "contract", keyword)) continue;
|
|
154
|
+
|
|
155
|
+
const overdue = days < 0;
|
|
156
|
+
const severity = overdue ? "critical" : days <= 7 ? "warning" : "info";
|
|
157
|
+
const title = overdue
|
|
158
|
+
? `合同已过期: ${row.title}`
|
|
159
|
+
: `合同即将到期: ${row.title}`;
|
|
160
|
+
const message = overdue
|
|
161
|
+
? `${row.company_name} 与 ${row.counterparty} 的合同《${row.title}》已于 ${row.end_date} 到期,请及时续签或终止。`
|
|
162
|
+
: `${row.company_name} 与 ${row.counterparty} 的合同《${row.title}》将在 ${days} 天后到期 (${row.end_date}),请提前安排续签。`;
|
|
163
|
+
|
|
164
|
+
createAlert(db, { companyId: row.company_id, title, message, severity, category: "contract" });
|
|
165
|
+
count++;
|
|
166
|
+
log(`opc-reminder: 合同提醒 [${row.company_name}] ${title}`);
|
|
167
|
+
if (webhookUrl) sendWebhook(webhookUrl, `【合同提醒】${title}\n${message}`, log);
|
|
168
|
+
}
|
|
169
|
+
return count;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ── 检查项 3:现金流预警 ──────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
function checkCashFlow(db: OpcDatabase, log: (msg: string) => void, webhookUrl?: string): number {
|
|
175
|
+
let count = 0;
|
|
176
|
+
const start = daysAgo(30);
|
|
177
|
+
const companies = db.query(
|
|
178
|
+
`SELECT id, name FROM opc_companies WHERE status = 'active'`,
|
|
179
|
+
) as CompanyRow[];
|
|
180
|
+
|
|
181
|
+
for (const company of companies) {
|
|
182
|
+
const fin = db.queryOne(
|
|
183
|
+
`SELECT
|
|
184
|
+
COALESCE(SUM(CASE WHEN type='income' THEN amount ELSE 0 END),0) as income,
|
|
185
|
+
COALESCE(SUM(CASE WHEN type='expense' THEN amount ELSE 0 END),0) as expense
|
|
186
|
+
FROM opc_transactions
|
|
187
|
+
WHERE company_id = ? AND transaction_date >= ?`,
|
|
188
|
+
company.id, start,
|
|
189
|
+
) as FinRow | null;
|
|
190
|
+
|
|
191
|
+
if (!fin) continue;
|
|
192
|
+
const net = fin.income - fin.expense;
|
|
193
|
+
if (net >= 0) continue; // 现金流正常,不报警
|
|
194
|
+
|
|
195
|
+
// 净流出超过 5000 元才报警
|
|
196
|
+
if (Math.abs(net) < 5000) continue;
|
|
197
|
+
|
|
198
|
+
if (alertExists(db, company.id, "cashflow", "现金流预警")) continue;
|
|
199
|
+
|
|
200
|
+
const severity = Math.abs(net) > 50000 ? "critical" : "warning";
|
|
201
|
+
createAlert(db, {
|
|
202
|
+
companyId: company.id,
|
|
203
|
+
title: `现金流预警: 近30天净流出 ${Math.abs(net).toLocaleString()} 元`,
|
|
204
|
+
message: `${company.name} 近30天收入 ${fin.income.toLocaleString()} 元,支出 ${fin.expense.toLocaleString()} 元,净流出 ${Math.abs(net).toLocaleString()} 元。请关注资金状况,必要时调整支出计划。`,
|
|
205
|
+
severity,
|
|
206
|
+
category: "cashflow",
|
|
207
|
+
});
|
|
208
|
+
count++;
|
|
209
|
+
log(`opc-reminder: 现金流预警 [${company.name}] 净流出 ${Math.abs(net).toLocaleString()} 元`);
|
|
210
|
+
if (webhookUrl) sendWebhook(webhookUrl, `【现金流预警】${company.name} 近30天净流出 ${Math.abs(net).toLocaleString()} 元,请及时关注资金状况。`, log);
|
|
211
|
+
}
|
|
212
|
+
return count;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ── 检查项 4:投资轮次跟进提醒 ──────────────────────────────────
|
|
216
|
+
|
|
217
|
+
function checkInvestmentRounds(db: OpcDatabase, log: (msg: string) => void, webhookUrl?: string): number {
|
|
218
|
+
let count = 0;
|
|
219
|
+
// 找出 close_date 在7天内的活跃融资轮
|
|
220
|
+
const rows = db.query(
|
|
221
|
+
`SELECT r.*, c.name as company_name FROM opc_investment_rounds r
|
|
222
|
+
LEFT JOIN opc_companies c ON r.company_id = c.id
|
|
223
|
+
WHERE r.status IN ('planning','open') AND r.close_date != '' AND r.close_date <= ?`,
|
|
224
|
+
daysAgo(-7),
|
|
225
|
+
) as ({ id: string; company_id: string; round_name: string; close_date: string; company_name: string })[];
|
|
226
|
+
|
|
227
|
+
for (const row of rows) {
|
|
228
|
+
const days = daysUntil(row.close_date);
|
|
229
|
+
if (days === null) continue; // 日期格式异常,跳过
|
|
230
|
+
const keyword = row.round_name.slice(0, 15);
|
|
231
|
+
if (alertExists(db, row.company_id, "investment", keyword)) continue;
|
|
232
|
+
|
|
233
|
+
const severity = days < 0 ? "warning" : "info";
|
|
234
|
+
const title = days < 0
|
|
235
|
+
? `融资轮次已超预期关闭日: ${row.round_name}`
|
|
236
|
+
: `融资轮次即将截止: ${row.round_name}`;
|
|
237
|
+
const message = days < 0
|
|
238
|
+
? `${row.company_name} 的${row.round_name}计划关闭日 (${row.close_date}) 已过,请更新融资进度或调整截止日期。`
|
|
239
|
+
: `${row.company_name} 的${row.round_name}将在 ${days} 天后截止 (${row.close_date}),请跟进投资人沟通进度。`;
|
|
240
|
+
|
|
241
|
+
createAlert(db, { companyId: row.company_id, title, message, severity, category: "investment" });
|
|
242
|
+
count++;
|
|
243
|
+
log(`opc-reminder: 融资提醒 [${row.company_name}] ${title}`);
|
|
244
|
+
if (webhookUrl) sendWebhook(webhookUrl, `【融资提醒】${title}\n${message}`, log);
|
|
245
|
+
}
|
|
246
|
+
return count;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ── 主扫描函数 ─────────────────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
export function runReminderScan(db: OpcDatabase, log: (msg: string) => void, webhookUrl?: string): void {
|
|
252
|
+
try {
|
|
253
|
+
let total = 0;
|
|
254
|
+
total += checkTaxDeadlines(db, log, webhookUrl);
|
|
255
|
+
total += checkContractExpiry(db, log, webhookUrl);
|
|
256
|
+
total += checkCashFlow(db, log, webhookUrl);
|
|
257
|
+
total += checkInvestmentRounds(db, log, webhookUrl);
|
|
258
|
+
if (total > 0) {
|
|
259
|
+
log(`opc-reminder: 本次扫描生成 ${total} 条提醒`);
|
|
260
|
+
}
|
|
261
|
+
} catch (err) {
|
|
262
|
+
log(`opc-reminder: 扫描异常: ${err instanceof Error ? err.message : String(err)}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** 启动定时提醒服务,返回停止函数 */
|
|
267
|
+
export function startReminderService(
|
|
268
|
+
db: OpcDatabase,
|
|
269
|
+
log: (msg: string) => void,
|
|
270
|
+
webhookUrl?: string,
|
|
271
|
+
intervalMs = 3600_000, // 默认每小时扫描一次
|
|
272
|
+
): () => void {
|
|
273
|
+
// 启动时立即扫描一次(延迟30秒,等数据库稳定)
|
|
274
|
+
const initTimer = setTimeout(() => {
|
|
275
|
+
log("opc-reminder: 首次扫描启动");
|
|
276
|
+
runReminderScan(db, log, webhookUrl);
|
|
277
|
+
}, 30_000);
|
|
278
|
+
|
|
279
|
+
// 周期性扫描
|
|
280
|
+
const interval = setInterval(() => {
|
|
281
|
+
runReminderScan(db, log, webhookUrl);
|
|
282
|
+
}, intervalMs);
|
|
283
|
+
|
|
284
|
+
return () => {
|
|
285
|
+
clearTimeout(initTimer);
|
|
286
|
+
clearInterval(interval);
|
|
287
|
+
log("opc-reminder: 提醒服务已停止");
|
|
288
|
+
};
|
|
289
|
+
}
|
package/src/opc/types.ts
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 星环OPC中心 — 核心业务类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** 公司状态流转: pending → active → suspended → acquired → packaged → terminated */
|
|
6
|
+
export type OpcCompanyStatus =
|
|
7
|
+
| "pending"
|
|
8
|
+
| "active"
|
|
9
|
+
| "suspended"
|
|
10
|
+
| "acquired"
|
|
11
|
+
| "packaged"
|
|
12
|
+
| "terminated";
|
|
13
|
+
|
|
14
|
+
/** 一人公司 */
|
|
15
|
+
export type OpcCompany = {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
industry: string;
|
|
19
|
+
owner_name: string;
|
|
20
|
+
owner_contact: string;
|
|
21
|
+
status: OpcCompanyStatus;
|
|
22
|
+
registered_capital: number;
|
|
23
|
+
description: string;
|
|
24
|
+
created_at: string;
|
|
25
|
+
updated_at: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** AI 员工角色 */
|
|
29
|
+
export type OpcEmployeeRole =
|
|
30
|
+
| "finance"
|
|
31
|
+
| "legal"
|
|
32
|
+
| "hr"
|
|
33
|
+
| "media"
|
|
34
|
+
| "project"
|
|
35
|
+
| "general";
|
|
36
|
+
|
|
37
|
+
/** AI 员工 */
|
|
38
|
+
export type OpcEmployee = {
|
|
39
|
+
id: string;
|
|
40
|
+
company_id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
role: OpcEmployeeRole;
|
|
43
|
+
skills: string;
|
|
44
|
+
status: "active" | "inactive";
|
|
45
|
+
created_at: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** 交易类型 */
|
|
49
|
+
export type OpcTransactionType = "income" | "expense";
|
|
50
|
+
|
|
51
|
+
/** 交易分类 */
|
|
52
|
+
export type OpcTransactionCategory =
|
|
53
|
+
| "service_income"
|
|
54
|
+
| "product_income"
|
|
55
|
+
| "investment_income"
|
|
56
|
+
| "salary"
|
|
57
|
+
| "rent"
|
|
58
|
+
| "utilities"
|
|
59
|
+
| "marketing"
|
|
60
|
+
| "tax"
|
|
61
|
+
| "supplies"
|
|
62
|
+
| "other";
|
|
63
|
+
|
|
64
|
+
/** 交易记录 */
|
|
65
|
+
export type OpcTransaction = {
|
|
66
|
+
id: string;
|
|
67
|
+
company_id: string;
|
|
68
|
+
type: OpcTransactionType;
|
|
69
|
+
category: OpcTransactionCategory;
|
|
70
|
+
amount: number;
|
|
71
|
+
description: string;
|
|
72
|
+
counterparty: string;
|
|
73
|
+
transaction_date: string;
|
|
74
|
+
created_at: string;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** 客户/联系人 */
|
|
78
|
+
export type OpcContact = {
|
|
79
|
+
id: string;
|
|
80
|
+
company_id: string;
|
|
81
|
+
name: string;
|
|
82
|
+
phone: string;
|
|
83
|
+
email: string;
|
|
84
|
+
company_name: string;
|
|
85
|
+
tags: string;
|
|
86
|
+
notes: string;
|
|
87
|
+
last_contact_date: string;
|
|
88
|
+
created_at: string;
|
|
89
|
+
updated_at: string;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// ── Phase 2 类型 ─────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
/** 发票状态 */
|
|
95
|
+
export type OpcInvoiceStatus = "draft" | "issued" | "paid" | "void";
|
|
96
|
+
|
|
97
|
+
/** 发票 */
|
|
98
|
+
export type OpcInvoice = {
|
|
99
|
+
id: string;
|
|
100
|
+
company_id: string;
|
|
101
|
+
invoice_number: string;
|
|
102
|
+
type: "sales" | "purchase";
|
|
103
|
+
counterparty: string;
|
|
104
|
+
amount: number;
|
|
105
|
+
tax_rate: number;
|
|
106
|
+
tax_amount: number;
|
|
107
|
+
total_amount: number;
|
|
108
|
+
status: OpcInvoiceStatus;
|
|
109
|
+
issue_date: string;
|
|
110
|
+
notes: string;
|
|
111
|
+
created_at: string;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** 税务申报记录 */
|
|
115
|
+
export type OpcTaxFiling = {
|
|
116
|
+
id: string;
|
|
117
|
+
company_id: string;
|
|
118
|
+
period: string;
|
|
119
|
+
tax_type: "vat" | "income_tax" | "other";
|
|
120
|
+
revenue: number;
|
|
121
|
+
deductible: number;
|
|
122
|
+
tax_amount: number;
|
|
123
|
+
status: "pending" | "filed" | "paid";
|
|
124
|
+
due_date: string;
|
|
125
|
+
filed_date: string;
|
|
126
|
+
notes: string;
|
|
127
|
+
created_at: string;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/** 合同状态 */
|
|
131
|
+
export type OpcContractStatus = "draft" | "active" | "expired" | "terminated" | "disputed";
|
|
132
|
+
|
|
133
|
+
/** 合同 */
|
|
134
|
+
export type OpcContract = {
|
|
135
|
+
id: string;
|
|
136
|
+
company_id: string;
|
|
137
|
+
title: string;
|
|
138
|
+
counterparty: string;
|
|
139
|
+
contract_type: string;
|
|
140
|
+
amount: number;
|
|
141
|
+
start_date: string;
|
|
142
|
+
end_date: string;
|
|
143
|
+
status: OpcContractStatus;
|
|
144
|
+
key_terms: string;
|
|
145
|
+
risk_notes: string;
|
|
146
|
+
reminder_date: string;
|
|
147
|
+
created_at: string;
|
|
148
|
+
updated_at: string;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/** 人力资源记录 */
|
|
152
|
+
export type OpcHrRecord = {
|
|
153
|
+
id: string;
|
|
154
|
+
company_id: string;
|
|
155
|
+
employee_name: string;
|
|
156
|
+
position: string;
|
|
157
|
+
salary: number;
|
|
158
|
+
social_insurance: number;
|
|
159
|
+
housing_fund: number;
|
|
160
|
+
start_date: string;
|
|
161
|
+
end_date: string;
|
|
162
|
+
contract_type: "full_time" | "part_time" | "contractor" | "intern";
|
|
163
|
+
status: "active" | "resigned" | "terminated";
|
|
164
|
+
notes: string;
|
|
165
|
+
created_at: string;
|
|
166
|
+
updated_at: string;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** 新媒体内容 */
|
|
170
|
+
export type OpcMediaContent = {
|
|
171
|
+
id: string;
|
|
172
|
+
company_id: string;
|
|
173
|
+
title: string;
|
|
174
|
+
platform: string;
|
|
175
|
+
content_type: "article" | "short_video" | "image" | "live" | "other";
|
|
176
|
+
content: string;
|
|
177
|
+
status: "draft" | "scheduled" | "published" | "archived";
|
|
178
|
+
scheduled_date: string;
|
|
179
|
+
published_date: string;
|
|
180
|
+
tags: string;
|
|
181
|
+
metrics: string;
|
|
182
|
+
created_at: string;
|
|
183
|
+
updated_at: string;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/** 项目状态 */
|
|
187
|
+
export type OpcProjectStatus = "planning" | "active" | "paused" | "completed" | "cancelled";
|
|
188
|
+
|
|
189
|
+
/** 项目 */
|
|
190
|
+
export type OpcProject = {
|
|
191
|
+
id: string;
|
|
192
|
+
company_id: string;
|
|
193
|
+
name: string;
|
|
194
|
+
description: string;
|
|
195
|
+
status: OpcProjectStatus;
|
|
196
|
+
start_date: string;
|
|
197
|
+
end_date: string;
|
|
198
|
+
budget: number;
|
|
199
|
+
spent: number;
|
|
200
|
+
created_at: string;
|
|
201
|
+
updated_at: string;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/** 项目任务 */
|
|
205
|
+
export type OpcTask = {
|
|
206
|
+
id: string;
|
|
207
|
+
project_id: string;
|
|
208
|
+
company_id: string;
|
|
209
|
+
title: string;
|
|
210
|
+
description: string;
|
|
211
|
+
assignee: string;
|
|
212
|
+
priority: "low" | "medium" | "high" | "urgent";
|
|
213
|
+
status: "todo" | "in_progress" | "review" | "done";
|
|
214
|
+
due_date: string;
|
|
215
|
+
hours_estimated: number;
|
|
216
|
+
hours_actual: number;
|
|
217
|
+
created_at: string;
|
|
218
|
+
updated_at: string;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// ── Phase 3 类型 ─────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
/** 融资轮次 */
|
|
224
|
+
export type OpcInvestmentRound = {
|
|
225
|
+
id: string;
|
|
226
|
+
company_id: string;
|
|
227
|
+
round_name: string;
|
|
228
|
+
amount: number;
|
|
229
|
+
valuation_pre: number;
|
|
230
|
+
valuation_post: number;
|
|
231
|
+
status: "planning" | "fundraising" | "closed" | "cancelled";
|
|
232
|
+
lead_investor: string;
|
|
233
|
+
close_date: string;
|
|
234
|
+
notes: string;
|
|
235
|
+
created_at: string;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/** 投资人 */
|
|
239
|
+
export type OpcInvestor = {
|
|
240
|
+
id: string;
|
|
241
|
+
round_id: string;
|
|
242
|
+
company_id: string;
|
|
243
|
+
name: string;
|
|
244
|
+
type: "individual" | "institutional" | "angel" | "vc" | "strategic";
|
|
245
|
+
amount: number;
|
|
246
|
+
equity_percent: number;
|
|
247
|
+
contact: string;
|
|
248
|
+
notes: string;
|
|
249
|
+
created_at: string;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
/** 服务项目 */
|
|
253
|
+
export type OpcService = {
|
|
254
|
+
id: string;
|
|
255
|
+
company_id: string;
|
|
256
|
+
name: string;
|
|
257
|
+
category: string;
|
|
258
|
+
provider: string;
|
|
259
|
+
unit_price: number;
|
|
260
|
+
billing_cycle: "monthly" | "quarterly" | "yearly" | "one_time";
|
|
261
|
+
status: "active" | "suspended" | "terminated";
|
|
262
|
+
description: string;
|
|
263
|
+
created_at: string;
|
|
264
|
+
updated_at: string;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
/** 采购订单 */
|
|
268
|
+
export type OpcProcurementOrder = {
|
|
269
|
+
id: string;
|
|
270
|
+
service_id: string;
|
|
271
|
+
company_id: string;
|
|
272
|
+
title: string;
|
|
273
|
+
amount: number;
|
|
274
|
+
status: "pending" | "approved" | "paid" | "cancelled";
|
|
275
|
+
order_date: string;
|
|
276
|
+
delivery_date: string;
|
|
277
|
+
notes: string;
|
|
278
|
+
created_at: string;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/** 里程碑 */
|
|
282
|
+
export type OpcMilestone = {
|
|
283
|
+
id: string;
|
|
284
|
+
company_id: string;
|
|
285
|
+
title: string;
|
|
286
|
+
category: "business" | "product" | "finance" | "legal" | "team" | "other";
|
|
287
|
+
target_date: string;
|
|
288
|
+
completed_date: string;
|
|
289
|
+
status: "pending" | "in_progress" | "completed" | "cancelled";
|
|
290
|
+
description: string;
|
|
291
|
+
created_at: string;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
/** 生命周期事件 */
|
|
295
|
+
export type OpcLifecycleEvent = {
|
|
296
|
+
id: string;
|
|
297
|
+
company_id: string;
|
|
298
|
+
event_type: string;
|
|
299
|
+
title: string;
|
|
300
|
+
event_date: string;
|
|
301
|
+
impact: string;
|
|
302
|
+
description: string;
|
|
303
|
+
created_at: string;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
/** 运营指标 */
|
|
307
|
+
export type OpcMetric = {
|
|
308
|
+
id: string;
|
|
309
|
+
company_id: string;
|
|
310
|
+
name: string;
|
|
311
|
+
value: number;
|
|
312
|
+
unit: string;
|
|
313
|
+
category: string;
|
|
314
|
+
recorded_at: string;
|
|
315
|
+
notes: string;
|
|
316
|
+
created_at: string;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/** 告警 */
|
|
320
|
+
export type OpcAlert = {
|
|
321
|
+
id: string;
|
|
322
|
+
company_id: string;
|
|
323
|
+
title: string;
|
|
324
|
+
severity: "info" | "warning" | "critical";
|
|
325
|
+
category: string;
|
|
326
|
+
status: "active" | "acknowledged" | "resolved";
|
|
327
|
+
message: string;
|
|
328
|
+
resolved_at: string;
|
|
329
|
+
created_at: string;
|
|
330
|
+
};
|