wps-gantt — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited wps-gantt (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
任务列表 → Excel甘特图。不用Project也能做项目排期。
wps-docx-writer每个任务需要:
from openpyxl import Workbook
from openpyxl.styles import (Font, Alignment, PatternFill,
Border, Side, numbers)
from openpyxl.utils import get_column_letter
from datetime import datetime, timedelta
import os
def create_gantt(tasks, output_path=None):
"""
tasks = [
{'name': '需求分析', 'start': '2026-04-01', 'end': '2026-04-07',
'owner': '张三', 'progress': 100},
{'name': '系统设计', 'start': '2026-04-08', 'end': '2026-04-14',
'owner': '李四', 'progress': 60},
...
]
"""
wb = Workbook()
ws = wb.active
ws.title = "项目甘特图"
# 计算日期范围
all_dates = []
for t in tasks:
all_dates.append(datetime.strptime(t['start'], '%Y-%m-%d'))
all_dates.append(datetime.strptime(t['end'], '%Y-%m-%d'))
min_date = min(all_dates)
max_date = max(all_dates)
total_days = (max_date - min_date).days + 1
# 样式
header_fill = PatternFill('solid', fgColor='2C3E50')
header_font = Font(name='微软雅黑', size=10, bold=True, color='FFFFFF')
bar_fill = PatternFill('solid', fgColor='3498DB')
done_fill = PatternFill('solid', fgColor='2ECC71')
milestone_fill = PatternFill('solid', fgColor='E74C3C')
today_fill = PatternFill('solid', fgColor='F39C12')
thin = Side(style='thin', color='D5D8DC')
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# 左侧列标题
left_headers = ['序号', '任务名称', '负责人', '开始', '结束', '进度']
for col, h in enumerate(left_headers, 1):
cell = ws.cell(row=1, column=col, value=h)
cell.font = header_font
cell.fill = header_fill
cell.alignment = Alignment(horizontal='center')
# 列宽
ws.column_dimensions['A'].width = 5
ws.column_dimensions['B'].width = 20
ws.column_dimensions['C'].width = 8
ws.column_dimensions['D'].width = 11
ws.column_dimensions['E'].width = 11
ws.column_dimensions['F'].width = 7
# 日期列标题(每天一列或按周)
date_start_col = len(left_headers) + 1
use_weekly = total_days > 60
if use_weekly:
# 按周显示
week_start = min_date - timedelta(days=min_date.weekday())
col = date_start_col
while week_start <= max_date:
cell = ws.cell(row=1, column=col,
value=week_start.strftime('%m/%d'))
cell.font = Font(name='微软雅黑', size=8, color='FFFFFF')
cell.fill = header_fill
cell.alignment = Alignment(horizontal='center')
ws.column_dimensions[get_column_letter(col)].width = 5
week_start += timedelta(days=7)
col += 1
else:
for d in range(total_days):
date = min_date + timedelta(days=d)
col = date_start_col + d
cell = ws.cell(row=1, column=col, value=date.strftime('%m/%d'))
cell.font = Font(name='微软雅黑', size=7, color='FFFFFF')
cell.fill = header_fill
cell.alignment = Alignment(horizontal='center', text_rotation=90)
ws.column_dimensions[get_column_letter(col)].width = 3.5
# 任务行
body_font = Font(name='微软雅黑', size=10)
for row_idx, task in enumerate(tasks, 2):
ws.cell(row=row_idx, column=1, value=row_idx-1).font = body_font
ws.cell(row=row_idx, column=2, value=task['name']).font = body_font
ws.cell(row=row_idx, column=3,
value=task.get('owner', '')).font = body_font
ws.cell(row=row_idx, column=4, value=task['start']).font = body_font
ws.cell(row=row_idx, column=5, value=task['end']).font = body_font
progress = task.get('progress', 0)
ws.cell(row=row_idx, column=6,
value=f'{progress}%').font = body_font
# 画甘特条
start = datetime.strptime(task['start'], '%Y-%m-%d')
end = datetime.strptime(task['end'], '%Y-%m-%d')
if use_weekly:
week_start = min_date - timedelta(days=min_date.weekday())
s_col = date_start_col + (start - week_start).days // 7
e_col = date_start_col + (end - week_start).days // 7
else:
s_col = date_start_col + (start - min_date).days
e_col = date_start_col + (end - min_date).days
for c in range(s_col, e_col + 1):
cell = ws.cell(row=row_idx, column=c)
if progress == 100:
cell.fill = done_fill
else:
cell.fill = bar_fill
cell.border = border
ws.row_dimensions[1].height = 30
ws.freeze_panes = 'G2' # 冻结左侧列和标题行
if not output_path:
output_path = '项目甘特图.xlsx'
wb.save(output_path)
return os.path.abspath(output_path)# 生成甘特图
/wps-gantt 帮我做个项目甘特图,需求分析2周→设计1周→开发4周→测试2周→上线
# 从数据生成
/wps-gantt 用tasks.xlsx里的任务列表生成甘特图
# 更新进度
/wps-gantt 更新项目甘特图的进度~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.