提交 dc447146 authored 作者: 王鹏飞's avatar 王鹏飞

feat: add workflow management and user utilities

- Implemented manual stage transitions and approval rules in workflow.js. - Added current user retrieval utility in current-user.js. - Refactored logs controller to simplify error handling and improve readability. - Introduced validation for logs routes using zod. - Enhanced wechat controller with improved error handling and validation. - Created wx-chart controller and routes for managing chart data. - Added test-watch.mjs for application loading confirmation.
上级 9e258d66
SERVER_PORT=4101
MONGODB_URI=
DATABASE_URL=
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=
MYSQL_DATABASE=com_dms
DINGTALK_APP_ID=
DINGTALK_AGENT_ID=
DINGTALK_APP_KEY=
DINGTALK_APP_SECRET=
DINGTALK_CORP_ID=
DINGTALK_STREAM_DEBUG=false
DINGTALK_PROJECT_APPROVAL_PROCESS_CODE=
DINGTALK_CONTRACT_APPROVAL_PROCESS_CODE=
DINGTALK_ACCEPTANCE_APPROVAL_PROCESS_CODE=
WX_APPID_1=
WX_SECRET_1=
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
node_modules/ node_modules/
# Environment variables # Environment variables
.env
.env.local .env.local
.env.*.local .env.*.local
......
# ezijing-node-server # ezijing-node-server
Modern Node.js API server for WeChat services and log collection. Modern Node.js API server for DMS, WeChat services, chart data, and log collection.
## Quick Start ## Quick Start
...@@ -8,9 +8,6 @@ Modern Node.js API server for WeChat services and log collection. ...@@ -8,9 +8,6 @@ Modern Node.js API server for WeChat services and log collection.
# Install dependencies # Install dependencies
npm install npm install
# Start MongoDB (required)
mongod --dbpath /path/to/data
# Development (with hot reload) # Development (with hot reload)
npm run dev npm run dev
...@@ -27,10 +24,12 @@ src/ ...@@ -27,10 +24,12 @@ src/
├── config.js # Configuration ├── config.js # Configuration
├── lib/ # Shared utilities ├── lib/ # Shared utilities
│ ├── logger.js # Pino logger │ ├── logger.js # Pino logger
│ ├── db.js # MongoDB connection │ ├── mongo.js # MongoDB connection
│ └── file.js # File utilities │ └── file.js # File utilities
├── middleware/ # Global middleware ├── middleware/ # Global middleware
├── db/ # MySQL Drizzle runtime client
└── modules/ # Feature modules └── modules/ # Feature modules
├── dms/ # DMS app
├── wechat/ # WeChat SDK ├── wechat/ # WeChat SDK
├── wx-chart/ # WeChat chart data ├── wx-chart/ # WeChat chart data
└── logs/ # Log collection └── logs/ # Log collection
...@@ -99,7 +98,17 @@ SERVER_PORT=4101 ...@@ -99,7 +98,17 @@ SERVER_PORT=4101
DATA_DIR=../node-server-data DATA_DIR=../node-server-data
# MongoDB # MongoDB
MONGODB_URI=mongodb://localhost:27017/ezijing-logs MONGODB_URI=
# MySQL / Drizzle
DATABASE_URL=mysql://root:password@127.0.0.1:3306/com_dms
# Legacy MySQL fallback when DATABASE_URL is not set
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=
MYSQL_DATABASE=com_dms
# WeChat config (numbered format) # WeChat config (numbered format)
WX_APPID_1=your_appid WX_APPID_1=your_appid
......
import 'dotenv/config'
import { defineConfig } from 'drizzle-kit'
const databaseUrl = process.env.DATABASE_URL
export default defineConfig({
dialect: 'mysql',
schema: './src/modules/dms/**/schema.js',
out: './migrations/drizzle',
dbCredentials: databaseUrl ? {
url: databaseUrl,
} : {
host: process.env.MYSQL_HOST || '127.0.0.1',
port: parseInt(process.env.MYSQL_PORT || '3306', 10) || 3306,
user: process.env.MYSQL_USER || 'root',
password: process.env.MYSQL_PASSWORD || undefined,
database: process.env.MYSQL_DATABASE || 'com_dms',
},
})
-- DMS database bootstrap.
-- Do not execute this file without explicit confirmation.
CREATE DATABASE IF NOT EXISTS com_dms DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `product_list` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(120) NOT NULL COMMENT '产品名称',
`status` int NOT NULL DEFAULT 10 COMMENT '产品状态: 0停用 10启用',
`description` text COMMENT '产品说明',
`operator_user_id` varchar(64) COMMENT '最后操作人系统用户ID',
`operator_name` varchar(120) COMMENT '最后操作人姓名',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_products_name` (`name`),
KEY `idx_products_status` (`status`),
KEY `idx_products_operator_user_id` (`operator_user_id`)
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品信息';
CREATE TABLE IF NOT EXISTS `project_list` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_code` varchar(64) NOT NULL,
`name` varchar(255) NOT NULL,
`province` varchar(120),
`city` varchar(120),
`school_name` varchar(255),
`department_name` varchar(255),
`product_id` bigint unsigned COMMENT '关联产品ID',
`product_name` varchar(255),
`owner_user_id` varchar(64),
`owner_name` varchar(120),
`owner_mobile` varchar(64),
`owner_ding_user_id` varchar(128),
`contact_name` varchar(120),
`contact_title` varchar(120),
`contact_phone` varchar(64),
`solution` text,
`stage` int NOT NULL DEFAULT 10,
`status` int NOT NULL DEFAULT 0 COMMENT '项目状态: 0进行中 10审批中 20已归档',
`description` text,
`operator_user_id` varchar(64) COMMENT '最后操作人系统用户ID',
`operator_name` varchar(120) COMMENT '最后操作人姓名',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_projects_project_code` (`project_code`),
KEY `idx_projects_stage_status` (`stage`, `status`),
KEY `idx_projects_product_id` (`product_id`),
KEY `idx_projects_owner_user_id` (`owner_user_id`),
KEY `idx_projects_owner_mobile` (`owner_mobile`),
KEY `idx_projects_operator_user_id` (`operator_user_id`)
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目主表';
CREATE TABLE IF NOT EXISTS `case_list` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(255) NOT NULL COMMENT '案例名称',
`description` text COMMENT '案例简介',
`product_id` bigint unsigned COMMENT '关联产品ID',
`product_name` varchar(255) COMMENT '产品名称',
`files` longtext COMMENT '案例附件JSON',
`operator_user_id` varchar(64) COMMENT '最后操作人系统用户ID',
`operator_name` varchar(120) COMMENT '最后操作人姓名',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_cases_product_id` (`product_id`),
KEY `idx_cases_operator_user_id` (`operator_user_id`)
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='案例信息';
CREATE TABLE IF NOT EXISTS `project_initiations` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint unsigned NOT NULL,
`application_file_url` varchar(500),
`argument_file_url` varchar(500),
`project_amount` decimal(14,2),
`fund_source` varchar(255),
`execution_plan` text,
`expected_tender_time` varchar(120),
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_initiations_project_id` (`project_id`),
CONSTRAINT `project_initiations_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目立项信息';
CREATE TABLE IF NOT EXISTS `project_procurements` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint unsigned NOT NULL,
`tender_owner` varchar(120),
`business_params` text,
`technical_params` text,
`intention_publicity` varchar(255),
`main_bid_owner` varchar(120),
`companion_bidders` text,
`formal_bid_status` varchar(120),
`winning_notice_file_url` varchar(500),
`bid_archive_file_url` varchar(500),
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_procurements_project_id` (`project_id`),
CONSTRAINT `project_procurements_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目招投标信息';
CREATE TABLE IF NOT EXISTS `project_contracts` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint unsigned NOT NULL,
`contract_no` varchar(128),
`contract_name` varchar(255),
`amount` decimal(14,2),
`drafter` varchar(120),
`archive_file_url` varchar(500),
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_contracts_project_id` (`project_id`),
CONSTRAINT `project_contracts_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目合同信息';
CREATE TABLE IF NOT EXISTS `project_deliveries` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint unsigned NOT NULL,
`delivery_address` varchar(255),
`delivery_contact` varchar(120),
`delivery_contact_phone` varchar(64),
`delivery_note` text,
`completed_at` datetime,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_deliveries_project_id` (`project_id`),
CONSTRAINT `project_deliveries_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目交付信息';
CREATE TABLE IF NOT EXISTS `project_acceptances` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint unsigned NOT NULL,
`acceptance_report_url` varchar(500),
`acceptance_note` text,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_acceptances_project_id` (`project_id`),
CONSTRAINT `project_acceptances_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目验收信息';
CREATE TABLE IF NOT EXISTS `project_timelines` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint unsigned NOT NULL,
`project_code` varchar(64) NOT NULL,
`title` varchar(255) NOT NULL,
`description` text,
`stage` int NOT NULL,
`status` int NOT NULL,
`operator_name` varchar(120) COMMENT '操作人姓名',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_project_timelines_project_id` (`project_id`),
KEY `idx_project_timelines_project_code` (`project_code`),
KEY `idx_project_timelines_created_at` (`created_at`),
CONSTRAINT `project_timelines_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目时间线记录';
CREATE TABLE IF NOT EXISTS `project_approval_instances` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`approval_key` enum('project_approval','contract_approval','acceptance_approval') NOT NULL,
`process_code` varchar(128) NOT NULL,
`process_instance_id` varchar(128),
`project_id` bigint unsigned NOT NULL,
`project_code` varchar(64) NOT NULL,
`originator_user_id` varchar(64),
`originator_ding_user_id` varchar(128) NOT NULL,
`status` enum('created','running','approved','rejected','terminated','deleted','failed') NOT NULL DEFAULT 'created',
`form_snapshot` json,
`result_snapshot` json,
`error_message` text,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_approval_instances_process_instance_id` (`process_instance_id`),
KEY `idx_approval_instances_project_id` (`project_id`),
KEY `idx_approval_instances_project_code` (`project_code`),
KEY `idx_approval_instances_status` (`status`),
CONSTRAINT `project_approval_instances_project_id_project_list_id_fk` FOREIGN KEY (`project_id`) REFERENCES `project_list` (`id`) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目审批实例';
CREATE TABLE IF NOT EXISTS `dingtalk_user_bindings` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`system_user_id` varchar(64) NOT NULL,
`ding_user_id` varchar(128) NOT NULL,
`name` varchar(120),
`mobile` varchar(64),
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_dingtalk_user_bindings_system_user_id` (`system_user_id`),
UNIQUE KEY `uk_dingtalk_user_bindings_ding_user_id` (`ding_user_id`)
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钉钉用户绑定关系';
差异被折叠。
{
"version": "7",
"dialect": "mysql",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1776998400000,
"tag": "0000_init_dms_schema",
"breakpoints": true
}
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论