基本完成
This commit is contained in:
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
|
|
||||||
project(rewrite_qt VERSION 1.0.0 LANGUAGES CXX)
|
project(rewrite_qt VERSION 1.0.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(REWRITE_QT_DISPLAY_NAME "人脸识别考勤系统")
|
||||||
set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml")
|
set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml")
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -54,6 +55,7 @@ endif()
|
|||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
set_target_properties(apprewrite_qt PROPERTIES
|
set_target_properties(apprewrite_qt PROPERTIES
|
||||||
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
|
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
|
||||||
|
QT_ANDROID_APP_NAME "${REWRITE_QT_DISPLAY_NAME}"
|
||||||
QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
|
QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -184,10 +184,11 @@ CMake 中 Android 相关配置:
|
|||||||
|
|
||||||
```cmake
|
```cmake
|
||||||
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
|
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
|
||||||
|
QT_ANDROID_APP_NAME "人脸识别考勤系统"
|
||||||
QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
|
QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
|
||||||
```
|
```
|
||||||
|
|
||||||
`QT_ANDROID_APP_ICON` 需要 Qt 6.9 或更高版本。当前 Qt 6.10 可正常使用。
|
`QT_ANDROID_APP_NAME` 用于设置 Android 桌面显示名,`QT_ANDROID_APP_ICON` 用于设置启动图标。
|
||||||
|
|
||||||
## 6. 功能说明
|
## 6. 功能说明
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
android.overridePathCheck=true
|
||||||
|
android.useAndroidX=true
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=Face Attendance
|
Name=人脸识别考勤系统
|
||||||
Exec=apprewrite_qt
|
Exec=apprewrite_qt
|
||||||
Icon=rewrite_qt
|
Icon=rewrite_qt
|
||||||
Terminal=false
|
Terminal=false
|
||||||
|
|||||||
+133
-72
@@ -10,7 +10,7 @@ ApplicationWindow {
|
|||||||
minimumWidth: 900
|
minimumWidth: 900
|
||||||
minimumHeight: 620
|
minimumHeight: 620
|
||||||
visible: true
|
visible: true
|
||||||
title: "人脸识别考勤系统 - QML 管理端"
|
title: "人脸识别考勤系统"
|
||||||
color: "#f6f7f9"
|
color: "#f6f7f9"
|
||||||
|
|
||||||
readonly property color ink900: "#182230"
|
readonly property color ink900: "#182230"
|
||||||
@@ -43,6 +43,7 @@ ApplicationWindow {
|
|||||||
readonly property bool denseLayout: width < 1380
|
readonly property bool denseLayout: width < 1380
|
||||||
readonly property bool narrowLayout: width < 1280
|
readonly property bool narrowLayout: width < 1280
|
||||||
readonly property bool slimLayout: width < 1040
|
readonly property bool slimLayout: width < 1040
|
||||||
|
readonly property bool phoneLayout: width < 560
|
||||||
readonly property int sidebarWidth: slimLayout ? 0 : (compactLayout ? 212 : 240)
|
readonly property int sidebarWidth: slimLayout ? 0 : (compactLayout ? 212 : 240)
|
||||||
|
|
||||||
font.family: "Microsoft YaHei UI"
|
font.family: "Microsoft YaHei UI"
|
||||||
@@ -255,31 +256,33 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
component EmptyState: Item {
|
component EmptyState: Item {
|
||||||
|
id: emptyState
|
||||||
property string title: ""
|
property string title: ""
|
||||||
property string description: ""
|
property string description: ""
|
||||||
property string badgeText: ""
|
property string badgeText: ""
|
||||||
property color accent: accentColor
|
property color accent: accentColor
|
||||||
|
readonly property bool tightState: phoneLayout || height < 190
|
||||||
|
|
||||||
implicitWidth: 320
|
implicitWidth: phoneLayout ? 280 : 320
|
||||||
implicitHeight: 220
|
implicitHeight: phoneLayout ? 154 : 220
|
||||||
|
width: Math.min(implicitWidth, parent ? Math.max(180, parent.width - 28) : implicitWidth)
|
||||||
|
height: Math.min(implicitHeight, parent ? Math.max(126, parent.height - 20) : implicitHeight)
|
||||||
z: 20
|
z: 20
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.centerIn: parent
|
anchors.fill: parent
|
||||||
width: Math.min(parent.width, 320)
|
|
||||||
height: 200
|
|
||||||
radius: 8
|
radius: 8
|
||||||
color: "#fffaf4"
|
color: "#fffaf4"
|
||||||
border.color: "#e7ddd2"
|
border.color: "#e7ddd2"
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: 12
|
spacing: emptyState.tightState ? 8 : 12
|
||||||
width: parent.width - 40
|
width: parent.width - 32
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 64
|
width: emptyState.tightState ? 52 : 64
|
||||||
height: 64
|
height: width
|
||||||
radius: 8
|
radius: 8
|
||||||
color: Qt.tint("#ffffff", Qt.rgba(accent.r, accent.g, accent.b, 0.16))
|
color: Qt.tint("#ffffff", Qt.rgba(accent.r, accent.g, accent.b, 0.16))
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -288,7 +291,7 @@ ApplicationWindow {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: badgeText
|
text: badgeText
|
||||||
color: accent
|
color: accent
|
||||||
font.pixelSize: 22
|
font.pixelSize: emptyState.tightState ? 18 : 22
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,17 +302,18 @@ ApplicationWindow {
|
|||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: ink900
|
color: ink900
|
||||||
font.pixelSize: 20
|
font.pixelSize: emptyState.tightState ? 18 : 20
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
visible: !emptyState.tightState || parent.width > 260
|
||||||
text: description
|
text: description
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: ink500
|
color: ink500
|
||||||
font.pixelSize: 13
|
font.pixelSize: emptyState.tightState ? 12 : 13
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,7 +345,7 @@ ApplicationWindow {
|
|||||||
property string description: ""
|
property string description: ""
|
||||||
property color accent: accentColor
|
property color accent: accentColor
|
||||||
|
|
||||||
implicitHeight: descriptionLabel.visible ? 52 : 32
|
implicitHeight: descriptionLabel.visible ? (phoneLayout ? 64 : 52) : 32
|
||||||
implicitWidth: 300
|
implicitWidth: 300
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@@ -362,7 +366,7 @@ ApplicationWindow {
|
|||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: sectionHeader.title
|
text: sectionHeader.title
|
||||||
font.pixelSize: 22
|
font.pixelSize: phoneLayout ? 20 : 22
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: ink900
|
color: ink900
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
@@ -404,6 +408,29 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
component MobileNavTabButton: TabButton {
|
||||||
|
id: control
|
||||||
|
implicitHeight: 42
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 8
|
||||||
|
color: control.checked ? tealColor : panelStrong
|
||||||
|
border.width: 1
|
||||||
|
border.color: control.checked ? tealColor : lineColor
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Label {
|
||||||
|
text: control.text
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: control.checked ? "#f6fbfb" : ink700
|
||||||
|
font.pixelSize: phoneLayout ? 12 : 13
|
||||||
|
font.bold: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function applyRecordFilters() {
|
function applyRecordFilters() {
|
||||||
appController.applyFilters(
|
appController.applyFilters(
|
||||||
classFilter.currentText,
|
classFilter.currentText,
|
||||||
@@ -702,8 +729,11 @@ ApplicationWindow {
|
|||||||
|
|
||||||
Label {
|
Label {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "管理端"
|
width: parent.width - 18
|
||||||
font.pixelSize: compactLayout ? 24 : 28
|
text: "人脸识别考勤系统"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
font.pixelSize: compactLayout ? 17 : 19
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: "#ffffff"
|
color: "#ffffff"
|
||||||
}
|
}
|
||||||
@@ -835,7 +865,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: slimLayout ? 96 : 142
|
Layout.preferredHeight: phoneLayout ? 108 : (slimLayout ? 96 : 142)
|
||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
@@ -852,10 +882,12 @@ ApplicationWindow {
|
|||||||
spacing: 6
|
spacing: 6
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
text: ["考勤记录总览", "统计分析面板", "配置与同步中心", "人脸资料管理", "关于"][window.currentPageIndex]
|
text: ["考勤记录总览", "统计分析面板", "配置与同步中心", "人脸资料管理", "关于"][window.currentPageIndex]
|
||||||
font.pixelSize: slimLayout ? 20 : (compactLayout ? 24 : 28)
|
font.pixelSize: slimLayout ? 20 : (compactLayout ? 24 : 28)
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: ink900
|
color: ink900
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
@@ -922,15 +954,19 @@ ApplicationWindow {
|
|||||||
id: navigationBar
|
id: navigationBar
|
||||||
visible: slimLayout
|
visible: slimLayout
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: visible ? implicitHeight : 0
|
Layout.preferredHeight: visible ? 42 : 0
|
||||||
|
spacing: 6
|
||||||
|
padding: 0
|
||||||
|
property real tabWidth: (width - spacing * 4) / 5
|
||||||
currentIndex: window.currentPageIndex
|
currentIndex: window.currentPageIndex
|
||||||
onCurrentIndexChanged: window.switchPage(currentIndex)
|
onCurrentIndexChanged: window.switchPage(currentIndex)
|
||||||
|
background: Item {}
|
||||||
|
|
||||||
TabButton { text: "考勤记录" }
|
MobileNavTabButton { width: navigationBar.tabWidth; text: "考勤记录" }
|
||||||
TabButton { text: "统计分析" }
|
MobileNavTabButton { width: navigationBar.tabWidth; text: "统计分析" }
|
||||||
TabButton { text: "配置中心" }
|
MobileNavTabButton { width: navigationBar.tabWidth; text: "配置中心" }
|
||||||
TabButton { text: "人脸管理" }
|
MobileNavTabButton { width: navigationBar.tabWidth; text: "人脸管理" }
|
||||||
TabButton { text: "关于" }
|
MobileNavTabButton { width: navigationBar.tabWidth; text: "关于" }
|
||||||
}
|
}
|
||||||
|
|
||||||
StackLayout {
|
StackLayout {
|
||||||
@@ -1069,7 +1105,7 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
Layout.preferredHeight: slimLayout ? 174 : 92
|
Layout.preferredHeight: phoneLayout ? 236 : (slimLayout ? 174 : 92)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
@@ -1080,8 +1116,8 @@ ApplicationWindow {
|
|||||||
rowSpacing: 12
|
rowSpacing: 12
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Layout.preferredWidth: 150
|
Layout.fillWidth: true
|
||||||
width: 150
|
Layout.preferredWidth: phoneLayout ? 0 : 150
|
||||||
spacing: 6
|
spacing: 6
|
||||||
Label { text: "班级"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
Label { text: "班级"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
||||||
AppComboBox {
|
AppComboBox {
|
||||||
@@ -1093,8 +1129,8 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Layout.preferredWidth: 160
|
Layout.fillWidth: true
|
||||||
width: 160
|
Layout.preferredWidth: phoneLayout ? 0 : 160
|
||||||
spacing: 6
|
spacing: 6
|
||||||
Label { text: "学号"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
Label { text: "学号"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
||||||
AppComboBox {
|
AppComboBox {
|
||||||
@@ -1106,8 +1142,8 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Layout.preferredWidth: 190
|
Layout.fillWidth: true
|
||||||
width: 190
|
Layout.preferredWidth: phoneLayout ? 0 : 190
|
||||||
spacing: 6
|
spacing: 6
|
||||||
Label { text: "姓名"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
Label { text: "姓名"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
||||||
AppTextField {
|
AppTextField {
|
||||||
@@ -1119,8 +1155,8 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Layout.preferredWidth: 160
|
Layout.fillWidth: true
|
||||||
width: 160
|
Layout.preferredWidth: phoneLayout ? 0 : 160
|
||||||
spacing: 6
|
spacing: 6
|
||||||
Label { text: "日期"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
Label { text: "日期"; color: ink700; font.bold: true; font.pixelSize: 12 }
|
||||||
AppComboBox {
|
AppComboBox {
|
||||||
@@ -1133,8 +1169,9 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Layout.preferredWidth: 150
|
Layout.fillWidth: true
|
||||||
width: dateFilter.currentIndex === 4 ? 150 : 0
|
Layout.preferredWidth: phoneLayout ? 0 : 150
|
||||||
|
width: dateFilter.currentIndex === 4 ? implicitWidth : 0
|
||||||
height: dateFilter.currentIndex === 4 ? implicitHeight : 0
|
height: dateFilter.currentIndex === 4 ? implicitHeight : 0
|
||||||
visible: dateFilter.currentIndex === 4
|
visible: dateFilter.currentIndex === 4
|
||||||
spacing: 6
|
spacing: 6
|
||||||
@@ -1148,9 +1185,11 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Flow {
|
||||||
|
Layout.columnSpan: slimLayout ? 2 : 1
|
||||||
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignBottom
|
Layout.alignment: Qt.AlignBottom
|
||||||
height: 42
|
height: implicitHeight
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
SecondaryButton {
|
SecondaryButton {
|
||||||
@@ -1180,12 +1219,12 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
property real timeColWidth: Math.max(168, Math.min(220, width * 0.21))
|
property real timeColWidth: phoneLayout ? 112 : Math.max(168, Math.min(220, width * 0.21))
|
||||||
property real classColWidth: Math.max(88, Math.min(124, width * 0.11))
|
property real classColWidth: phoneLayout ? 0 : Math.max(88, Math.min(124, width * 0.11))
|
||||||
property real studentColWidth: Math.max(86, Math.min(116, width * 0.10))
|
property real studentColWidth: phoneLayout ? 64 : Math.max(86, Math.min(116, width * 0.10))
|
||||||
property real nameColWidth: Math.max(118, Math.min(158, width * 0.14))
|
property real nameColWidth: phoneLayout ? 88 : Math.max(118, Math.min(158, width * 0.14))
|
||||||
property real confidenceColWidth: Math.max(96, Math.min(126, width * 0.11))
|
property real confidenceColWidth: phoneLayout ? 0 : Math.max(96, Math.min(126, width * 0.11))
|
||||||
property real statusColWidth: Math.max(84, Math.min(102, width * 0.09))
|
property real statusColWidth: phoneLayout ? 64 : Math.max(84, Math.min(102, width * 0.09))
|
||||||
property bool showClassColumn: !denseLayout
|
property bool showClassColumn: !denseLayout
|
||||||
property bool showConfidenceColumn: !narrowLayout
|
property bool showConfidenceColumn: !narrowLayout
|
||||||
|
|
||||||
@@ -1325,7 +1364,7 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
Layout.preferredHeight: slimLayout ? 150 : 78
|
Layout.preferredHeight: phoneLayout ? 186 : (slimLayout ? 150 : 78)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
@@ -1338,7 +1377,8 @@ ApplicationWindow {
|
|||||||
|
|
||||||
AppComboBox {
|
AppComboBox {
|
||||||
id: quickStatisticsFilter
|
id: quickStatisticsFilter
|
||||||
Layout.preferredWidth: 150
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: phoneLayout ? 0 : 150
|
||||||
model: ["今天", "最近7天", "最近30天", "本月"]
|
model: ["今天", "最近7天", "最近30天", "本月"]
|
||||||
currentIndex: 2
|
currentIndex: 2
|
||||||
onCurrentTextChanged: {
|
onCurrentTextChanged: {
|
||||||
@@ -1349,14 +1389,16 @@ ApplicationWindow {
|
|||||||
|
|
||||||
AppTextField {
|
AppTextField {
|
||||||
id: statsStartField
|
id: statsStartField
|
||||||
Layout.preferredWidth: 150
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: phoneLayout ? 0 : 150
|
||||||
placeholderText: "开始日期"
|
placeholderText: "开始日期"
|
||||||
onEditingFinished: appController.updateStatisticsRange(text, statsEndField.text)
|
onEditingFinished: appController.updateStatisticsRange(text, statsEndField.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
AppTextField {
|
AppTextField {
|
||||||
id: statsEndField
|
id: statsEndField
|
||||||
Layout.preferredWidth: 150
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: phoneLayout ? 0 : 150
|
||||||
placeholderText: "结束日期"
|
placeholderText: "结束日期"
|
||||||
onEditingFinished: appController.updateStatisticsRange(statsStartField.text, text)
|
onEditingFinished: appController.updateStatisticsRange(statsStartField.text, text)
|
||||||
}
|
}
|
||||||
@@ -1375,13 +1417,13 @@ ApplicationWindow {
|
|||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
columns: slimLayout ? 3 : (compactLayout ? 1 : 3)
|
columns: phoneLayout ? 1 : (slimLayout ? 3 : (compactLayout ? 1 : 3))
|
||||||
rowSpacing: 10
|
rowSpacing: 10
|
||||||
columnSpacing: 14
|
columnSpacing: 14
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: slimLayout ? 74 : 100
|
Layout.preferredHeight: phoneLayout ? 68 : (slimLayout ? 74 : 100)
|
||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
@@ -1411,7 +1453,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: slimLayout ? 74 : 100
|
Layout.preferredHeight: phoneLayout ? 68 : (slimLayout ? 74 : 100)
|
||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
@@ -1441,7 +1483,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: slimLayout ? 74 : 100
|
Layout.preferredHeight: phoneLayout ? 68 : (slimLayout ? 74 : 100)
|
||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
@@ -1460,6 +1502,7 @@ ApplicationWindow {
|
|||||||
font.pixelSize: slimLayout ? 14 : (compactLayout ? 18 : 20)
|
font.pixelSize: slimLayout ? 14 : (compactLayout ? 18 : 20)
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: goldColor
|
color: goldColor
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,14 +1526,15 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
property real studentColWidth: Math.max(90, Math.min(128, width * 0.12))
|
property real studentColWidth: phoneLayout ? 68 : Math.max(90, Math.min(128, width * 0.12))
|
||||||
property real nameColWidth: Math.max(128, Math.min(188, width * 0.17))
|
property real nameColWidth: phoneLayout ? 96 : Math.max(128, Math.min(188, width * 0.17))
|
||||||
property real totalColWidth: Math.max(96, Math.min(124, width * 0.12))
|
property real totalColWidth: phoneLayout ? 92 : Math.max(96, Math.min(124, width * 0.12))
|
||||||
property real todayColWidth: Math.max(92, Math.min(110, width * 0.10))
|
property real todayColWidth: Math.max(92, Math.min(110, width * 0.10))
|
||||||
property real lastColWidth: Math.max(180, Math.min(240, width * 0.20))
|
property real lastColWidth: Math.max(180, Math.min(240, width * 0.20))
|
||||||
property real avgColWidth: Math.max(98, Math.min(126, width * 0.11))
|
property real avgColWidth: Math.max(98, Math.min(126, width * 0.11))
|
||||||
property bool showTodayColumn: !denseLayout
|
property bool showTodayColumn: !denseLayout
|
||||||
property bool showLastColumn: !narrowLayout
|
property bool showLastColumn: !narrowLayout
|
||||||
|
property bool showAverageColumn: !phoneLayout
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -1524,7 +1568,12 @@ ApplicationWindow {
|
|||||||
Layout.preferredWidth: statisticsTableCard.lastColWidth
|
Layout.preferredWidth: statisticsTableCard.lastColWidth
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
Label { text: "平均置信度"; Layout.preferredWidth: statisticsTableCard.avgColWidth; font.bold: true }
|
Label {
|
||||||
|
text: "平均置信度"
|
||||||
|
visible: statisticsTableCard.showAverageColumn
|
||||||
|
Layout.preferredWidth: statisticsTableCard.avgColWidth
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1574,7 +1623,13 @@ ApplicationWindow {
|
|||||||
Layout.preferredWidth: statisticsTableCard.lastColWidth
|
Layout.preferredWidth: statisticsTableCard.lastColWidth
|
||||||
color: ink700
|
color: ink700
|
||||||
}
|
}
|
||||||
Label { text: model.averageConfidenceText; Layout.preferredWidth: statisticsTableCard.avgColWidth; color: tealColor; font.bold: true }
|
Label {
|
||||||
|
text: model.averageConfidenceText
|
||||||
|
visible: statisticsTableCard.showAverageColumn
|
||||||
|
Layout.preferredWidth: statisticsTableCard.avgColWidth
|
||||||
|
color: tealColor
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1622,7 +1677,7 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
Layout.preferredHeight: slimLayout ? 174 : 88
|
Layout.preferredHeight: phoneLayout ? 218 : (slimLayout ? 174 : 88)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
@@ -1648,11 +1703,13 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SecondaryButton {
|
SecondaryButton {
|
||||||
|
Layout.fillWidth: phoneLayout
|
||||||
text: "保存地址"
|
text: "保存地址"
|
||||||
onClicked: appController.serverUrl = serverUrlField.text
|
onClicked: appController.serverUrl = serverUrlField.text
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimaryButton {
|
PrimaryButton {
|
||||||
|
Layout.fillWidth: phoneLayout
|
||||||
text: "测试连接"
|
text: "测试连接"
|
||||||
fillColor: tealColor
|
fillColor: tealColor
|
||||||
onClicked: appController.testConnection()
|
onClicked: appController.testConnection()
|
||||||
@@ -2019,13 +2076,15 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
Layout.preferredHeight: slimLayout ? 132 : 88
|
Layout.preferredHeight: phoneLayout ? 170 : (slimLayout ? 132 : 88)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
RowLayout {
|
GridLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: slimLayout ? 12 : 18
|
anchors.margins: slimLayout ? 12 : 18
|
||||||
spacing: 12
|
columns: phoneLayout ? 1 : 2
|
||||||
|
rowSpacing: 12
|
||||||
|
columnSpacing: 12
|
||||||
|
|
||||||
SectionHeader {
|
SectionHeader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -2034,8 +2093,9 @@ ApplicationWindow {
|
|||||||
accent: goldColor
|
accent: goldColor
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Flow {
|
||||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
Layout.fillWidth: phoneLayout
|
||||||
|
Layout.alignment: phoneLayout ? Qt.AlignLeft : (Qt.AlignRight | Qt.AlignVCenter)
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
SecondaryButton { text: "刷新"; onClicked: appController.refreshFaces() }
|
SecondaryButton { text: "刷新"; onClicked: appController.refreshFaces() }
|
||||||
@@ -2059,14 +2119,14 @@ ApplicationWindow {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 16
|
anchors.margins: 16
|
||||||
clip: true
|
clip: true
|
||||||
property int cardColumns: Math.max(1, Math.floor(width / (compactLayout ? 236 : 260)))
|
property int cardColumns: phoneLayout ? 1 : Math.max(1, Math.floor(width / (compactLayout ? 236 : 260)))
|
||||||
cellWidth: Math.max(240, Math.floor(width / cardColumns))
|
cellWidth: Math.max(phoneLayout ? 280 : 240, Math.floor(width / cardColumns))
|
||||||
cellHeight: 332
|
cellHeight: phoneLayout ? 392 : 352
|
||||||
model: appController.faceModel
|
model: appController.faceModel
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
width: Math.min(244, GridView.view.cellWidth - 18)
|
width: Math.min(phoneLayout ? 300 : 244, GridView.view.cellWidth - 18)
|
||||||
height: 308
|
height: phoneLayout ? 368 : 328
|
||||||
property bool hovered: faceHoverHandler.hovered
|
property bool hovered: faceHoverHandler.hovered
|
||||||
radius: 8
|
radius: 8
|
||||||
color: hovered ? "#fff6ef" : "#ffffff"
|
color: hovered ? "#fff6ef" : "#ffffff"
|
||||||
@@ -2085,7 +2145,7 @@ ApplicationWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: compactLayout ? 152 : 168
|
Layout.preferredHeight: phoneLayout ? 140 : (compactLayout ? 152 : 168)
|
||||||
radius: 16
|
radius: 16
|
||||||
color: model.hasPhoto ? "#eef3f5" : goldSoft
|
color: model.hasPhoto ? "#eef3f5" : goldSoft
|
||||||
border.color: model.hasPhoto ? "#dbe4ea" : "#eadbb0"
|
border.color: model.hasPhoto ? "#dbe4ea" : "#eadbb0"
|
||||||
@@ -2179,15 +2239,16 @@ ApplicationWindow {
|
|||||||
radius: 8
|
radius: 8
|
||||||
color: panelStrong
|
color: panelStrong
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
|
clip: true
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 24
|
anchors.margins: phoneLayout ? 16 : 24
|
||||||
spacing: 18
|
spacing: phoneLayout ? 12 : 18
|
||||||
|
|
||||||
SectionHeader {
|
SectionHeader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
title: "人脸识别考勤系统管理端"
|
title: "人脸识别考勤系统"
|
||||||
description: "用于连接考勤服务端,集中查看签到记录、统计考勤情况、维护签到时段、管理名称映射与人脸照片绑定。"
|
description: "用于连接考勤服务端,集中查看签到记录、统计考勤情况、维护签到时段、管理名称映射与人脸照片绑定。"
|
||||||
accent: tealColor
|
accent: tealColor
|
||||||
}
|
}
|
||||||
@@ -2220,7 +2281,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 92
|
Layout.preferredHeight: phoneLayout ? 124 : 108
|
||||||
radius: 8
|
radius: 8
|
||||||
color: "#f8fafb"
|
color: "#f8fafb"
|
||||||
border.color: lineColor
|
border.color: lineColor
|
||||||
|
|||||||
Reference in New Issue
Block a user