update
This commit is contained in:
parent
0bb4483436
commit
079ee6f0f4
|
@ -0,0 +1,2 @@
|
|||
.venv/
|
||||
.idea/
|
|
@ -0,0 +1,26 @@
|
|||
FROM python:3.12-slim
|
||||
LABEL authors="lxy"
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 复制依赖文件
|
||||
COPY requirements.txt .
|
||||
|
||||
# 安装依赖
|
||||
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
|
||||
|
||||
# 复制项目文件
|
||||
COPY . .
|
||||
|
||||
# 设置环境变量
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# 运行迁移(可选)
|
||||
# RUN python manage.py migrate
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 启动 Django 开发服务器
|
||||
CMD ["python", "manage.py", "runserver", "0.0.0.0:8080"]
|
318
README.md
318
README.md
|
@ -1,2 +1,318 @@
|
|||
# Photoshop
|
||||
# 开源项目评分标准说明文档
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本评分系统旨在全面评估开源项目的质量、活跃度和成熟度。评分体系包含多个维度,每个维度都有其特定的评分标准和改进建议。
|
||||
|
||||
## 2. 评分维度
|
||||
|
||||
### 2.1 基础要素评分
|
||||
|
||||
## 开源许可证评分
|
||||
|
||||
- **满分标准**: 使用标准开源许可证(MIT/Apache/GPL等) - 100分
|
||||
- **不合格标准**: 无许可证 - 0分
|
||||
- **改进建议**: 建议使用标准的开源许可证以明确项目的使用条款和限制
|
||||
|
||||
### 2.2 问题处理评分
|
||||
|
||||
## 未解决issue评分
|
||||
|
||||
- **优秀**: 未解决issue较少 (80-100分)
|
||||
- **良好**: 未解决issue较多 (60-80分)
|
||||
- **待改进**: 未解决issue很多 (0-60分)
|
||||
- **改进建议**: 保持适度的未解决issue数量,及时处理重要issue
|
||||
|
||||
## 已解决issue评分
|
||||
|
||||
- **优秀**: 已解决issue很多 (80-100分)
|
||||
- **良好**: 已解决issue较多 (60-80分)
|
||||
- **待改进**: 已解决issue较少 (0-60分)
|
||||
- **改进建议**: 提高issue解决率,保持良好的问题跟踪和处理机制
|
||||
|
||||
### 2.3 安全性评分
|
||||
|
||||
包含四个等级的安全警告评分:
|
||||
|
||||
- 低风险安全警告 (100分/0分)
|
||||
- 中等风险安全警告 (100分/0分)
|
||||
- 高风险安全警告 (100分/0分)
|
||||
- 严重风险安全警告 (100分/0分)
|
||||
|
||||
每个等级的评分标准:
|
||||
|
||||
- **满分标准**: 无相应级别警告
|
||||
- **不合格标准**: 存在多个相应级别警告
|
||||
- **改进建议**: 根据风险等级优先处理安全问题,确保项目安全性
|
||||
|
||||
### 2.4 社区活跃度评分
|
||||
|
||||
## Star数评分
|
||||
|
||||
- **优秀**: Star很多 (80-100分)
|
||||
- **良好**: Star较多 (60-80分)
|
||||
- **待改进**: Star较少 (0-60分)
|
||||
- **改进建议**: 提高项目影响力,完善文档和功能以吸引更多用户关注
|
||||
|
||||
## 关注者评分
|
||||
|
||||
- **优秀**: 关注者很多 (80-100分)
|
||||
- **良好**: 关注者较多 (60-80分)
|
||||
- **待改进**: 关注者较少 (0-60分)
|
||||
- **改进建议**: 增加项目曝光度,保持更新以维持用户关注度
|
||||
|
||||
## Fork数评分
|
||||
|
||||
- **优秀**: 分支数很多 (80-100分)
|
||||
- **良好**: 分支数较多 (60-80分)
|
||||
- **待改进**: 分支数较少 (0-60分)
|
||||
- **改进建议**: 鼓励社区贡献,完善协作指南以促进分支开发
|
||||
|
||||
### 2.5 开发活跃度评分
|
||||
|
||||
## 提交次数评分
|
||||
|
||||
- **优秀**: 提交次数很多 (80-100分)
|
||||
- **良好**: 提交次数较多 (60-80分)
|
||||
- **待改进**: 提交次数较少 (0-60分)
|
||||
- **改进建议**: 保持稳定的开发活跃度,定期提交代码更新
|
||||
|
||||
## 开发者数量评分
|
||||
|
||||
- **优秀**: 开发者数量很多 (80-100分)
|
||||
- **良好**: 开发者数量较多 (60-80分)
|
||||
- **待改进**: 开发者数量较少 (0-60分)
|
||||
- **改进建议**: 扩大开发团队,培养核心贡献者
|
||||
|
||||
## 发布版本数评分
|
||||
|
||||
- **优秀**: 发布版本数很多 (80-100分)
|
||||
- **良好**: 发布版本数较多 (60-80分)
|
||||
- **待改进**: 发布版本数较少 (0-60分)
|
||||
- **改进建议**: 建立规范的版本发布流程,保持稳定的迭代节奏
|
||||
|
||||
## 3. 总体成熟度评分
|
||||
|
||||
- **优秀**: 项目成熟,维护良好 (80-100分)
|
||||
- **良好**: 项目稳定,有待改进 (60-80分)
|
||||
- **一般**: 项目基本可用,需要加强维护 (40-60分)
|
||||
- **待改进**: 项目初期或疏于维护 (0-40分)
|
||||
- **改进建议**: 根据各项分值改进薄弱环节,提高项目整体质量
|
||||
|
||||
## 4. 评分使用建议
|
||||
|
||||
1. 定期进行评分,跟踪项目发展状况
|
||||
2. 针对低分项优先改进
|
||||
3. 关注安全警告,及时处理安全问题
|
||||
4. 持续完善文档和社区建设
|
||||
5. 保持稳定的更新和维护频率
|
||||
|
||||
## 5.接口文档
|
||||
|
||||
### 接口名称
|
||||
|
||||
项目成熟度分析接口
|
||||
|
||||
### 接口路径
|
||||
|
||||
```
|
||||
/maturityAnalyse/
|
||||
```
|
||||
|
||||
### 请求方法
|
||||
|
||||
```
|
||||
GET
|
||||
```
|
||||
|
||||
### 请求参数
|
||||
|
||||
| 参数名 | 类型 | 是否必填 | 描述 |
|
||||
| ---------- | ------ | -------- | ------------------ |
|
||||
| owner | string | 是 | GitLink 仓库拥有者 |
|
||||
| repository | string | 是 | GitLink 仓库名称 |
|
||||
|
||||
### 示例请求
|
||||
|
||||
```
|
||||
bash
|
||||
|
||||
|
||||
复制代码
|
||||
GET /maturityAnalyse/?owner=xuos&repository=xiuos
|
||||
```
|
||||
|
||||
### 返回格式
|
||||
|
||||
返回数据为 JSON 格式,结构如下:
|
||||
|
||||
```
|
||||
{
|
||||
"data": {
|
||||
"scores": {
|
||||
"license_score": {
|
||||
"score": 100,
|
||||
"description": "开源许可证评分",
|
||||
"criteria": {
|
||||
"100": "使用标准开源许可证(MIT/Apache/GPL等)",
|
||||
"0": "无许可证"
|
||||
},
|
||||
"suggestion": "建议使用标准的开源许可证以明确项目的使用条款和限制"
|
||||
},
|
||||
"open_issue_score": {
|
||||
"score": 1,
|
||||
"description": "未解决issue评分",
|
||||
"criteria": {
|
||||
"80-100": "未解决issue较少",
|
||||
"60-80": "未解决issue较多",
|
||||
"0-60": "未解决issue很多"
|
||||
},
|
||||
"suggestion": "保持适度的未解决issue数量,及时处理重要issue"
|
||||
},
|
||||
"closed_issue_score": {
|
||||
"score": 0,
|
||||
"description": "已解决issue评分",
|
||||
"criteria": {
|
||||
"80-100": "已解决issue很多",
|
||||
"60-80": "已解决issue较多",
|
||||
"0-60": "已解决issue较少"
|
||||
},
|
||||
"suggestion": "提高issue解决率,保持良好的问题跟踪和处理机制"
|
||||
},
|
||||
"low_advisory_score": {
|
||||
"score": 100,
|
||||
"description": "低风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无低风险警告",
|
||||
"0": "多个低风险警告"
|
||||
},
|
||||
"suggestion": "定期检查并修复安全隐患,即使是低风险问题也应重视"
|
||||
},
|
||||
"moderate_advisory_score": {
|
||||
"score": 100,
|
||||
"description": "中等风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无中等风险警告",
|
||||
"0": "多个中风险警告"
|
||||
},
|
||||
"suggestion": "优先处理中等风险安全问题,避免安全隐患扩大"
|
||||
},
|
||||
"high_advisory_score": {
|
||||
"score": 100,
|
||||
"description": "高风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无高风险警告",
|
||||
"0": "多个高风险警告"
|
||||
},
|
||||
"suggestion": "高风险安全问题必须立即处理,可考虑发布安全补丁版本"
|
||||
},
|
||||
"critical_advisory_score": {
|
||||
"score": 100,
|
||||
"description": "严重风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无严重风险警告",
|
||||
"0": "多个严重风险警告"
|
||||
},
|
||||
"suggestion": "严重安全问题需要紧急修复并及时通知用户更新"
|
||||
},
|
||||
"stars_score": {
|
||||
"score": 42,
|
||||
"description": "项目Star数评分",
|
||||
"criteria": {
|
||||
"80-100": "Star很多",
|
||||
"60-80": "Star较多",
|
||||
"0-60": "Star较少"
|
||||
},
|
||||
"suggestion": "提高项目影响力,完善文档和功能以吸引更多用户关注"
|
||||
},
|
||||
"watching_score": {
|
||||
"score": 100,
|
||||
"description": "项目关注者评分",
|
||||
"criteria": {
|
||||
"80-100": "关注者很多",
|
||||
"60-80": "关注者较多",
|
||||
"0-60": "关注者较少"
|
||||
},
|
||||
"suggestion": "增加项目曝光度,保持更新以维持用户关注度"
|
||||
},
|
||||
"fork_score": {
|
||||
"score": 53,
|
||||
"description": "项目分支数评分",
|
||||
"criteria": {
|
||||
"80-100": "分支数很多",
|
||||
"60-80": "分支数较多",
|
||||
"0-60": "分支数较少"
|
||||
},
|
||||
"suggestion": "鼓励社区贡献,完善协作指南以促进分支开发"
|
||||
},
|
||||
"commits_number_score": {
|
||||
"score": 100,
|
||||
"description": "提交次数评分",
|
||||
"criteria": {
|
||||
"80-100": "提交次数很多",
|
||||
"60-80": "提交次数较多",
|
||||
"0-60": "提交次数较少"
|
||||
},
|
||||
"suggestion": "保持稳定的开发活跃度,定期提交代码更新"
|
||||
},
|
||||
"developer_number_score": {
|
||||
"score": 100,
|
||||
"description": "开发者数量评分",
|
||||
"criteria": {
|
||||
"80-100": "开发者数量很多",
|
||||
"60-80": "开发者数量较多",
|
||||
"0-60": "开发者数量较少"
|
||||
},
|
||||
"suggestion": "扩大开发团队,培养核心贡献者"
|
||||
},
|
||||
"release_number_score": {
|
||||
"score": 100,
|
||||
"description": "发布版本数评分",
|
||||
"criteria": {
|
||||
"80-100": "发布版本数很多",
|
||||
"60-80": "发布版本数较多",
|
||||
"0-60": "发布版本数较少"
|
||||
},
|
||||
"suggestion": "建立规范的版本发布流程,保持稳定的迭代节奏"
|
||||
},
|
||||
"overall_maturity_score": {
|
||||
"score": 76.61538461538461,
|
||||
"description": "总体成熟度评分",
|
||||
"criteria": {
|
||||
"80-100": "项目成熟,维护良好",
|
||||
"60-80": "项目稳定,有待改进",
|
||||
"40-60": "项目基本可用,需要加强维护",
|
||||
"0-40": "项目初期或疏于维护"
|
||||
},
|
||||
"suggestion": "根据各项分值改进薄弱环节,提高项目整体质量"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 返回字段说明
|
||||
|
||||
- data
|
||||
|
||||
: 返回的数据对象。
|
||||
|
||||
- scores
|
||||
|
||||
: 各项评分的详细信息。
|
||||
|
||||
- **license_score**: 开源许可证评分。
|
||||
- **open_issue_score**: 未解决 issue 的评分。
|
||||
- **closed_issue_score**: 已解决 issue 的评分。
|
||||
- **low_advisory_score**: 低风险安全警告评分。
|
||||
- **moderate_advisory_score**: 中等风险安全警告评分。
|
||||
- **high_advisory_score**: 高风险安全警告评分。
|
||||
- **critical_advisory_score**: 严重风险安全警告评分。
|
||||
- **stars_score**: 项目 Star 数评分。
|
||||
- **watching_score**: 项目关注者评分。
|
||||
- **fork_score**: 项目分支数评分。
|
||||
- **commits_number_score**: 提交次数评分。
|
||||
- **developer_number_score**: 开发者数量评分。
|
||||
- **release_number_score**: 发布版本数评分。
|
||||
- **overall_maturity_score**: 总体成熟度评分。
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'maturityAnalyse.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
ASGI config for maturityAnalyse project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'maturityAnalyse.settings')
|
||||
|
||||
application = get_asgi_application()
|
|
@ -0,0 +1,124 @@
|
|||
"""
|
||||
Django settings for maturityAnalyse project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 5.1.2.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-bk5uuf*=u0@dnlpicrk%(7#20iyez^yeh9yp1wau4r_7653vev'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'maturityAnalyse.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [BASE_DIR / 'templates']
|
||||
,
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'maturityAnalyse.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/5.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
@ -0,0 +1,25 @@
|
|||
"""
|
||||
URL configuration for maturityAnalyse project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
|
||||
from maturityAnalyse.views import calculate
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('maturityAnalyse/', calculate , name = "calculate"),
|
||||
]
|
|
@ -0,0 +1,611 @@
|
|||
import configparser
|
||||
import math
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
|
||||
from django.http import JsonResponse
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from maturityAnalyse import settings
|
||||
|
||||
config_file_path = os.path.join(settings.BASE_DIR, 'static', 'config.ini')
|
||||
|
||||
|
||||
# 加载配置文件
|
||||
def load_config(file_path):
|
||||
config = configparser.ConfigParser()
|
||||
config.read(file_path)
|
||||
return config['Limits']
|
||||
|
||||
|
||||
# 获取最大最小值
|
||||
def get_extreme_values(name):
|
||||
limits = load_config(config_file_path)
|
||||
|
||||
try:
|
||||
max_value = int(limits[f"{name}_max"])
|
||||
min_value = int(limits[f"{name}_min"])
|
||||
except KeyError:
|
||||
print(f"没有找到配置项: {name}")
|
||||
max_value, min_value = None, None
|
||||
|
||||
return max_value, min_value
|
||||
|
||||
|
||||
# 获取成熟度计算所需的上下文(最大最小值)
|
||||
def get_maturity_context():
|
||||
context = MaturityContext()
|
||||
context.commits_number_max, context.commits_number_min = get_extreme_values("commits_number")
|
||||
context.contributing_max, context.contributing_min = get_extreme_values("contributing")
|
||||
context.critical_advisory_max, context.critical_advisory_min = get_extreme_values("critical_advisory")
|
||||
context.forks_max, context.forks_min = get_extreme_values("forks")
|
||||
context.high_advisory_max, context.high_advisory_min = get_extreme_values("high_advisory")
|
||||
context.issue_closed_max, context.issue_closed_min = get_extreme_values("issue_closed")
|
||||
context.issue_opened_max, context.issue_opened_min = get_extreme_values("issue_opened")
|
||||
context.license_max, context.license_min = get_extreme_values("license_info")
|
||||
context.low_advisory_max, context.low_advisory_min = get_extreme_values("low_advisory")
|
||||
context.moderate_advisory_max, context.moderate_advisory_min = get_extreme_values("moderate_advisory")
|
||||
context.stars_max, context.stars_min = get_extreme_values("stars")
|
||||
context.release_number_max, context.release_number_min = get_extreme_values("release_number")
|
||||
context.developer_number_max, context.developer_number_min = get_extreme_values("developer_number")
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class MaturityContext:
|
||||
def __init__(self):
|
||||
self.stars_max = 0
|
||||
self.stars_min = 0
|
||||
self.watching_max = 0
|
||||
self.watching_min = 0
|
||||
self.forks_max = 0
|
||||
self.forks_min = 0
|
||||
self.commits_number_max = 0
|
||||
self.commits_number_min = 0
|
||||
self.license_max = 0
|
||||
self.license_min = 0
|
||||
self.issue_closed_max = 0
|
||||
self.issue_closed_min = 0
|
||||
self.issue_opened_max = 0
|
||||
self.issue_opened_min = 0
|
||||
self.low_advisory_max = 0
|
||||
self.low_advisory_min = 0
|
||||
self.moderate_advisory_max = 0
|
||||
self.moderate_advisory_min = 0
|
||||
self.high_advisory_max = 0
|
||||
self.high_advisory_min = 0
|
||||
self.critical_advisory_max = 0
|
||||
self.critical_advisory_min = 0
|
||||
self.contributing_max = 0
|
||||
self.contributing_min = 0
|
||||
self.developer_number_max = 0
|
||||
self.developer_number_min = 0
|
||||
self.release_number_max = 0
|
||||
self.release_number_min = 0
|
||||
|
||||
|
||||
class Software:
|
||||
def __init__(self, license, issue_opened, issue_closed, low_advisory, moderate_advisory, high_advisory,
|
||||
critical_advisory, stars, watching, forks, commits_number, average_day_interval, readme,
|
||||
contributing, developer_number, release_number, user_number, sum_user_score):
|
||||
self.license = license
|
||||
self.issue_opened = issue_opened
|
||||
self.issue_closed = issue_closed
|
||||
self.low_advisory = low_advisory
|
||||
self.moderate_advisory = moderate_advisory
|
||||
self.high_advisory = high_advisory
|
||||
self.critical_advisory = critical_advisory
|
||||
self.stars = stars
|
||||
self.watching = watching
|
||||
self.forks = forks
|
||||
self.commits_number = commits_number
|
||||
self.contributing = contributing
|
||||
self.developer_number = developer_number
|
||||
self.release_number = release_number
|
||||
|
||||
|
||||
class AllWeightSoftware:
|
||||
def __init__(self, software):
|
||||
self.s = software
|
||||
self.m = 0
|
||||
|
||||
|
||||
def generate_score(value, max_value, min_value):
|
||||
if max_value - min_value == 0:
|
||||
return 100 if value > 0 else 0
|
||||
|
||||
if max_value > 2:
|
||||
return log_generate_score(value, max_value, min_value)
|
||||
else:
|
||||
return normal_generate_score(value, max_value, min_value)
|
||||
|
||||
|
||||
def normal_generate_score(value, max_value, min_value):
|
||||
return int(100 * (value - min_value) / (max_value - min_value))
|
||||
|
||||
|
||||
def log_generate_score(value, max_value, min_value):
|
||||
if max_value - min_value == 0 and max_value != 0:
|
||||
return 50
|
||||
|
||||
fv = math.log10(value) if value > 0 else 0
|
||||
fmax = math.log10(max_value) if max_value != 0 else 0
|
||||
fmin = math.log10(min_value) if min_value != 0 else 0
|
||||
|
||||
return int(100 * (fv - fmin) / (fmax - fmin))
|
||||
|
||||
|
||||
def maturity(software, context):
|
||||
ws = AllWeightSoftware(software)
|
||||
|
||||
# 计算每个属性的分数
|
||||
ws.license_score = generate_score(software.license, context.license_max, context.license_min)
|
||||
|
||||
ws.open_issue_score = generate_score(software.issue_opened, context.issue_opened_max,
|
||||
context.issue_opened_min)
|
||||
|
||||
ws.closed_issue_score = generate_score(software.issue_closed, context.issue_closed_max, context.issue_closed_min)
|
||||
|
||||
ws.low_advisory_score = 100 - generate_score(software.low_advisory, context.low_advisory_max,
|
||||
context.low_advisory_min)
|
||||
|
||||
ws.moderate_advisory_score = 100 - generate_score(software.moderate_advisory, context.moderate_advisory_max,
|
||||
context.moderate_advisory_min)
|
||||
|
||||
ws.high_advisory_score = 100 - generate_score(software.high_advisory, context.high_advisory_max,
|
||||
context.high_advisory_min)
|
||||
|
||||
ws.critical_advisory_score = 100 - generate_score(software.critical_advisory, context.critical_advisory_max,
|
||||
context.critical_advisory_min)
|
||||
|
||||
ws.stars_score = generate_score(software.stars, context.stars_max, context.stars_min)
|
||||
|
||||
ws.watching_score = generate_score(software.watching, context.watching_max, context.watching_min)
|
||||
|
||||
ws.fork_score = generate_score(software.forks, context.forks_max, context.forks_min)
|
||||
|
||||
ws.commits_number_score = generate_score(software.commits_number, context.commits_number_max,
|
||||
context.commits_number_min)
|
||||
|
||||
ws.developer_number_score = generate_score(software.developer_number, context.developer_number_max,
|
||||
context.developer_number_min)
|
||||
|
||||
ws.release_number_score = generate_score(software.release_number, context.release_number_max,
|
||||
context.release_number_min)
|
||||
|
||||
# 计算整体成熟度,去掉权重影响
|
||||
ws.m = (ws.license_score + ws.open_issue_score + ws.closed_issue_score +
|
||||
# 降低了这部分内容的权重
|
||||
(ws.low_advisory_score + ws.moderate_advisory_score + ws.high_advisory_score + ws.critical_advisory_score) * 0.25 +
|
||||
ws.stars_score + ws.watching_score + ws.fork_score + ws.commits_number_score +
|
||||
ws.developer_number_score + ws.release_number_score) / 10
|
||||
|
||||
stage = 0
|
||||
if ws.m < 60:
|
||||
stage = 2
|
||||
elif ws.m >= 60 and ws.m < 80:
|
||||
stage = 1
|
||||
|
||||
yadd = stage * 3 - 1
|
||||
|
||||
scores_charts = [
|
||||
{
|
||||
"name": "license_score",
|
||||
"score": ws.license_score,
|
||||
"description": "开源许可证评分",
|
||||
"criteria": {
|
||||
"100": "使用标准开源许可证(MIT/Apache/GPL等)",
|
||||
"0": "无许可证"
|
||||
},
|
||||
"suggestion": "建议使用标准的开源许可证以明确项目的使用条款和限制",
|
||||
"itemStyle": {
|
||||
"color": "#e9ff40"
|
||||
},
|
||||
"value": [
|
||||
3,
|
||||
1 + yadd,
|
||||
ws.license_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "open_issue_score",
|
||||
"score": ws.open_issue_score,
|
||||
"description": "未解决issue评分",
|
||||
"criteria": {
|
||||
"80-100": "未解决issue较少",
|
||||
"60-80": "未解决issue较多",
|
||||
"0-60": "未解决issue很多"
|
||||
},
|
||||
"suggestion": "保持适度的未解决issue数量,及时处理重要issue",
|
||||
"itemStyle": {
|
||||
"color": "#abd9e9"
|
||||
},
|
||||
"value": [
|
||||
7,
|
||||
2 + yadd,
|
||||
ws.open_issue_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "closed_issue_score",
|
||||
"score": ws.closed_issue_score,
|
||||
"description": "已解决issue评分",
|
||||
"criteria": {
|
||||
"80-100": "已解决issue很多",
|
||||
"60-80": "已解决issue较多",
|
||||
"0-60": "已解决issue较少"
|
||||
},
|
||||
"suggestion": "提高issue解决率,保持良好的问题跟踪和处理机制",
|
||||
"itemStyle": {
|
||||
"color": "#74add1"
|
||||
},
|
||||
"value": [
|
||||
8,
|
||||
2 + yadd,
|
||||
ws.closed_issue_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "low_advisory_score",
|
||||
"score": ws.low_advisory_score,
|
||||
"description": "低风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无低风险警告",
|
||||
"0": "多个低风险警告"
|
||||
},
|
||||
"suggestion": "定期检查并修复安全隐患,即使是低风险问题也应重视",
|
||||
"itemStyle": {
|
||||
"color": "#ffffbf"
|
||||
},
|
||||
"value": [
|
||||
0,
|
||||
1 + yadd,
|
||||
ws.low_advisory_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "moderate_advisory_score",
|
||||
"score": ws.moderate_advisory_score,
|
||||
"description": "中等风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无中等风险警告",
|
||||
"0": "多个中风险警告"
|
||||
},
|
||||
"suggestion": "优先处理中等风险安全问题,避免安全隐患扩大",
|
||||
"itemStyle": {
|
||||
"color": "#fee090"
|
||||
},
|
||||
"value": [
|
||||
0,
|
||||
2 + yadd,
|
||||
ws.moderate_advisory_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "high_advisory_score",
|
||||
"score": ws.high_advisory_score,
|
||||
"description": "高风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无高风险警告",
|
||||
"0": "多个高风险警告"
|
||||
},
|
||||
"suggestion": "高风险安全问题必须立即处理,可考虑发布安全补丁版本",
|
||||
"itemStyle": {
|
||||
"color": "#fdae61"
|
||||
},
|
||||
"value": [
|
||||
1,
|
||||
1 + yadd,
|
||||
ws.high_advisory_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "critical_advisory_score",
|
||||
"score": ws.critical_advisory_score,
|
||||
"description": "严重风险安全警告评分",
|
||||
"criteria": {
|
||||
"100": "无严重风险警告",
|
||||
"0": "多个严重风险警告"
|
||||
},
|
||||
"suggestion": "严重安全问题需要紧急修复并及时通知用户更新",
|
||||
"itemStyle": {
|
||||
"color": "#f46d43"
|
||||
},
|
||||
"value": [
|
||||
1,
|
||||
2 + yadd,
|
||||
ws.critical_advisory_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stars_score",
|
||||
"score": ws.stars_score,
|
||||
"description": "项目Star数评分",
|
||||
"criteria": {
|
||||
"80-100": "Star很多",
|
||||
"60-80": "Star较多",
|
||||
"0-60": "Star较少"
|
||||
},
|
||||
"suggestion": "提高项目影响力,完善文档和功能以吸引更多用户关注",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
3,
|
||||
2 + yadd,
|
||||
ws.stars_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "watching_score",
|
||||
"score": ws.watching_score,
|
||||
"description": "项目关注者评分",
|
||||
"criteria": {
|
||||
"80-100": "关注者很多",
|
||||
"60-80": "关注者较多",
|
||||
"0-60": "关注者较少"
|
||||
},
|
||||
"suggestion": "增加项目曝光度,保持更新以维持用户关注度",
|
||||
"itemStyle": {
|
||||
"color": "#40daff"
|
||||
},
|
||||
"value": [
|
||||
4,
|
||||
2 + yadd,
|
||||
ws.watching_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fork_score",
|
||||
"score": ws.fork_score,
|
||||
"description": "项目fork数评分",
|
||||
"criteria": {
|
||||
"80-100": "fork数很多",
|
||||
"60-80": "fork数较多",
|
||||
"0-60": "fork数较少"
|
||||
},
|
||||
"suggestion": "鼓励社区贡献,完善协作指南以促进fork开发",
|
||||
"itemStyle": {
|
||||
"color": "#73d797"
|
||||
},
|
||||
"value": [
|
||||
5,
|
||||
1 + yadd,
|
||||
ws.fork_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "commits_number_score",
|
||||
"score": ws.commits_number_score,
|
||||
"description": "提交次数评分",
|
||||
"criteria": {
|
||||
"80-100": "提交次数很多",
|
||||
"60-80": "提交次数较多",
|
||||
"0-60": "提交次数较少"
|
||||
},
|
||||
"suggestion": "保持稳定的开发活跃度,定期提交代码更新",
|
||||
"itemStyle": {
|
||||
"color": "#ad73d7"
|
||||
},
|
||||
"value": [
|
||||
6,
|
||||
1 + yadd,
|
||||
ws.commits_number_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "developer_number_score",
|
||||
"score": ws.developer_number_score,
|
||||
"description": "开发者数量评分",
|
||||
"criteria": {
|
||||
"80-100": "开发者数量很多",
|
||||
"60-80": "开发者数量较多",
|
||||
"0-60": "开发者数量较少"
|
||||
},
|
||||
"suggestion": "扩大开发团队,培养核心贡献者",
|
||||
"itemStyle": {
|
||||
"color": "#ee6df5"
|
||||
},
|
||||
"value": [
|
||||
2,
|
||||
2 + yadd,
|
||||
ws.developer_number_score
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "release_number_score",
|
||||
"score": ws.release_number_score,
|
||||
"description": "发布版本数评分",
|
||||
"criteria": {
|
||||
"80-100": "发布版本数很多",
|
||||
"60-80": "发布版本数较多",
|
||||
"0-60": "发布版本数较少"
|
||||
},
|
||||
"suggestion": "建立规范的版本发布流程,保持稳定的迭代节奏",
|
||||
"itemStyle": {
|
||||
"color": "#c4b7e5"
|
||||
},
|
||||
"value": [
|
||||
2,
|
||||
1 + yadd,
|
||||
ws.release_number_score
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
main_score = {
|
||||
"name": "overall_maturity_score",
|
||||
"score": ws.m,
|
||||
"description": "总体成熟度评分",
|
||||
"criteria": {
|
||||
"80-100": "项目成熟,维护良好",
|
||||
"60-80": "项目稳定,有待改进",
|
||||
"40-60": "项目基本可用,需要加强维护",
|
||||
"0-40": "项目初期或疏于维护"
|
||||
},
|
||||
"x_axis": ["稳健性","稳健性","稳健性","扩展性","扩展性","扩展性","维护性","维护性","维护性"],
|
||||
"y_axis": ["成熟型","成熟型","成熟型","稳定型","稳定型","稳定型","成长型","成长型","成长型"],
|
||||
"suggestion": "根据各项分值改进薄弱环节,提高项目整体质量"
|
||||
}
|
||||
|
||||
return {'main_score': main_score, 'scores': scores_charts}
|
||||
|
||||
|
||||
def fetch_data(url):
|
||||
"""从给定 URL 获取数据并以 JSON 格式返回。"""
|
||||
response = requests.get(url)
|
||||
response.raise_for_status() # 对于错误响应抛出异常
|
||||
return response.json()
|
||||
|
||||
|
||||
@require_http_methods(['GET'])
|
||||
def calculate(request):
|
||||
owner = request.GET.get('owner')
|
||||
repository = request.GET.get('repository')
|
||||
env_url = "https://www.gitlink.org.cn"
|
||||
if request.GET.get('env_url') == "testforgeplus":
|
||||
env_url = "https://testforgeplus.trustie.net"
|
||||
|
||||
# owner = "xuos" # 替换为实际的 owner
|
||||
# repository = "xiuos" # 替换为实际的 repository
|
||||
|
||||
# owner = "leslieder"
|
||||
# repository = "nodom"
|
||||
|
||||
# owner = "openEuler-Ecosystem"
|
||||
# repository = "openEuler-EulerOS"
|
||||
|
||||
# 从 API 获取数据
|
||||
link1_info = f"{env_url}/api/{owner}/{repository}/detail.json"
|
||||
link2_contri = f"{env_url}/api/{owner}/{repository}/contributors.json"
|
||||
link3_issue = f"{env_url}/api/{owner}/{repository}/issues.json"
|
||||
link4_commits = f"{env_url}/api/{owner}/{repository}/commits.json"
|
||||
link_release = f"{env_url}/api/{owner}/{repository}/releases.json"
|
||||
|
||||
try:
|
||||
software_detail = fetch_data(link1_info)
|
||||
contributors = fetch_data(link2_contri)
|
||||
issues = fetch_data(link3_issue)
|
||||
commits = fetch_data(link4_commits)
|
||||
releases = fetch_data(link_release)
|
||||
|
||||
# 提取必要的信息
|
||||
license_info = 1 if software_detail.get("license_name") else 0
|
||||
issue_opened = issues.get("open_count", 0)
|
||||
issue_closed = issues.get("close_count", 0)
|
||||
low_advisory = software_detail.get("advisories", {}).get("low", 0)
|
||||
moderate_advisory = software_detail.get("advisories", {}).get("moderate", 0)
|
||||
high_advisory = software_detail.get("advisories", {}).get("high", 0)
|
||||
critical_advisory = software_detail.get("advisories", {}).get("critical", 0)
|
||||
stars = software_detail.get("praises_count", 0)
|
||||
watching = software_detail.get("watchers_count", 0)
|
||||
forks = software_detail.get("forked_count", 0)
|
||||
commits_number = commits.get("total_count")
|
||||
average_day_interval = software_detail.get("average_day_interval", 0)
|
||||
readme = software_detail.get("readme", False)
|
||||
contributing = software_detail.get("contributing", False)
|
||||
developer_number = len(contributors.get("list"))
|
||||
release_number = releases.get("total_count")
|
||||
user_number = software_detail.get("user_number", 0)
|
||||
sum_user_score = software_detail.get("sum_user_score", 0)
|
||||
|
||||
except TypeError:
|
||||
return JsonResponse({'data': {}})
|
||||
except:
|
||||
return JsonResponse({'data': {}})
|
||||
# 输出每个信息
|
||||
# print("许可证:", license_info)
|
||||
# print("打开的问题数量:", issue_opened)
|
||||
# print("关闭的问题数量:", issue_closed)
|
||||
# print("低风险通报数量:", low_advisory)
|
||||
# print("中风险通报数量:", moderate_advisory)
|
||||
# print("高风险通报数量:", high_advisory)
|
||||
# print("严重风险通报数量:", critical_advisory)
|
||||
# print("星级:", stars)
|
||||
# print("关注者数量:", watching)
|
||||
# print("分支数量:", forks)
|
||||
# print("提交数量:", commits_number)
|
||||
# print("平均天数间隔:", average_day_interval)
|
||||
# print("是否包含 README:", readme)
|
||||
# print("是否包含贡献指南:", contributing)
|
||||
# print("开发者数量:", developer_number)
|
||||
# print("发布版本数量:", release_number)
|
||||
# print("用户数量:", user_number)
|
||||
# print("用户总评分:", sum_user_score)
|
||||
|
||||
# 创建 Software 实例
|
||||
software = Software(
|
||||
license=license_info,
|
||||
issue_opened=issue_opened,
|
||||
issue_closed=issue_closed,
|
||||
low_advisory=low_advisory,
|
||||
moderate_advisory=moderate_advisory,
|
||||
high_advisory=high_advisory,
|
||||
critical_advisory=critical_advisory,
|
||||
stars=stars,
|
||||
watching=watching,
|
||||
forks=forks,
|
||||
commits_number=commits_number,
|
||||
average_day_interval=average_day_interval,
|
||||
readme=readme,
|
||||
contributing=contributing,
|
||||
developer_number=developer_number,
|
||||
release_number=release_number,
|
||||
user_number=user_number,
|
||||
sum_user_score=sum_user_score
|
||||
)
|
||||
|
||||
update_config(software)
|
||||
|
||||
context = get_maturity_context()
|
||||
maturity_score = maturity(software, context)
|
||||
|
||||
return JsonResponse({'data': maturity_score})
|
||||
|
||||
|
||||
def update_config(software):
|
||||
"""根据软件数据更新 config.ini 文件"""
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_file_path)
|
||||
|
||||
# 更新每个数据项
|
||||
update_config_value(config, 'license_info', software.license)
|
||||
update_config_value(config, 'issue_opened', software.issue_opened)
|
||||
update_config_value(config, 'issue_closed', software.issue_closed)
|
||||
update_config_value(config, 'low_advisory', software.low_advisory)
|
||||
update_config_value(config, 'moderate_advisory', software.moderate_advisory)
|
||||
update_config_value(config, 'high_advisory', software.high_advisory)
|
||||
update_config_value(config, 'critical_advisory', software.critical_advisory)
|
||||
update_config_value(config, 'stars', software.stars)
|
||||
update_config_value(config, 'watching', software.watching)
|
||||
update_config_value(config, 'forks', software.forks)
|
||||
update_config_value(config, 'commits_number', software.commits_number)
|
||||
update_config_value(config, 'developer_number', software.developer_number)
|
||||
update_config_value(config, 'release_number', software.release_number)
|
||||
|
||||
# 保存更新后的配置
|
||||
with open(config_file_path, 'w') as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
|
||||
def update_config_value(config, key, value):
|
||||
"""更新配置中的最大值和最小值"""
|
||||
section = 'Limits' # 指定使用的节
|
||||
|
||||
# 获取当前最小值和最大值
|
||||
current_min = config.getint(section, key + '_min')
|
||||
current_max = config.getint(section, key + '_max')
|
||||
|
||||
# 更新最小值
|
||||
if value < current_min:
|
||||
config.set(section, key + '_min', str(value))
|
||||
|
||||
# 更新最大值
|
||||
if value > current_max:
|
||||
config.set(section, key + '_max', str(value))
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# owner = "xuos" # 替换为实际的 owner
|
||||
# repository = "xiuos" # 替换为实际的 repository
|
||||
# calculate(owner,repository)
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
WSGI config for maturityAnalyse project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'maturityAnalyse.settings')
|
||||
|
||||
application = get_wsgi_application()
|
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
[Limits]
|
||||
license_info_min = 0
|
||||
license_info_max = 1
|
||||
issue_opened_min = 0
|
||||
issue_opened_max = 57
|
||||
issue_closed_min = 0
|
||||
issue_closed_max = 0
|
||||
low_advisory_min = 0
|
||||
low_advisory_max = 0
|
||||
moderate_advisory_min = 0
|
||||
moderate_advisory_max = 0
|
||||
high_advisory_min = 0
|
||||
high_advisory_max = 0
|
||||
critical_advisory_min = 0
|
||||
critical_advisory_max = 0
|
||||
stars_min = 0
|
||||
stars_max = 226
|
||||
watching_min = 0
|
||||
watching_max = 56
|
||||
forks_min = 0
|
||||
forks_max = 2668
|
||||
commits_number_min = 17
|
||||
commits_number_max = 2083
|
||||
developer_number_min = 1
|
||||
developer_number_max = 20
|
||||
release_number_min = 0
|
||||
release_number_max = 2
|
||||
|
|
@ -0,0 +1,516 @@
|
|||
// prettier-ignore
|
||||
|
||||
|
||||
|
||||
$.get('https://testbd.trustie.net/maturityAnalyse/?owner=GitLink&repository=gitea_hat').done(function(data) {
|
||||
|
||||
var e = data.data.scores
|
||||
|
||||
|
||||
});
|
||||
|
||||
var step = 2;
|
||||
var yadd= step * 3 -1
|
||||
|
||||
e=[
|
||||
{
|
||||
"name": "license_score",
|
||||
"score": 0,
|
||||
"description": "开源许可证评分",
|
||||
"criteria": {
|
||||
"0": "无许可证",
|
||||
"100": "使用标准开源许可证(MIT/Apache/GPL等)"
|
||||
},
|
||||
"suggestion": "建议使用标准的开源许可证以明确项目的使用条款和限制",
|
||||
"itemStyle": {
|
||||
"color": "#74add1"
|
||||
},
|
||||
"value": [
|
||||
8,
|
||||
1+yadd,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "open_issue_score",
|
||||
"score": 100,
|
||||
"description": "未解决issue评分",
|
||||
"criteria": {
|
||||
"80-100": "未解决issue较少",
|
||||
"60-80": "未解决issue较多",
|
||||
"0-60": "未解决issue很多"
|
||||
},
|
||||
"suggestion": "保持适度的未解决issue数量,及时处理重要issue",
|
||||
"itemStyle": {
|
||||
"color": "#74add1"
|
||||
},
|
||||
"value": [
|
||||
3,
|
||||
1+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "closed_issue_score",
|
||||
"score": 99,
|
||||
"description": "已解决issue评分",
|
||||
"criteria": {
|
||||
"80-100": "已解决issue很多",
|
||||
"60-80": "已解决issue较多",
|
||||
"0-60": "已解决issue较少"
|
||||
},
|
||||
"suggestion": "提高issue解决率,保持良好的问题跟踪和处理机制",
|
||||
"itemStyle": {
|
||||
"color": "#74add1"
|
||||
},
|
||||
"value": [
|
||||
3,
|
||||
2+yadd,
|
||||
99
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "low_advisory_score",
|
||||
"score": 100,
|
||||
"description": "低风险安全警告评分",
|
||||
"criteria": {
|
||||
"0": "多个低风险警告",
|
||||
"100": "无低风险警告"
|
||||
},
|
||||
"suggestion": "定期检查并修复安全隐患,即使是低风险问题也应重视",
|
||||
"itemStyle": {
|
||||
"color": "#ffffbf"
|
||||
},
|
||||
"value": [
|
||||
5,
|
||||
1+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "moderate_advisory_score",
|
||||
"score": 100,
|
||||
"description": "中等风险安全警告评分",
|
||||
"criteria": {
|
||||
"0": "多个中风险警告",
|
||||
"100": "无中等风险警告"
|
||||
},
|
||||
"suggestion": "优先处理中等风险安全问题,避免安全隐患扩大",
|
||||
"itemStyle": {
|
||||
"color": "#fee090"
|
||||
},
|
||||
"value": [
|
||||
5,
|
||||
2+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "high_advisory_score",
|
||||
"score": 100,
|
||||
"description": "高风险安全警告评分",
|
||||
"criteria": {
|
||||
"0": "多个高风险警告",
|
||||
"100": "无高风险警告"
|
||||
},
|
||||
"suggestion": "高风险安全问题必须立即处理,可考虑发布安全补丁版本",
|
||||
"itemStyle": {
|
||||
"color": "#fdae61"
|
||||
},
|
||||
"value": [
|
||||
4,
|
||||
1+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "critical_advisory_score",
|
||||
"score": 100,
|
||||
"description": "严重风险安全警告评分",
|
||||
"criteria": {
|
||||
"0": "多个严重风险警告",
|
||||
"100": "无严重风险警告"
|
||||
},
|
||||
"suggestion": "严重安全问题需要紧急修复并及时通知用户更新",
|
||||
"itemStyle": {
|
||||
"color": "#f46d43"
|
||||
},
|
||||
"value": [
|
||||
4,
|
||||
2+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stars_score",
|
||||
"score": 0,
|
||||
"description": "项目Star数评分",
|
||||
"criteria": {
|
||||
"80-100": "Star很多",
|
||||
"60-80": "Star较多",
|
||||
"0-60": "Star较少"
|
||||
},
|
||||
"suggestion": "提高项目影响力,完善文档和功能以吸引更多用户关注",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
0,
|
||||
1+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "watching_score",
|
||||
"score": 100,
|
||||
"description": "项目关注者评分",
|
||||
"criteria": {
|
||||
"80-100": "关注者很多",
|
||||
"60-80": "关注者较多",
|
||||
"0-60": "关注者较少"
|
||||
},
|
||||
"suggestion": "增加项目曝光度,保持更新以维持用户关注度",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
0,
|
||||
2+yadd,
|
||||
100
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fork_score",
|
||||
"score": 0,
|
||||
"description": "项目分支数评分",
|
||||
"criteria": {
|
||||
"80-100": "分支数很多",
|
||||
"60-80": "分支数较多",
|
||||
"0-60": "分支数较少"
|
||||
},
|
||||
"suggestion": "鼓励社区贡献,完善协作指南以促进分支开发",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
1,
|
||||
1+yadd,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "commits_number_score",
|
||||
"score": 28,
|
||||
"description": "提交次数评分",
|
||||
"criteria": {
|
||||
"80-100": "提交次数很多",
|
||||
"60-80": "提交次数较多",
|
||||
"0-60": "提交次数较少"
|
||||
},
|
||||
"suggestion": "保持稳定的开发活跃度,定期提交代码更新",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
2,
|
||||
1+yadd,
|
||||
28
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "developer_number_score",
|
||||
"score": 0,
|
||||
"description": "开发者数量评分",
|
||||
"criteria": {
|
||||
"80-100": "开发者数量很多",
|
||||
"60-80": "开发者数量较多",
|
||||
"0-60": "开发者数量较少"
|
||||
},
|
||||
"suggestion": "扩大开发团队,培养核心贡献者",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
2,
|
||||
2+yadd,
|
||||
28
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "release_number_score",
|
||||
"score": 0,
|
||||
"description": "发布版本数评分",
|
||||
"criteria": {
|
||||
"80-100": "发布版本数很多",
|
||||
"60-80": "发布版本数较多",
|
||||
"0-60": "发布版本数较少"
|
||||
},
|
||||
"suggestion": "建立规范的版本发布流程,保持稳定的迭代节奏",
|
||||
"itemStyle": {
|
||||
"color": "#93AAFC"
|
||||
},
|
||||
"value": [
|
||||
1,
|
||||
2+yadd,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
var t = [
|
||||
"活跃度",
|
||||
"活跃度",
|
||||
"活跃度",
|
||||
"质量安全",
|
||||
"质量安全",
|
||||
"质量安全",
|
||||
"基础要素",
|
||||
"基础要素",
|
||||
"基础要素"
|
||||
];
|
||||
|
||||
// 基础要素:开源许可证评分,
|
||||
// 质量: 未解决issue评分,已解决issue评分, 安全性评分
|
||||
// 活跃度: Star数评分,关注者评分,Fork数评分,提交次数评分,开发者数量评分,发布版本数评分
|
||||
|
||||
|
||||
// var i = [
|
||||
// "协作",
|
||||
// "协作",
|
||||
// "协作",
|
||||
// "社区活跃度",
|
||||
// "社区活跃度",
|
||||
// "社区活跃度",
|
||||
// "开发活跃度",
|
||||
// "开发活跃度",
|
||||
// "开发活跃度"
|
||||
// ];
|
||||
var i = [
|
||||
"成熟型",
|
||||
"成熟型",
|
||||
"成熟型",
|
||||
"稳定型",
|
||||
"稳定型",
|
||||
"稳定型",
|
||||
"成长型",
|
||||
"成长型",
|
||||
"成长型"
|
||||
];
|
||||
// var i = [
|
||||
// "项目成熟,维护良好",
|
||||
// "项目成熟,维护良好",
|
||||
// "项目成熟,维护良好",
|
||||
// "项目稳定,有待改进",
|
||||
// "项目稳定,有待改进",
|
||||
// "项目稳定,有待改进",
|
||||
// "项目基本可用,需要加强维护",
|
||||
// "项目基本可用,需要加强维护",
|
||||
// "项目基本可用,需要加强维护",
|
||||
// "项目初期或疏于维护",
|
||||
// "项目初期或疏于维护",
|
||||
// "项目初期或疏于维护",
|
||||
// // "质量",
|
||||
// // "基础要素",
|
||||
// // "基础要素",
|
||||
// // "基础要素",
|
||||
// ];
|
||||
var a = 3;
|
||||
var n = 3;
|
||||
var o = false;
|
||||
|
||||
// prettier-ignore
|
||||
// var days = ['', 'Friday', '',
|
||||
// 'Wednesday', '', '', 'Sunday'];
|
||||
// prettier-ignore
|
||||
const l = o ? "white" : "#333"
|
||||
, r = o ? "rgba(255,255,255,0.5)" : "#aaa";
|
||||
|
||||
// var data = [ [0, 16, 4], [0, 17, 6], [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5], [1, 0, 7], [1, 1, 0], [1, 2, 0]];
|
||||
option = {
|
||||
tooltip: {
|
||||
textStyle: {
|
||||
fontWeight: "bolder"
|
||||
},
|
||||
formatter: e => "mock" === e.data.validity ? e.name + ": \u5373\u5c06\u4e0a\u7ebf" : e.data.description + ": " + e.data.value[2]
|
||||
},
|
||||
visualMap: {
|
||||
max: 20,
|
||||
inRange: {
|
||||
color: [
|
||||
'#313695',
|
||||
'#4575b4',
|
||||
'#74add1',
|
||||
'#abd9e9',
|
||||
'#e0f3f8',
|
||||
'#ffffbf',
|
||||
'#fee090',
|
||||
'#fdae61',
|
||||
'#f46d43',
|
||||
'#d73027',
|
||||
'#a50026'
|
||||
]
|
||||
}
|
||||
},
|
||||
xAxis3D: {
|
||||
name: " ",
|
||||
type: "category",
|
||||
data: t,
|
||||
interval: 2,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: l
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: !0,
|
||||
interval: a - 1
|
||||
},
|
||||
axisLabel: {
|
||||
interval: a - 1,
|
||||
textStyle: {
|
||||
color: r,
|
||||
padding: [10, 10, 0, 0]
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
interval: a - 1,
|
||||
length: 1
|
||||
}
|
||||
},
|
||||
yAxis3D: {
|
||||
name: " ",
|
||||
type: "category",
|
||||
data: i,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: l
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
interval: n - 1,
|
||||
length: 0
|
||||
},
|
||||
splitArea: {
|
||||
show: !0,
|
||||
areaStyle: {
|
||||
color: ["rgba(255,247,207,0.5)", "rgba(255,231,231,0.5)", "rgba(226,226,226,0.5)"]
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
interval: n - 1,
|
||||
textStyle: {
|
||||
lineHeight: 2,
|
||||
color: r,
|
||||
padding: [10, 0, 0, 0]
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: !0,
|
||||
interval: n - 1
|
||||
}
|
||||
},
|
||||
zAxis3D: {
|
||||
name: " ",
|
||||
type: "value",
|
||||
splitNumber: 4,
|
||||
axisLine: {
|
||||
lineStyle: o ? {
|
||||
width: 1,
|
||||
opacity: .2,
|
||||
color: l
|
||||
} : {
|
||||
width: .1,
|
||||
opacity: .5,
|
||||
color: l
|
||||
}
|
||||
},
|
||||
splitArea: {
|
||||
show: !0,
|
||||
areaStyle: {
|
||||
color: ["#ffffff", "#ffffff", "#ffffff"]
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
show: !1
|
||||
},
|
||||
axisTick: {
|
||||
show: !1
|
||||
}
|
||||
},
|
||||
grid3D: {
|
||||
axisLine: {
|
||||
interval: 1
|
||||
},
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
opacity: .2
|
||||
},
|
||||
label: {
|
||||
show: !1
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
interval: 2
|
||||
},
|
||||
viewControl: {
|
||||
projection: "perspective",
|
||||
zoomSensitivity: 0,
|
||||
rotateSensitivity: [1, 0],
|
||||
distance: 380,
|
||||
alpha: 20,
|
||||
beta: 25
|
||||
},
|
||||
top: -40,
|
||||
boxWidth: 150,
|
||||
boxDepth: 150,
|
||||
environment: "none",
|
||||
light: {
|
||||
main: {
|
||||
intensity: .8,
|
||||
alpha: 50
|
||||
},
|
||||
ambient: {
|
||||
intensity: .5
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: "bar3D",
|
||||
data: e,
|
||||
shading: "realistic",
|
||||
bevelSize: .1,
|
||||
bevelSmoothness: 2,
|
||||
barSize: 10,
|
||||
label: {
|
||||
show: !1,
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
borderWidth: 1,
|
||||
color: "#333",
|
||||
distance: -20,
|
||||
formatter: function (e) {
|
||||
for (var t = e.data.description, i = 2, a = Math.ceil(t.length / i), n = "\n", o = 0; o < a; o++) {
|
||||
var l = o * i
|
||||
, r = l + i;
|
||||
n += t.substring(l, r) + "\n"
|
||||
}
|
||||
return n
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
opacity: .95
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: !1
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#FFB800",
|
||||
opacity: .7
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
Loading…
Reference in New Issue