Files
atomk-hermes-skills/skills/archived/tongtool-order-remark/SKILL.md
T

7.4 KiB

name, description
name description
tongtool-order-remark Log into Tongtool ERP, search for a specific order by ID, and add a remark.

Tongtool Order Remark Automation

This skill automates the process of logging into the Tongtool ERP system, navigating to a specific order using global search, and adding a custom remark to the order details.

Dependencies

  • Python 3
  • DrissionPage
  • ddddocr
  • requests

The Script

This script performs the following steps:

  1. Opens a headless Chromium browser using DrissionPage (Crucial: 1920x1080 window size).
  2. Navigates to the Tongtool login page (passport.tongtool.com).
  3. Uses ddddocr to solve the captcha and logs in.
  4. Navigates to the ERP dashboard to initialize the session.
  5. Uses the global search URL to jump directly to the target order's detail page.
  6. Clicks the "Add Remark" button (#addOrderRemark).
  7. robustly injects the desired remark into the text area using JS events.
  8. Clicks the "Save" button to apply the remark using by_js=True.
from DrissionPage import ChromiumPage, ChromiumOptions
import ddddocr, requests, json, time, os

def add_order_remark(order_id: str, note_text: str, user: str = 'ozonezsjgw@163.com', pwd: str = '111111'):
    co = ChromiumOptions()
    # Path to playwright Chromium
    co.set_browser_path('/home/ubuntu/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome')
    co.set_argument('--no-sandbox')
    co.set_argument('--disable-dev-shm-usage')
    # CRITICAL: Use a large window size to ensure the responsive UI displays the detail pane and action buttons
    co.set_argument('--window-size=1920,1080')
    co.headless()
    co.auto_port()

    driver = ChromiumPage(co)

    # Helper: Fix ddddocr misrecognitions
    def correct_ocr(raw_code):
        cleaned = ''.join(c for c in raw_code if c.isascii() and c.isalnum())
        return cleaned.translate(str.maketrans('oliOSsZz', '01105522'))

    # Helper: Close layui popups that block interaction
    def nuke_popups(page):
        try:
            page.run_js("""
                document.querySelectorAll('.layui-layer-shade, .layui-layer, .modal, .overlay, .jclose-blue, .close, [title="关闭"], .layui-layer-close').forEach(el => { try { el.remove(); } catch(e){} });
            """)
        except: pass

    # Login function with retry mechanism
    def login(driver, user, pwd, max_retry=5):
        for attempt in range(max_retry):
            driver.get('https://passport.tongtool.com/')
            time.sleep(3)
            driver.ele('css:input[name="username"]').input(user)
            driver.ele('css:input[name="password"]').input(pwd)
            
            img = driver.ele('css:img.pic-yzm')
            if not img:
                time.sleep(2)
                continue
                
            src = img.attr('src')
            cookies = {c['name']: c['value'] for c in driver.cookies()}
            
            try:
                resp = requests.get(src, cookies=cookies, timeout=10)
                raw = ddddocr.DdddOcr(show_ad=False).classification(resp.content)
                code = correct_ocr(raw)
                if len(code) < 4:
                    continue
                driver.ele('css:input[name="captcha"]').input(code)
                driver.ele('css:button.btn-primary').click()
                time.sleep(5)
            except Exception as e:
                print(f"Login request failed: {e}")
                continue
            
            for _ in range(5):
                if 'member' in driver.url or 'dashboard' in driver.url or 'yijiety' in driver.url:
                    return True
                time.sleep(2)
                
            if 'passport' in driver.url:
                body = driver.ele('tag:body').text
                if '验证码输入错误' in body:
                    continue  # Retry loop
                elif '密码' in body and '错误' in body:
                    print("Wrong password")
                    return False
        return False

    print("Attempting login...")
    success = login(driver, user, pwd)
    if not success:
        print("Login failed after max retries.")
        driver.quit()
        return False
    print("Login successful.")

    # Enter ERP to set session completely
    driver.get("https://yijiety.tongtool.com/dashboard/homepage/index.htm")
    time.sleep(8)
    nuke_popups(driver)

    # Navigate to the specific order using global search
    print(f"Navigating to order: {order_id}")
    search_url = (
        f"https://yijiety.tongtool.com/search/order.htm"
        f"?search_text_value={order_id}"
        f"&search_mark=salesRecordNumber"
        f"&source=global"
    )
    driver.get(search_url)
    time.sleep(12)
    nuke_popups(driver)

    # Attempt to add the remark
    remark_added = False
    btn = driver.ele('css:#addOrderRemark')
    if btn:
        a_tag = btn.ele('tag:a')
        if a_tag:
            a_tag.click(by_js=True)
            time.sleep(3)
            textarea = driver.ele('tag:textarea')
            if textarea:
                print("Writing remark robustly...")
                # MUST use JS dispatch for layui to detect the model change
                js = f"""
                    var ta = document.querySelector('textarea');
                    if(ta) {{
                        ta.value = '{note_text}';
                        ta.dispatchEvent(new Event('input', {{bubbles: true}}));
                        ta.dispatchEvent(new Event('change', {{bubbles: true}}));
                    }}
                """
                driver.run_js(js)
                time.sleep(1)
                
                for a in driver.eles('tag:a'):
                    if a.text.strip() == '保存':
                        a.click(by_js=True)
                        time.sleep(3)
                        print("Remark saved successfully!")
                        remark_added = True
                        break
            else:
                 print("Could not find the text area for the remark.")
        else:
            print("Could not find clickable element inside the remark button.")
    else:
        print("Could not find the remark button (#addOrderRemark) on the page.")

    driver.quit()
    return remark_added

if __name__ == '__main__':
    # Usage Example:
    order_id = "16Ezyhbg-PO-211-05103794125430842"
    custom_note = "Testing Order Remark Automation"
    add_order_remark(order_id, custom_note)

Pitfalls

  • Window Size Requirement (CRITICAL): It is critical to set a large window size (e.g., --window-size=1920,1080). The global search page uses a responsive grid. Without a wide window, the details pane (containing the remark button and other actions) may not be exposed or rendered in the DOM natively.
  • JS Event Dispatching for Textareas (CRITICAL): Using textarea.input('text') often fails to update the underlying layui/Vue model, resulting in a blank note being saved. Always use driver.run_js to set value and dispatch input and change events natively.
  • JS Click for Save: The save dialog anchor should be clicked with by_js=True (a.click(by_js=True)) because overlapping layui shades often block standard WebDriver clicks.
  • CSS Selector for Remark Button: The button has a specific ID. You must use driver.ele('css:#addOrderRemark'), and then click the <a> tag nested inside it.
  • Popups Blocking Interaction: Tongtool frequently shows layui popups (announcements) that cover the screen. Ensure the aggressive nuke_popups function is called before interacting.