LoginScreen.qml 5.83 KB
import QtQuick
import QtQuick.Controls.Basic
import QtQuick.Layouts
import "components"
import "." as App

Rectangle {
    id: root
    color: App.Theme.bgCanvas
    focus: true

    // 提交期间禁止重复点击 / 回车
    property bool submitting: false

    function doLogin() {
        if (submitting) return
        if (usernameField.text.length === 0 || passwordField.text.length === 0) {
            errorLabel.text = "用户名和密码不能为空"
            return
        }
        errorLabel.text = ""
        submitting = true
        // AuthBridge.login 是同步(pymysql 5s timeout),主线程会卡一下;
        // task #18 时若 db 慢需求改异步再说
        var ok = auth.login(usernameField.text, passwordField.text)
        submitting = false
        // 失败时 auth 会发 loginFailed 信号,由下面 Connections 接住
        // 成功时 auth.loggedInChanged → AppState 转发 → Main.qml StackLayout 切换
    }

    Keys.onReturnPressed: doLogin()
    Keys.onEnterPressed:  doLogin()

    Connections {
        target: auth
        function onLoginFailed(message) {
            errorLabel.text = message
        }
    }

    ColumnLayout {
        anchors.centerIn: parent
        width: 360
        spacing: 0

        Label {
            text: "登录"
            font.family: App.Theme.fontFamily
            font.pointSize: App.Theme.fontXxl
            font.weight: Font.Bold
            color: App.Theme.textPrimary
            Layout.alignment: Qt.AlignHCenter
            Layout.bottomMargin: 4
        }

        Label {
            text: "珠宝壹佰图像生成器"
            font.family: App.Theme.fontFamily
            font.pointSize: App.Theme.fontSm
            color: App.Theme.textSecondary
            Layout.alignment: Qt.AlignHCenter
            Layout.bottomMargin: App.Theme.space5
        }

        CaptionLabel {
            text: "用户名"
            Layout.bottomMargin: App.Theme.space2
        }
        ThemedTextField {
            id: usernameField
            text: ""
            placeholderText: "请输入用户名"
            enabled: !root.submitting
            Layout.fillWidth: true
            Layout.bottomMargin: App.Theme.space4
        }

        CaptionLabel {
            text: "密码"
            Layout.bottomMargin: App.Theme.space2
        }
        ThemedTextField {
            id: passwordField
            echoMode: TextInput.Password
            placeholderText: "••••••••"
            enabled: !root.submitting
            Layout.fillWidth: true
            Layout.bottomMargin: App.Theme.space2
        }

        RowLayout {
            spacing: App.Theme.space4
            Layout.fillWidth: true
            Layout.bottomMargin: App.Theme.space5

            CheckBox {
                id: rememberUser
                text: "记住用户名"
                checked: true
                enabled: !root.submitting
                font.family: App.Theme.fontFamily
                font.pointSize: App.Theme.fontSm
                contentItem: Text {
                    text: parent.text
                    font: parent.font
                    color: App.Theme.textPrimary
                    leftPadding: parent.indicator.width + 6
                    verticalAlignment: Text.AlignVCenter
                }
                indicator: Rectangle {
                    implicitWidth: 18
                    implicitHeight: 18
                    radius: 4
                    border.width: 1
                    border.color: parent.checked ? App.Theme.accent : App.Theme.borderStrong
                    color: parent.checked ? App.Theme.accent : App.Theme.bgSurface

                    Text {
                        anchors.centerIn: parent
                        text: "✓"
                        color: "white"
                        font.pixelSize: 12
                        font.weight: Font.Bold
                        visible: parent.parent.checked
                    }
                }
            }

            CheckBox {
                id: rememberPassword
                text: "记住密码"
                checked: true
                enabled: !root.submitting
                font.family: App.Theme.fontFamily
                font.pointSize: App.Theme.fontSm
                contentItem: Text {
                    text: parent.text
                    font: parent.font
                    color: App.Theme.textPrimary
                    leftPadding: parent.indicator.width + 6
                    verticalAlignment: Text.AlignVCenter
                }
                indicator: Rectangle {
                    implicitWidth: 18
                    implicitHeight: 18
                    radius: 4
                    border.width: 1
                    border.color: parent.checked ? App.Theme.accent : App.Theme.borderStrong
                    color: parent.checked ? App.Theme.accent : App.Theme.bgSurface

                    Text {
                        anchors.centerIn: parent
                        text: "✓"
                        color: "white"
                        font.pixelSize: 12
                        font.weight: Font.Bold
                        visible: parent.parent.checked
                    }
                }
            }

            Item { Layout.fillWidth: true }
        }

        PrimaryButton {
            text: root.submitting ? "登录中…" : "登录"
            enabled: !root.submitting
            Layout.fillWidth: true
            onClicked: doLogin()
        }

        Label {
            id: errorLabel
            text: ""
            font.family: App.Theme.fontFamily
            font.pointSize: App.Theme.fontXs
            color: App.Theme.danger
            wrapMode: Text.Wrap
            horizontalAlignment: Text.AlignHCenter
            Layout.fillWidth: true
            Layout.topMargin: App.Theme.space3
        }
    }
}