diff --git a/gsuid_core/help/draw_plugin_help.py b/gsuid_core/help/draw_plugin_help.py new file mode 100644 index 0000000..0b78894 --- /dev/null +++ b/gsuid_core/help/draw_plugin_help.py @@ -0,0 +1,107 @@ +from copy import deepcopy +from typing import Dict, List, Tuple, Callable, Optional + +from PIL import Image, ImageDraw, ImageFont + +from gsuid_core.data_store import get_res_path +from gsuid_core.utils.image.convert import convert_img +from gsuid_core.utils.image.image_tools import ( + crop_center_img, + easy_alpha_composite, +) + +from .model import PluginHelp + +cache: Dict[str, int] = {} + + +async def get_help( + name: str, + sub_text: str, + help_data: Dict[str, PluginHelp], + bg: Image.Image, + icon: Image.Image, + badge: Image.Image, + banner: Image.Image, + button: Image.Image, + font: Callable[[int], ImageFont.FreeTypeFont], + is_dark: bool = True, + text_color: Tuple[int, int, int] = (250, 250, 250), + sub_color: Optional[Tuple[int, int, int]] = None, +) -> bytes: + help_path = get_res_path('help') / f'{name}.jpg' + + if help_path.exists() and name in cache and cache[name]: + return await convert_img(Image.open(help_path)) + + if sub_color is None and is_dark: + sub_color = tuple(x - 50 for x in text_color if x > 50) + elif sub_color is None and not is_dark: + sub_color = tuple(x + 50 for x in text_color if x < 205) + + title = Image.new('RGBA', (900, 600)) + icon = icon.resize((300, 300)) + title.paste(icon, (300, 89), icon) + title.paste(badge, (0, 390), badge) + badge_s = badge.resize((720, 80)) + title.paste(badge_s, (90, 480), badge_s) + title_draw = ImageDraw.Draw(title) + + title_draw.text((450, 440), f'{name} 帮助', text_color, font(36), 'mm') + title_draw.text((450, 520), sub_text, sub_color, font(26), 'mm') + + w, h = 900, 630 + + sv_img_list: List[Image.Image] = [] + for sv_name in help_data: + tr_size = len(help_data[sv_name]['data']) + y = 100 + ((tr_size + 3) // 4) * 80 + h += y + sv_img = Image.new('RGBA', (900, y)) + sv_data = help_data[sv_name]['data'] + sv_desc = help_data[sv_name]['desc'] + + bc = deepcopy(banner) + bc_draw = ImageDraw.Draw(bc) + bc_draw.text((30, 25), sv_name, text_color, font(35), 'lm') + size, _ = font(35).getsize(sv_name) + bc_draw.text((42 + size, 30), sv_desc, sub_color, font(20), 'lm') + sv_img = easy_alpha_composite(sv_img, bc, (0, 10)) + # sv_img.paste(bc, (0, 10), bc) + + for index, tr in enumerate(sv_data): + bt = deepcopy(button) + bt_draw = ImageDraw.Draw(bt) + if len(tr['name']) > 8: + tr_name = tr['name'][:5] + '..' + else: + tr_name = tr['name'] + + bt_draw.text((105, 28), tr_name, text_color, font(26), 'mm') + bt_draw.text((105, 51), tr['eg'], sub_color, font(17), 'mm') + offset_x = 210 * (index % 4) + offset_y = 80 * (index // 4) + sv_img = easy_alpha_composite( + sv_img, bt, (26 + offset_x, 83 + offset_y) + ) + # sv_img.paste(bt, (26 + offset_x, 83 + offset_y), bt) + + sv_img_list.append(sv_img) + + img = crop_center_img(bg, w, h) + img.paste(title, (0, 0), title) + temp = 0 + for _sm in sv_img_list: + img.paste(_sm, (0, 600 + temp), _sm) + temp += _sm.size[1] + + img = img.convert('RGB') + help_path = get_res_path('help') / f'{name}.jpg' + img.save( + help_path, + 'JPEG', + quality=85, + subsampling=0, + ) + cache[name] = 1 + return await convert_img(img) diff --git a/gsuid_core/help/model.py b/gsuid_core/help/model.py new file mode 100644 index 0000000..15283b3 --- /dev/null +++ b/gsuid_core/help/model.py @@ -0,0 +1,15 @@ +from typing import List, TypedDict + + +class PluginSV(TypedDict): + name: str + desc: str + eg: str + need_ck: bool + need_sk: bool + need_admin: bool + + +class PluginHelp(TypedDict): + desc: str + data: List[PluginSV] diff --git a/gsuid_core/tools/gen_help.py b/gsuid_core/tools/gen_help.py new file mode 100644 index 0000000..6a3d89c --- /dev/null +++ b/gsuid_core/tools/gen_help.py @@ -0,0 +1,65 @@ +import copy +import json +from pathlib import Path + +from openpyxl import load_workbook + +sample = { + 'name': '', + 'desc': '', + 'eg': '', + 'need_ck': False, + 'need_sk': False, + 'need_admin': False, +} + +result = {} + +HELP_PATH = Path(__file__).parent / 'Help.xlsx' +OUTPUT_PATH = Path(__file__).parent / 'Help.json' + +wb = load_workbook(str(HELP_PATH)) +ws = wb.active + +module_name_str = '' +for row in range(2, 999): + # 跳过空白行 + if not ws.cell(row, 2).value: + continue + + _sample = copy.deepcopy(sample) + + # 将第一列读取为模块名 + if ws.cell(row, 1): + if ws.cell(row, 1).value is not None: + module_name_str = ws.cell(row, 1).value + + # if module_name_str is None and not isinstance(module_name_str, str): + # continue + + # 第二列为功能名 + _sample['name'] = ws.cell(row, 2).value + # 第三列为详细信息 + _sample['desc'] = ws.cell(row, 3).value + # 第四列为使用例 + _sample['eg'] = ws.cell(row, 4).value + + if ws.cell(row, 5).value == '是': + _sample['need_ck'] = True + + if ws.cell(row, 6).value == '是': + _sample['need_sk'] = True + + if ws.cell(row, 7).value == '是': + _sample['need_admin'] = True + + if isinstance(module_name_str, str): + module_name = module_name_str.split(' | ')[0] + module_desc = module_name_str.split(' | ')[1] + if module_name not in result: + result[module_name] = {'desc': module_desc, 'data': []} + + result[module_name]['data'].append(_sample) + +with open(OUTPUT_PATH, 'w', encoding='utf-8') as f: + json.dump(result, f, indent=2, ensure_ascii=False)