| import gradio as gr |
| import requests |
| import webbrowser |
| from typing import List, Dict, Any |
|
|
|
|
| class Hero: |
| def __init__(self, data: Dict[str, Any]): |
| self.heroId = data.get("heroId") |
| self.name = data.get("name") |
| self.alias = data.get("alias") |
| self.title = data.get("title") |
| self.roles = data.get("roles", []) |
| self.keywords = data.get("keywords") |
|
|
| @property |
| def image_url(self): |
| return f"https://game.gtimg.cn/images/lol/act/img/champion/{self.alias}.png" |
|
|
|
|
| class HeroList: |
| def __init__(self, data: Dict[str, Any]): |
| self.hero = [Hero(hero_data) for hero_data in data.get("hero", [])] |
|
|
|
|
| def get_hero_data() -> HeroList: |
| url = "https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js" |
| response = requests.get(url) |
| data = response.json() |
| return HeroList(data) |
|
|
|
|
| def translate_role(role: str) -> str: |
| role_map = { |
| "fighter": "ๆๅฃซ", |
| "tank": "ๅฆๅ
", |
| "mage": "ๆณๅธ", |
| "assassin": "ๅบๅฎข", |
| "marksman": "ๅฐๆ", |
| "support": "่พ
ๅฉ", |
| } |
| return role_map.get(role, role) |
|
|
|
|
| hero_list = None |
| all_heroes = [] |
| selected_heroes = [] |
|
|
|
|
| def load_heroes(): |
| global hero_list, all_heroes |
| if not all_heroes: |
| hero_list = get_hero_data() |
| all_heroes = hero_list.hero |
|
|
| for hero in all_heroes: |
| hero.roles = [translate_role(role) for role in hero.roles] |
|
|
| return all_heroes |
|
|
|
|
| |
| |
|
|
|
|
| def get_heroes_by_role(role: str): |
| if not all_heroes: |
| load_heroes() |
| return [hero for hero in all_heroes if role in hero.roles] |
|
|
|
|
| def search_heroes(query: str): |
| if not all_heroes: |
| load_heroes() |
| query = query.lower() |
| if not query: |
| return [] |
| return [ |
| hero |
| for hero in all_heroes |
| if query in hero.title.lower() |
| or query in hero.name.lower() |
| or (hero.keywords and query in hero.keywords.lower()) |
| ] |
|
|
|
|
| def select_hero(hero_alias: str): |
| global selected_heroes |
| if not all_heroes: |
| load_heroes() |
|
|
| hero = next((h for h in all_heroes if h.alias == hero_alias), None) |
| if hero and len(selected_heroes) < 10 and hero not in selected_heroes: |
| selected_heroes.append(hero) |
|
|
| return get_selected_heroes_display() |
|
|
|
|
| def remove_hero(hero_alias: str): |
| global selected_heroes |
| selected_heroes = [h for h in selected_heroes if h.alias != hero_alias] |
| return get_selected_heroes_display() |
|
|
|
|
| def clear_selection(): |
| global selected_heroes |
| selected_heroes = [] |
| return get_selected_heroes_display() |
|
|
|
|
| def get_selected_heroes_display(): |
| if not selected_heroes: |
| return "", "" |
|
|
| team1 = selected_heroes[:5] |
| team2 = selected_heroes[5:10] |
|
|
| team1_str = "\n".join([f"{h.title}({h.name})" for h in team1]) |
| team2_str = "\n".join([f"{h.title}({h.name})" for h in team2]) |
|
|
| return team1_str, team2_str |
|
|
|
|
| def open_hero_detail(hero_id: str): |
| url = f"https://101.qq.com/#/hero-detail?heroid={hero_id}&tab=equipment" |
| |
| return f"<script>window.open('{url}', '_blank')</script>ๅทฒๆๅผ่ฑ้่ฏฆๆ
: {url}" |
|
|
|
|
| def open_metasrc(hero_alias: str): |
| url = f"https://www.metasrc.com/lol/mayhem/build/{hero_alias.lower()}" |
| |
| return f"<script>window.open('{url}', '_blank')</script>ๅทฒๆๅผ MetaSrc: {url}" |
|
|
|
|
| def open_tier_list(): |
| url = "https://www.metasrc.com/lol/urf/tier-list" |
| |
| return f"<script>window.open('{url}', '_blank')</script>ๅทฒๆๅผๆ่กๆฆ: {url}" |
|
|
|
|
| def create_hero_card(hero: Hero): |
| with gr.Column(scale=1, min_width=140, elem_classes=["hero-card"]): |
| gr.HTML( |
| value=f'<img src="{hero.image_url}" class="hero-image" loading="lazy" />', |
| elem_classes=["hero-image-wrapper"] |
| ) |
| gr.Textbox( |
| value=f"{hero.title}\n({hero.name})", |
| lines=2, |
| interactive=False, |
| text_align="center", |
| show_label=False, |
| elem_classes=["hero-name"] |
| ) |
| gr.Textbox( |
| value=",".join(hero.roles), |
| lines=1, |
| interactive=False, |
| text_align="center", |
| show_label=False, |
| elem_classes=["hero-roles"] |
| ) |
| with gr.Row(elem_classes=["hero-buttons"]): |
| gr.Button("่ฏฆๆ
", variant="primary").click( |
| fn=lambda x: f"ๅทฒๆๅผ่ฑ้่ฏฆๆ
", |
| inputs=[gr.Textbox(value=hero.heroId, visible=False)], |
| outputs=[gr.Textbox(visible=False)], |
| js=f"() => window.open('https://101.qq.com/#/hero-detail?heroid={hero.heroId}&tab=equipment', '_blank')", |
| ) |
| gr.Button("ๅบ่ฃ
", variant="secondary").click( |
| fn=lambda x: f"ๅทฒๆๅผ MetaSrc", |
| inputs=[gr.Textbox(value=hero.alias, visible=False)], |
| outputs=[gr.Textbox(visible=False)], |
| js=f"() => window.open('https://www.metasrc.com/lol/mayhem/build/{hero.alias.lower()}', '_blank')", |
| ) |
|
|
|
|
| def create_hero_tab(tab_name: str): |
| with gr.Tab(tab_name): |
| |
| heroes = get_heroes_by_role(tab_name) |
| |
| |
| with gr.Row(elem_classes=["hero-grid"]): |
| for hero in heroes: |
| create_hero_card(hero) |
|
|
|
|
| role_tabs = ["ๆๅฃซ", "ๆณๅธ", "ๅบๅฎข", "ๅฆๅ
", "ๅฐๆ", "่พ
ๅฉ"] |
|
|
| with gr.Blocks( |
| title="ChatGptLoL - Python Gradio็ๆฌ", |
| css=""" |
| /* ๅ
จๅฑๆ ทๅผ */ |
| :root { |
| --primary-color: #0066cc; |
| --secondary-color: #0099ff; |
| --accent-color: #ff6600; |
| --background-color: #f0f2f5; |
| --card-background: #ffffff; |
| --text-color: #333333; |
| --text-light: #666666; |
| --border-radius: 12px; |
| --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
| --box-shadow-hover: 0 8px 15px rgba(0, 0, 0, 0.15); |
| --transition: all 0.3s ease; |
| --transition-fast: all 0.2s ease; |
| --transition-slow: all 0.5s ease; |
| } |
| |
| body { |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| background-color: var(--background-color); |
| color: var(--text-color); |
| line-height: 1.6; |
| } |
| |
| /* ็ฆ็จๆๆ Textarea ๆปๅจๆก */ |
| textarea { |
| overflow: hidden !important; |
| resize: none !important; |
| } |
| |
| .gradio-container { |
| max-width: 1400px !important; |
| margin: 0 auto; |
| padding: 20px; |
| } |
| |
| /* ๆ ้ขๆ ทๅผ */ |
| h1 { |
| text-align: center; |
| color: var(--primary-color); |
| margin-bottom: 30px !important; |
| font-weight: 700; |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); |
| } |
| |
| /* ๆ ็ญพ้กตๆ ทๅผ */ |
| .tabs { |
| margin-bottom: 30px; |
| } |
| |
| .tab-button { |
| font-weight: 600; |
| padding: 10px 20px; |
| border-radius: var(--border-radius) var(--border-radius) 0 0; |
| transition: var(--transition); |
| } |
| |
| .tab-button:hover { |
| background-color: var(--secondary-color) !important; |
| color: white !important; |
| } |
| |
| .tab-content { |
| background-color: var(--card-background); |
| border-radius: 0 var(--border-radius) var(--border-radius) var(--border-radius); |
| padding: 20px; |
| box-shadow: var(--box-shadow); |
| } |
| |
| /* ๆ็ดขๅบๅ */ |
| #search-hero-input { |
| width: 100% !important; |
| margin: 0 auto 0px auto !important; |
| background-color: var(--card-background) !important; |
| border: 2px solid var(--secondary-color) !important; |
| border-radius: var(--border-radius) !important; |
| --spacing-sm: 0px !important; |
| } |
| |
| #search-hero-input textarea { |
| width: 100% !important; |
| background-color: transparent !important; |
| } |
| |
| /* ๆ็ดข็ปๆๅฎนๅจ */ |
| #search-results-html { |
| background-color: transparent !important; |
| box-shadow: none !important; |
| padding: 0 !important; |
| width: 100% !important; |
| margin-top: 0 !important; |
| margin-bottom: 0 !important; |
| --spacing-sm: 0px !important; |
| } |
| |
| /* ็งป้คGradio็ๆ็็ฐ่ฒ่ๆฏ - ๆ็ดขๆก็็ถๅฎนๅจ */ |
| #search-hero-input.parent { |
| background: transparent !important; |
| box-shadow: none !important; |
| border: none !important; |
| } |
| |
| /* ็งป้คGradio็ๆ็็ฐ่ฒ่ๆฏ - ๆ็ดข็ปๆ็็ถๅฎนๅจ */ |
| #search-results-html.parent { |
| background: transparent !important; |
| box-shadow: none !important; |
| border: none !important; |
| } |
| |
| /* ็ดๆฅ้ๆฉๆ็ดขๆก็็ถๅฎนๅจ */ |
| .gradio-container > div:has(#search-hero-input) { |
| background: transparent !important; |
| box-shadow: none !important; |
| border: none !important; |
| } |
| |
| /* ็ดๆฅ้ๆฉๆ็ดข็ปๆ็็ถๅฎนๅจ */ |
| .gradio-container > div:has(#search-results-html) { |
| background: transparent !important; |
| box-shadow: none !important; |
| border: none !important; |
| } |
| |
| /* ็งป้ค็นๅฎSvelte็ฑป็็ฐ่ฒ่ๆฏ */ |
| div.svelte-633qhp { |
| background: transparent !important; |
| box-shadow: none !important; |
| border: none !important; |
| } |
| |
| /* ่ฑ้็ฝๆ ผๅธๅฑ */ |
| .hero-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); |
| gap: 16px; |
| padding: 10px; |
| max-height: 600px; |
| overflow-y: auto; |
| scrollbar-width: thin; |
| scrollbar-color: var(--secondary-color) #f1f1f1; |
| } |
| |
| /* WebKit ๆต่งๅจๆปๅจๆกๆ ทๅผ */ |
| .hero-grid::-webkit-scrollbar { |
| width: 8px; |
| } |
| |
| .hero-grid::-webkit-scrollbar-track { |
| background: #f1f1f1; |
| border-radius: 4px; |
| } |
| |
| .hero-grid::-webkit-scrollbar-thumb { |
| background: var(--secondary-color); |
| border-radius: 4px; |
| } |
| |
| .hero-grid::-webkit-scrollbar-thumb:hover { |
| background: var(--primary-color); |
| } |
| |
| /* ่ฑ้ๅก็ๆ ทๅผ */ |
| .hero-card { |
| background-color: var(--card-background); |
| border-radius: var(--border-radius); |
| padding: 15px; |
| box-shadow: var(--box-shadow); |
| transition: var(--transition); |
| text-align: center; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .hero-card::before { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: -100%; |
| width: 100%; |
| height: 100%; |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); |
| transition: var(--transition-slow); |
| } |
| |
| .hero-card:hover { |
| transform: translateY(-5px) scale(1.02); |
| box-shadow: var(--box-shadow-hover); |
| } |
| |
| .hero-card:hover::before { |
| left: 100%; |
| } |
| |
| /* ่ฑ้ๅพ็ๆ ทๅผ */ |
| .hero-image { |
| border-radius: 12px !important; |
| border: 2px solid #c8c8c8 !important; |
| margin-bottom: 10px !important; |
| margin-left: auto !important; |
| margin-right: auto !important; |
| display: block !important; |
| width: 90px !important; |
| height: 90px !important; |
| object-fit: cover !important; |
| } |
| |
| /* ่ฑ้ๅ็งฐๆ ทๅผ */ |
| .hero-name { |
| font-weight: 600 !important; |
| color: var(--primary-color) !important; |
| margin-bottom: 5px !important; |
| overflow: hidden !important; |
| text-overflow: ellipsis !important; |
| white-space: nowrap !important; |
| } |
| |
| /* ่ฑ้ๅ็งฐ Textbox ็ฆ็จๆปๅจ */ |
| .hero-name textarea { |
| overflow: hidden !important; |
| resize: none !important; |
| } |
| |
| /* ่ฑ้่ง่ฒๆ ทๅผ */ |
| .hero-roles { |
| font-size: 12px !important; |
| color: var(--text-light) !important; |
| margin-bottom: 10px !important; |
| overflow: hidden !important; |
| white-space: nowrap !important; |
| } |
| |
| /* ่ฑ้่ง่ฒ Textbox ็ฆ็จๆปๅจ */ |
| .hero-roles textarea { |
| overflow: hidden !important; |
| resize: none !important; |
| } |
| |
| /* ่ฑ้ๆ้ฎๆ ทๅผ */ |
| .hero-buttons { |
| display: flex; |
| gap: 8px; |
| width: 100%; |
| margin-top: auto; |
| } |
| |
| .hero-buttons .gr-button { |
| flex: 1; |
| font-size: 12px !important; |
| padding: 6px 10px !important; |
| } |
| |
| /* ๆ้ฎๆ ทๅผ */ |
| .gr-button { |
| border-radius: 8px !important; |
| font-weight: 600 !important; |
| transition: var(--transition) !important; |
| padding: 8px 16px !important; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .gr-button:hover { |
| transform: translateY(-2px) !important; |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important; |
| } |
| |
| .gr-button:active { |
| transform: translateY(0) !important; |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important; |
| } |
| |
| .gr-button::before { |
| content: ''; |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| width: 0; |
| height: 0; |
| background: rgba(255, 255, 255, 0.3); |
| border-radius: 50%; |
| transform: translate(-50%, -50%); |
| transition: var(--transition-fast); |
| } |
| |
| .gr-button:active::before { |
| width: 300px; |
| height: 300px; |
| } |
| |
| /* ๆปๅจๆ้ฎ */ |
| .scroll-buttons { |
| position: fixed; |
| bottom: 30px; |
| right: 30px; |
| z-index: 1000; |
| display: flex; |
| flex-direction: column; |
| gap: 10px; |
| } |
| |
| .scroll-buttons .gr-button { |
| background-color: var(--primary-color) !important; |
| color: white !important; |
| border: none !important; |
| padding: 12px 16px !important; |
| border-radius: 50% !important; |
| min-width: 50px !important; |
| height: 50px !important; |
| display: flex !important; |
| align-items: center !important; |
| justify-content: center !important; |
| box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); |
| } |
| |
| .scroll-buttons .gr-button:hover { |
| background-color: var(--secondary-color) !important; |
| transform: translateY(-3px) !important; |
| } |
| |
| /* ๅ่ฝๆ้ฎๅบๅ */ |
| .action-buttons { |
| display: flex; |
| gap: 15px; |
| justify-content: center; |
| margin: 20px 0; |
| padding: 0 20px; |
| } |
| |
| /* ้ไผๆพ็คบๅบๅ */ |
| .team-display { |
| background-color: var(--card-background); |
| border-radius: var(--border-radius); |
| padding: 20px; |
| box-shadow: var(--box-shadow); |
| margin: 20px 0; |
| gap: 30px; |
| } |
| |
| .team-textbox { |
| background-color: #f8f9fa !important; |
| border: 1px solid var(--secondary-color) !important; |
| border-radius: var(--border-radius) !important; |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important; |
| font-size: 14px !important; |
| line-height: 1.5 !important; |
| } |
| |
| /* ๅๅบๅผ่ฎพ่ฎก */ |
| @media (max-width: 768px) { |
| .gradio-container { |
| padding: 10px; |
| } |
| |
| h1 { |
| font-size: 1.5rem !important; |
| margin-bottom: 20px !important; |
| } |
| |
| .hero-grid { |
| grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); |
| gap: 12px; |
| padding: 10px; |
| max-height: 500px; |
| } |
| |
| .hero-card { |
| padding: 12px; |
| } |
| |
| .hero-image { |
| width: 90px !important; |
| height: 90px !important; |
| } |
| |
| .hero-name { |
| font-size: 12px !important; |
| } |
| |
| .hero-roles { |
| font-size: 10px !important; |
| } |
| |
| .hero-buttons .gr-button { |
| font-size: 10px !important; |
| padding: 4px 8px !important; |
| } |
| |
| .action-buttons { |
| flex-direction: column; |
| align-items: center; |
| gap: 10px; |
| } |
| |
| .action-buttons .gr-button { |
| width: 100%; |
| max-width: 200px; |
| } |
| |
| .team-display { |
| flex-direction: column; |
| gap: 20px; |
| padding: 15px; |
| } |
| |
| .search-result-item { |
| flex-direction: column; |
| align-items: flex-start; |
| gap: 12px; |
| padding: 15px; |
| } |
| |
| .search-result-image { |
| width: 70px !important; |
| height: 70px !important; |
| } |
| |
| .search-result-title { |
| font-size: 16px !important; |
| } |
| |
| .search-result-name { |
| font-size: 14px !important; |
| } |
| |
| .search-result-roles { |
| font-size: 12px !important; |
| } |
| |
| .search-result-buttons { |
| width: 100%; |
| justify-content: space-between; |
| } |
| |
| .search-result-button { |
| flex: 1; |
| font-size: 13px; |
| padding: 8px 12px; |
| } |
| |
| .scroll-buttons { |
| bottom: 20px; |
| right: 20px; |
| } |
| |
| .scroll-buttons .gr-button { |
| min-width: 40px !important; |
| height: 40px !important; |
| padding: 8px 12px !important; |
| } |
| } |
| |
| /* ๆ็ดข็ปๆๆ ทๅผ */ |
| .search-results { |
| display: flex; |
| flex-direction: column; |
| gap: 16px; |
| margin: 20px 0; |
| padding: 0 10px; |
| } |
| |
| .search-result-item { |
| display: flex; |
| align-items: center; |
| gap: 20px; |
| padding: 20px; |
| background-color: var(--card-background); |
| border-radius: var(--border-radius); |
| box-shadow: var(--box-shadow); |
| transition: var(--transition); |
| } |
| |
| .search-result-item:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); |
| } |
| |
| .search-result-image { |
| width: 90px; |
| height: 90px; |
| border-radius: 12px; |
| object-fit: cover; |
| border: 3px solid var(--secondary-color); |
| flex-shrink: 0; |
| } |
| |
| .search-result-info { |
| flex: 1; |
| } |
| |
| .search-result-title { |
| font-weight: 700; |
| font-size: 18px; |
| color: var(--primary-color); |
| margin-bottom: 6px; |
| } |
| |
| .search-result-name { |
| font-size: 16px; |
| color: var(--text-light); |
| margin-bottom: 6px; |
| } |
| |
| .search-result-roles { |
| font-size: 14px; |
| color: var(--text-light); |
| } |
| |
| .search-result-buttons { |
| display: flex; |
| gap: 12px; |
| flex-shrink: 0; |
| } |
| |
| .search-result-button { |
| padding: 10px 20px; |
| border: none; |
| border-radius: 8px; |
| font-size: 15px; |
| font-weight: 600; |
| cursor: pointer; |
| transition: var(--transition); |
| min-width: 90px; |
| text-align: center; |
| } |
| |
| .search-result-button.primary { |
| background-color: var(--primary-color); |
| color: white; |
| } |
| |
| .search-result-button.secondary { |
| background-color: var(--secondary-color); |
| color: white; |
| } |
| |
| .search-result-button:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
| } |
| |
| .search-empty { |
| text-align: center; |
| padding: 40px 20px; |
| color: var(--text-light); |
| background-color: var(--card-background); |
| border-radius: var(--border-radius); |
| box-shadow: var(--box-shadow); |
| margin: 20px 0; |
| } |
| |
| /* ไธญๅๅฑๅนๅๅบๅผ่ฐๆด */ |
| @media (min-width: 769px) and (max-width: 1024px) { |
| .hero-grid { |
| grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); |
| gap: 12px; |
| } |
| } |
| """, |
| head=""" |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
| <style> |
| /* ๅนณๆปๆปๅจ */ |
| html { |
| scroll-behavior: smooth; |
| } |
| |
| /* ่ชๅฎไนๆปๅจๆก */ |
| ::-webkit-scrollbar { |
| width: 8px; |
| } |
| |
| ::-webkit-scrollbar-track { |
| background: #f1f1f1; |
| } |
| |
| ::-webkit-scrollbar-thumb { |
| background: var(--primary-color); |
| border-radius: 4px; |
| } |
| |
| ::-webkit-scrollbar-thumb:hover { |
| background: var(--secondary-color); |
| } |
| </style> |
| """, |
| ) as app: |
| gr.Markdown("# ChatGptLoL - ่ฑ้่็่ฑ้้ๆฉๅทฅๅ
ท") |
|
|
| for tab_name in role_tabs: |
| create_hero_tab(tab_name) |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| search_query = gr.Textbox( |
| label="ๆ็ดข่ฑ้", |
| placeholder="่พๅ
ฅ่ฑ้ๅ็งฐๆๅ
ณ้ฎ่ฏ", |
| elem_id="search-hero-input", |
| ) |
|
|
| search_results_html = gr.HTML(elem_id="search-results-html", visible=True) |
|
|
| |
| import time |
| last_search_time = 0 |
| search_debounce_delay = 0.3 |
| previous_results = "" |
|
|
| def update_search_results(query): |
| global last_search_time, previous_results |
| current_time = time.time() |
| |
| |
| if current_time - last_search_time < search_debounce_delay: |
| |
| return previous_results |
| |
| last_search_time = current_time |
| results = search_heroes(query) |
| if not results: |
| previous_results = "<div class='search-empty'>ๆฒกๆๆพๅฐๅน้
็่ฑ้</div>" |
| return previous_results |
|
|
| html_content = '<div class="search-results">' |
| for h in results: |
| detail_url = ( |
| f"https://101.qq.com/#/hero-detail?heroid={h.heroId}&tab=equipment" |
| ) |
| equipment_url = ( |
| f"https://www.metasrc.com/lol/mayhem/build/{h.alias.lower()}" |
| ) |
| html_content += f""" |
| <div class="search-result-item"> |
| <img src="{h.image_url}" class="search-result-image" loading="lazy" /> |
| <div class="search-result-info"> |
| <div class="search-result-title">{h.title}</div> |
| <div class="search-result-name">{h.name}</div> |
| <div class="search-result-roles">{''.join(h.roles)}</div> |
| </div> |
| <div class="search-result-buttons"> |
| <button class="search-result-button primary" onclick="window.open('{detail_url}', '_blank')">่ฏฆๆ
</button> |
| <button class="search-result-button secondary" onclick="window.open('{equipment_url}', '_blank')">ๅบ่ฃ
</button> |
| </div> |
| </div> |
| """ |
| html_content += "</div>" |
| previous_results = html_content |
| return html_content |
|
|
| search_query.change( |
| fn=update_search_results, inputs=[search_query], outputs=[search_results_html] |
| ) |
|
|
| search_results = gr.Textbox( |
| label="ๆ็ดข็ปๆ", lines=10, interactive=False, visible=False |
| ) |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| with gr.Row(elem_id="scroll-buttons", elem_classes="scroll-buttons"): |
| gr.Button("โ", variant="primary", elem_classes=["scroll-top-btn"]).click( |
| fn=lambda: None, |
| inputs=[], |
| outputs=[], |
| js="() => window.scrollTo({top: 0, behavior: 'smooth'})" |
| ) |
| gr.Button("๐", variant="secondary", elem_classes=["scroll-search-btn"]).click( |
| fn=lambda: None, |
| inputs=[], |
| outputs=[], |
| js='() => { const element = document.getElementById("search-hero-input"); if (element) { const rect = element.getBoundingClientRect(); window.scrollTo({top: window.pageYOffset + rect.top - 100, behavior: "smooth"}); } }' |
| ) |
|
|
| app.launch() |
|
|