账单记录器迁移。
17
.clang-format
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
PointerAlignment: Left
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterFunction: true
|
||||||
|
AfterClass: true
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
ReflowComments: true
|
||||||
|
SpacesBeforeTrailingComments: 3
|
||||||
|
TabWidth: 4
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ColumnLimit: 130
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
42
.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
.idea
|
||||||
|
cmake-build-*
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
build
|
||||||
|
*.user
|
||||||
|
compile_commands.json
|
||||||
|
.vs
|
||||||
|
out
|
||||||
|
.cache
|
||||||
|
CMakeLists.txt.*
|
||||||
|
build*
|
||||||
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "ofen"]
|
||||||
|
path = ofen
|
||||||
|
url = https://www.sinxmiao.cn/taynpg/ofen
|
||||||
183
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
{
|
||||||
|
"files.autoSave": "onFocusChange",
|
||||||
|
"editor.fontSize": 14,
|
||||||
|
"cmake.configureOnOpen": true,
|
||||||
|
"editor.fontFamily": "'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light'",
|
||||||
|
"cmake.debugConfig": {
|
||||||
|
"console": "externalTerminal",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"description": "-gdb-set charset utf-8",
|
||||||
|
"text": "-gdb-set charset UTF-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Enable gdb pretty-printing",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
//"visualizerFile": "${workspaceRoot}/.vscode/qt6.natvis",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
"cmake.environment": {
|
||||||
|
//"EXTER_LIB_DIR": "C:/local"
|
||||||
|
},
|
||||||
|
"cmake.configureSettings": {
|
||||||
|
"CMAKE_PREFIX_PATH": "C:\\Qt\\Qt5.14.2\\5.14.2\\msvc2017_64",
|
||||||
|
//"CMAKE_TOOLCHAIN_FILE": "${env:TT_VCPKG}"
|
||||||
|
},
|
||||||
|
"cmake.configureArgs": [
|
||||||
|
"-Wno-dev"
|
||||||
|
],
|
||||||
|
"cmake.options.statusBarVisibility": "visible",
|
||||||
|
"cmake.generator": "Ninja",
|
||||||
|
"C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json",
|
||||||
|
"C_Cpp.default.cppStandard": "c++17",
|
||||||
|
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||||
|
"editor.inlayHints.enabled": "off",
|
||||||
|
"editor.unicodeHighlight.allowedLocales": {
|
||||||
|
"ja": true,
|
||||||
|
"zh-hant": true,
|
||||||
|
"zh-hans": true
|
||||||
|
},
|
||||||
|
"files.associations": {
|
||||||
|
"string": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"unordered_set": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"source_location": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"queue": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"shared_mutex": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"text_encoding": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"cfenv": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"ios": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"xfacet": "cpp",
|
||||||
|
"xhash": "cpp",
|
||||||
|
"xiosbase": "cpp",
|
||||||
|
"xlocale": "cpp",
|
||||||
|
"xlocbuf": "cpp",
|
||||||
|
"xlocinfo": "cpp",
|
||||||
|
"xlocmes": "cpp",
|
||||||
|
"xlocmon": "cpp",
|
||||||
|
"xlocnum": "cpp",
|
||||||
|
"xloctime": "cpp",
|
||||||
|
"xmemory": "cpp",
|
||||||
|
"xstring": "cpp",
|
||||||
|
"xtr1common": "cpp",
|
||||||
|
"xutility": "cpp",
|
||||||
|
"coroutine": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"future": "cpp",
|
||||||
|
"stdfloat": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"stack": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"filesystem": "cpp",
|
||||||
|
"flat_map": "cpp",
|
||||||
|
"flat_set": "cpp",
|
||||||
|
"stacktrace": "cpp",
|
||||||
|
"singleapplication": "cpp",
|
||||||
|
"strstream": "cpp",
|
||||||
|
"barrier": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"csetjmp": "cpp",
|
||||||
|
"cuchar": "cpp",
|
||||||
|
"expected": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"generator": "cpp",
|
||||||
|
"latch": "cpp",
|
||||||
|
"print": "cpp",
|
||||||
|
"scoped_allocator": "cpp",
|
||||||
|
"spanstream": "cpp",
|
||||||
|
"syncstream": "cpp",
|
||||||
|
"typeindex": "cpp"
|
||||||
|
},
|
||||||
|
"editor.tokenColorCustomizations": {
|
||||||
|
"textMateRules": [
|
||||||
|
{
|
||||||
|
"scope": "googletest.failed",
|
||||||
|
"settings": {
|
||||||
|
"foreground": "#f00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"scope": "googletest.passed",
|
||||||
|
"settings": {
|
||||||
|
"foreground": "#0f0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"scope": "googletest.run",
|
||||||
|
"settings": {
|
||||||
|
"foreground": "#0f0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
92
CMakeLists.txt
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(SimpleAccount VERSION 0.1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
add_compile_options(/utf-8)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/)
|
||||||
|
|
||||||
|
add_definitions(-DFMT_HEADER_ONLY)
|
||||||
|
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Sql)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Sql)
|
||||||
|
|
||||||
|
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
|
||||||
|
add_subdirectory(ofen/SingleApplication)
|
||||||
|
include_directories(ofen)
|
||||||
|
|
||||||
|
set(PROJECT_SOURCES
|
||||||
|
main.cpp
|
||||||
|
mainwidget.cpp
|
||||||
|
mainwidget.h
|
||||||
|
mainwidget.ui
|
||||||
|
SqlOpr.h SqlOpr.cpp
|
||||||
|
filterform.h filterform.cpp filterform.ui
|
||||||
|
recordedit.cpp recordedit.h recordedit.ui
|
||||||
|
repayment.ui repayment.cpp repayment.h
|
||||||
|
resource/SimpleAccount.rc res.qrc
|
||||||
|
resource/qss.qrc
|
||||||
|
statistic.h statistic.cpp
|
||||||
|
util.h util.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
|
qt_add_executable(SimpleAccount
|
||||||
|
MANUAL_FINALIZATION
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
util.h util.cpp
|
||||||
|
)
|
||||||
|
# Define target properties for Android with Qt 6 as:
|
||||||
|
# set_property(TARGET SimpleAccount APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||||
|
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||||
|
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
|
||||||
|
else()
|
||||||
|
if(ANDROID)
|
||||||
|
add_library(SimpleAccount SHARED
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
# Define properties for Android with Qt 5 after find_package() calls as:
|
||||||
|
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||||
|
else()
|
||||||
|
add_executable(SimpleAccount
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(SimpleAccount PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Sql Qt${QT_VERSION_MAJOR}::Network)
|
||||||
|
target_link_libraries(SimpleAccount PRIVATE SingleApplication::SingleApplication)
|
||||||
|
|
||||||
|
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||||
|
# If you are developing for iOS or macOS you should consider setting an
|
||||||
|
# explicit, fixed bundle identifier manually though.
|
||||||
|
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||||
|
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.SimpleAccount)
|
||||||
|
endif()
|
||||||
|
set_target_properties(SimpleAccount PROPERTIES
|
||||||
|
${BUNDLE_ID_OPTION}
|
||||||
|
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||||
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||||
|
MACOSX_BUNDLE TRUE
|
||||||
|
WIN32_EXECUTABLE TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(TARGETS SimpleAccount
|
||||||
|
BUNDLE DESTINATION .
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(QT_VERSION_MAJOR EQUAL 6)
|
||||||
|
qt_finalize_executable(SimpleAccount)
|
||||||
|
endif()
|
||||||
495
SqlOpr.cpp
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
#include "SqlOpr.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
#include <QSqlError>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
ACTSqlOpr::~ACTSqlOpr()
|
||||||
|
{
|
||||||
|
if (db_.isOpen()) {
|
||||||
|
db_.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ACTSqlOpr::OpenDb(const std::string& path)
|
||||||
|
{
|
||||||
|
dbPath_ = path;
|
||||||
|
db_ = QSqlDatabase::addDatabase("QSQLITE", "account_connection");
|
||||||
|
db_.setDatabaseName(QString::fromStdString(path));
|
||||||
|
|
||||||
|
if (!db_.open()) {
|
||||||
|
lastErr_ = fmt::format("无法打开数据库:{}", db_.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!generateDefaultTB()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ACTSqlOpr::UpdateAccount(AccountRecord& record)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("UPDATE account_records SET money = ?, pay_type = ?, dt = ?, "
|
||||||
|
"thing = ?, classify = ?, remark = ?, addition_file = ? WHERE id = ?");
|
||||||
|
|
||||||
|
query.addBindValue(record.money);
|
||||||
|
query.addBindValue(QString::fromStdString(record.payType));
|
||||||
|
query.addBindValue(QString::fromStdString(record.dt));
|
||||||
|
query.addBindValue(QString::fromStdString(record.thing));
|
||||||
|
query.addBindValue(QString::fromStdString(record.classify));
|
||||||
|
query.addBindValue(QString::fromStdString(record.remark));
|
||||||
|
query.addBindValue(QString::fromStdString(record.additionFile));
|
||||||
|
query.addBindValue(record.id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("执行更新失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlDatabase& ACTSqlOpr::GetDb()
|
||||||
|
{
|
||||||
|
return db_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& ACTSqlOpr::GetLastErr()
|
||||||
|
{
|
||||||
|
return lastErr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ACTSqlOpr::AppendAccount(AccountRecord& record)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("INSERT INTO account_records "
|
||||||
|
"(money, pay_type, dt, thing, classify, remark, addition_file) "
|
||||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
|
||||||
|
query.addBindValue(record.money);
|
||||||
|
query.addBindValue(QString::fromStdString(record.payType));
|
||||||
|
query.addBindValue(QString::fromStdString(record.dt));
|
||||||
|
query.addBindValue(QString::fromStdString(record.thing));
|
||||||
|
query.addBindValue(QString::fromStdString(record.classify));
|
||||||
|
query.addBindValue(QString::fromStdString(record.remark));
|
||||||
|
query.addBindValue(QString::fromStdString(record.additionFile));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("执行插入失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
record.id = query.lastInsertId().toInt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ACTSqlOpr::DeleteAccount(int32_t id)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("DELETE FROM account_records WHERE id = ?");
|
||||||
|
query.addBindValue(id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("执行删除失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ACTSqlOpr::GetAccountList(AccountRecordList& ret)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("SELECT id, money, pay_type, dt, thing, classify, remark, addition_file "
|
||||||
|
"FROM account_records ORDER BY dt DESC");
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.clear();
|
||||||
|
while (query.next()) {
|
||||||
|
AccountRecord record;
|
||||||
|
record.id = query.value(0).toInt();
|
||||||
|
record.money = query.value(1).toInt();
|
||||||
|
record.payType = query.value(2).toString().toStdString();
|
||||||
|
record.dt = query.value(3).toString().toStdString();
|
||||||
|
record.thing = query.value(4).toString().toStdString();
|
||||||
|
record.classify = query.value(5).toString().toStdString();
|
||||||
|
record.remark = query.value(6).toString().toStdString();
|
||||||
|
record.additionFile = query.value(7).toString().toStdString();
|
||||||
|
|
||||||
|
ret.push_back(record);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ACTSqlOpr::generateDefaultTB()
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
QString sql = "CREATE TABLE IF NOT EXISTS account_records ("
|
||||||
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
|
"money INTEGER NOT NULL, "
|
||||||
|
"pay_type TEXT NOT NULL, "
|
||||||
|
"dt TEXT NOT NULL, "
|
||||||
|
"thing TEXT, "
|
||||||
|
"classify TEXT, "
|
||||||
|
"remark TEXT, "
|
||||||
|
"addition_file TEXT)";
|
||||||
|
|
||||||
|
if (!query.exec(sql)) {
|
||||||
|
lastErr_ = fmt::format("创建表失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTSqlOpr::ACTSqlOpr()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ComSqlOpr::ComSqlOpr(QSqlDatabase& db) : db_(db)
|
||||||
|
{
|
||||||
|
generateDefaultTB();
|
||||||
|
CheckContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::GetClassifyList(ClassifyRecordList& ret)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("SELECT id, key, value, type, mark FROM common_records WHERE key = '分类'");
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.clear();
|
||||||
|
while (query.next()) {
|
||||||
|
CommonRecord record;
|
||||||
|
record.id = query.value(0).toInt();
|
||||||
|
record.key = query.value(1).toString().toStdString();
|
||||||
|
record.value = query.value(2).toString().toStdString();
|
||||||
|
record.type = query.value(3).toString().toStdString();
|
||||||
|
record.mark = query.value(4).toString().toStdString();
|
||||||
|
ret.push_back(record);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::GetItem(CommonRecord& ret, const std::string& key)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("SELECT id, key, value, type, mark FROM common_records "
|
||||||
|
"WHERE key = ? ORDER BY id DESC LIMIT 1");
|
||||||
|
query.addBindValue(QString::fromStdString(key));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.next()) {
|
||||||
|
ret.id = query.value(0).toInt();
|
||||||
|
ret.key = query.value(1).toString().toStdString();
|
||||||
|
ret.value = query.value(2).toString().toStdString();
|
||||||
|
ret.type = query.value(3).toString().toStdString();
|
||||||
|
ret.mark = query.value(4).toString().toStdString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastErr_ = fmt::format("未找到key为'{}'的记录", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::UpdateItem(CommonRecord& ret)
|
||||||
|
{
|
||||||
|
if (ret.id <= 0) {
|
||||||
|
lastErr_ = "无效的记录ID";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("UPDATE common_records SET "
|
||||||
|
"key = ?, value = ?, type = ?, mark = ? "
|
||||||
|
"WHERE id = ?");
|
||||||
|
|
||||||
|
query.addBindValue(QString::fromStdString(ret.key));
|
||||||
|
query.addBindValue(QString::fromStdString(ret.value));
|
||||||
|
query.addBindValue(QString::fromStdString(ret.type));
|
||||||
|
query.addBindValue(QString::fromStdString(ret.mark));
|
||||||
|
query.addBindValue(ret.id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("更新失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::InserItem(CommonRecord& ret)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("INSERT INTO common_records (key, value, type, mark) "
|
||||||
|
"VALUES (?, ?, ?, ?)");
|
||||||
|
|
||||||
|
query.addBindValue(QString::fromStdString(ret.key));
|
||||||
|
query.addBindValue(QString::fromStdString(ret.value));
|
||||||
|
query.addBindValue(QString::fromStdString(ret.type));
|
||||||
|
query.addBindValue(QString::fromStdString(ret.mark));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("插入失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.id = query.lastInsertId().toInt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::DeleteItem(const std::string& value)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("DELETE FROM common_records WHERE value = ? and key = '分类'");
|
||||||
|
query.addBindValue(QString::fromStdString(value));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("删除失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.numRowsAffected() == 0) {
|
||||||
|
lastErr_ = fmt::format("未找到value为'{}'的记录", value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::CheckContent()
|
||||||
|
{
|
||||||
|
if (!db_.transaction()) {
|
||||||
|
lastErr_ = fmt::format("开始事务失败: {}", db_.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::tuple<std::string, std::string>> defaultCategories = {{"分类", "默认"}};
|
||||||
|
|
||||||
|
for (const auto& [key, val] : defaultCategories) {
|
||||||
|
if (!CheckAndInsert(key, val, "", "")) {
|
||||||
|
db_.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!db_.commit()) {
|
||||||
|
lastErr_ = fmt::format("提交事务失败: {}", db_.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::CheckClassifyExist(const std::string& value)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("SELECT 1 FROM common_records WHERE value = ? and key = '分类'");
|
||||||
|
query.addBindValue(QString::fromStdString(value));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return query.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& ComSqlOpr::GetLastErr()
|
||||||
|
{
|
||||||
|
return lastErr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::CheckAndInsert(const std::string& key, const std::string& value, const std::string& type, const std::string& mark)
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("SELECT 1 FROM common_records WHERE key = ? LIMIT 1");
|
||||||
|
query.addBindValue(QString::fromStdString(key));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("查询失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.next()) {
|
||||||
|
return true; // 记录已存在
|
||||||
|
}
|
||||||
|
|
||||||
|
query.prepare("INSERT INTO common_records (key, value, type, mark) VALUES (?, ?, ?, ?)");
|
||||||
|
query.addBindValue(QString::fromStdString(key));
|
||||||
|
query.addBindValue(QString::fromStdString(value));
|
||||||
|
query.addBindValue(QString::fromStdString(type));
|
||||||
|
query.addBindValue(QString::fromStdString(mark));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = fmt::format("插入失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComSqlOpr::generateDefaultTB()
|
||||||
|
{
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
QString sql = "CREATE TABLE IF NOT EXISTS common_records ("
|
||||||
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
|
"key TEXT NOT NULL, "
|
||||||
|
"value TEXT, "
|
||||||
|
"type TEXT, "
|
||||||
|
"mark TEXT)";
|
||||||
|
|
||||||
|
if (!query.exec(sql)) {
|
||||||
|
lastErr_ = fmt::format("创建表失败: {}", query.lastError().text().toStdString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RepaySqlOpr::RepaySqlOpr(QSqlDatabase& db) : db_(db)
|
||||||
|
{
|
||||||
|
generateDefaultTB();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RepaySqlOpr::GetRepayResult(RepayRecordList& ret, int32_t accID)
|
||||||
|
{
|
||||||
|
ret.clear();
|
||||||
|
lastErr_.clear();
|
||||||
|
|
||||||
|
if (!db_.isOpen()) {
|
||||||
|
lastErr_ = "Database is not open";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("SELECT id, accID, money, dt, remark FROM repay_record WHERE accID = :accID");
|
||||||
|
query.bindValue(":accID", accID);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = query.lastError().text().toStdString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (query.next()) {
|
||||||
|
RepayRecord record;
|
||||||
|
record.id = query.value("id").toInt();
|
||||||
|
record.accID = query.value("accID").toInt();
|
||||||
|
record.money = query.value("money").toInt();
|
||||||
|
record.dt = query.value("dt").toString().toStdString();
|
||||||
|
record.remark = query.value("remark").toString().toStdString();
|
||||||
|
ret.push_back(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RepaySqlOpr::InsertRepayRecord(RepayRecord& ret)
|
||||||
|
{
|
||||||
|
lastErr_.clear();
|
||||||
|
|
||||||
|
if (!db_.isOpen()) {
|
||||||
|
lastErr_ = "Database is not open";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("INSERT INTO repay_record (accID, money, dt, remark) "
|
||||||
|
"VALUES (:accID, :money, :dt, :remark)");
|
||||||
|
query.bindValue(":accID", ret.accID);
|
||||||
|
query.bindValue(":money", ret.money);
|
||||||
|
query.bindValue(":dt", QString::fromStdString(ret.dt));
|
||||||
|
query.bindValue(":remark", QString::fromStdString(ret.remark));
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = query.lastError().text().toStdString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the auto-generated id
|
||||||
|
ret.id = query.lastInsertId().toInt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RepaySqlOpr::updateRepayRecord(RepayRecord& ret)
|
||||||
|
{
|
||||||
|
lastErr_.clear();
|
||||||
|
|
||||||
|
if (!db_.isOpen()) {
|
||||||
|
lastErr_ = "Database is not open";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("UPDATE repay_record SET accID = :accID, money = :money, "
|
||||||
|
"dt = :dt, remark = :remark WHERE id = :id");
|
||||||
|
query.bindValue(":accID", ret.accID);
|
||||||
|
query.bindValue(":money", ret.money);
|
||||||
|
query.bindValue(":dt", QString::fromStdString(ret.dt));
|
||||||
|
query.bindValue(":remark", QString::fromStdString(ret.remark));
|
||||||
|
query.bindValue(":id", ret.id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = query.lastError().text().toStdString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.numRowsAffected() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RepaySqlOpr::deleteRepayRecord(int32_t id)
|
||||||
|
{
|
||||||
|
lastErr_.clear();
|
||||||
|
|
||||||
|
if (!db_.isOpen()) {
|
||||||
|
lastErr_ = "Database is not open";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
query.prepare("DELETE FROM repay_record WHERE id = :id");
|
||||||
|
query.bindValue(":id", id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
lastErr_ = query.lastError().text().toStdString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.numRowsAffected() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& RepaySqlOpr::GetLastErr()
|
||||||
|
{
|
||||||
|
return lastErr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RepaySqlOpr::generateDefaultTB()
|
||||||
|
{
|
||||||
|
lastErr_.clear();
|
||||||
|
|
||||||
|
if (!db_.isOpen()) {
|
||||||
|
lastErr_ = "Database is not open";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(db_);
|
||||||
|
QString createTable = "CREATE TABLE IF NOT EXISTS repay_record ("
|
||||||
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
|
"accID INTEGER NOT NULL, "
|
||||||
|
"money INTEGER NOT NULL, "
|
||||||
|
"dt TEXT NOT NULL, "
|
||||||
|
"remark TEXT)";
|
||||||
|
|
||||||
|
if (!query.exec(createTable)) {
|
||||||
|
lastErr_ = query.lastError().text().toStdString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
111
SqlOpr.h
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#ifndef SQL_OPR_H
|
||||||
|
#define SQL_OPR_H
|
||||||
|
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct AccountRecord {
|
||||||
|
int32_t id{};
|
||||||
|
int32_t money{};
|
||||||
|
std::string payType{};
|
||||||
|
std::string dt;
|
||||||
|
std::string thing;
|
||||||
|
std::string classify;
|
||||||
|
std::string remark;
|
||||||
|
std::string additionFile{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonRecord {
|
||||||
|
int32_t id{};
|
||||||
|
std::string key;
|
||||||
|
std::string value;
|
||||||
|
std::string type;
|
||||||
|
std::string mark;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RepayRecord {
|
||||||
|
int32_t id{};
|
||||||
|
int32_t accID{};
|
||||||
|
int32_t money{};
|
||||||
|
std::string dt;
|
||||||
|
std::string remark;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ClassifyRecordList = std::vector<CommonRecord>;
|
||||||
|
using AccountRecordList = std::vector<AccountRecord>;
|
||||||
|
using RepayRecordList = std::vector<RepayRecord>;
|
||||||
|
|
||||||
|
class ACTSqlOpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ACTSqlOpr();
|
||||||
|
~ACTSqlOpr();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool OpenDb(const std::string& path);
|
||||||
|
bool GetAccountList(AccountRecordList& ret);
|
||||||
|
bool AppendAccount(AccountRecord& ret);
|
||||||
|
bool DeleteAccount(int32_t id);
|
||||||
|
bool UpdateAccount(AccountRecord& ret);
|
||||||
|
QSqlDatabase& GetDb();
|
||||||
|
const std::string& GetLastErr();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool generateDefaultTB();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSqlDatabase db_;
|
||||||
|
std::string dbPath_{};
|
||||||
|
std::string lastErr_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class ComSqlOpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ComSqlOpr(QSqlDatabase& db);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool GetClassifyList(ClassifyRecordList& ret);
|
||||||
|
bool GetItem(CommonRecord& ret, const std::string& key);
|
||||||
|
bool UpdateItem(CommonRecord& ret);
|
||||||
|
bool InserItem(CommonRecord& ret);
|
||||||
|
bool DeleteItem(const std::string& value);
|
||||||
|
bool CheckContent();
|
||||||
|
bool CheckClassifyExist(const std::string& value);
|
||||||
|
const std::string& GetLastErr();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CheckAndInsert(const std::string& key, const std::string& value, const std::string& type, const std::string& mark);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool generateDefaultTB();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSqlDatabase& db_;
|
||||||
|
std::string lastErr_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepaySqlOpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RepaySqlOpr(QSqlDatabase& db);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool GetRepayResult(RepayRecordList& ret, int32_t accID);
|
||||||
|
bool InsertRepayRecord(RepayRecord& ret);
|
||||||
|
bool updateRepayRecord(RepayRecord& ret);
|
||||||
|
bool deleteRepayRecord(int32_t id);
|
||||||
|
const std::string& GetLastErr();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool generateDefaultTB();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSqlDatabase& db_;
|
||||||
|
std::string lastErr_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQL_OPR_H
|
||||||
439
filterform.cpp
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
#include "filterform.h"
|
||||||
|
|
||||||
|
#include "recordedit.h"
|
||||||
|
#include "ui_filterform.h"
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QRegularExpressionValidator>
|
||||||
|
#include <QShowEvent>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
FilterForm::FilterForm(QWidget* parent, std::unique_ptr<ACTSqlOpr>& sqlOpr, std::unique_ptr<ComSqlOpr>& comSqlOpr,
|
||||||
|
std::unique_ptr<RepaySqlOpr>& repaySqlOpr)
|
||||||
|
: QDialog(parent), ui(new Ui::FilterForm), sqlOpr_(sqlOpr), comSqlOpr_(comSqlOpr), repaySqlOpr_(repaySqlOpr)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
statistic_ = std::make_shared<Statistic>(repaySqlOpr_);
|
||||||
|
Init();
|
||||||
|
setWindowTitle("结果");
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterForm::~FilterForm()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilterForm::exec()
|
||||||
|
{
|
||||||
|
ShowResult();
|
||||||
|
if (!over_) {
|
||||||
|
return QDialog::Rejected;
|
||||||
|
}
|
||||||
|
return QDialog::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterForm::Init()
|
||||||
|
{
|
||||||
|
auto* lay = new QVBoxLayout(this);
|
||||||
|
tw_ = new QTableWidget(this);
|
||||||
|
|
||||||
|
QStringList headers;
|
||||||
|
headers << "ID" << "类型" << "分类" << "金额" << "日期" << "内容" << "备注";
|
||||||
|
|
||||||
|
tw_->setColumnCount(headers.size());
|
||||||
|
tw_->setHorizontalHeaderLabels(headers);
|
||||||
|
tw_->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
|
||||||
|
tw_->setColumnWidth(0, 50);
|
||||||
|
tw_->setColumnWidth(1, 100);
|
||||||
|
tw_->setColumnWidth(2, 100);
|
||||||
|
tw_->setColumnWidth(3, 100);
|
||||||
|
tw_->setColumnWidth(4, 150);
|
||||||
|
tw_->setColumnWidth(5, 300);
|
||||||
|
tw_->setColumnWidth(6, 100);
|
||||||
|
|
||||||
|
lay->addWidget(tw_);
|
||||||
|
ui->widget->setLayout(lay);
|
||||||
|
|
||||||
|
ui->edCashIn->setReadOnly(true);
|
||||||
|
ui->edCashOut->setReadOnly(true);
|
||||||
|
ui->edCreditIn->setReadOnly(true);
|
||||||
|
ui->edCreditOut->setReadOnly(true);
|
||||||
|
ui->edCreditCash->setReadOnly(true);
|
||||||
|
|
||||||
|
tw_->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(tw_, &QTableWidget::customContextMenuRequested, this, &FilterForm::ShowContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterForm::ShowResult()
|
||||||
|
{
|
||||||
|
over_ = false;
|
||||||
|
AccountRecordList list;
|
||||||
|
if (!sqlOpr_->GetAccountList(list)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_.clear();
|
||||||
|
if (!Filter(list, result_)) {
|
||||||
|
QMessageBox::warning(this, "错误", "筛选失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result_.empty()) {
|
||||||
|
QMessageBox::warning(this, "提示", "没有符合条件的记录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& item : result_) {
|
||||||
|
tw_->insertRow(tw_->rowCount());
|
||||||
|
int row = tw_->rowCount() - 1;
|
||||||
|
|
||||||
|
auto* i1 = new QTableWidgetItem(QString::number(item.id));
|
||||||
|
i1->setFlags(i1->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
auto* i2 = new QTableWidgetItem(QString::fromStdString(item.payType));
|
||||||
|
i2->setFlags(i2->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
auto* i3 = new QTableWidgetItem(QString::fromStdString(item.classify));
|
||||||
|
i3->setFlags(i3->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
auto* i4 = new QTableWidgetItem(QString::number(item.money / 100.0));
|
||||||
|
i4->setFlags(i4->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
auto* i5 = new QTableWidgetItem(QString::fromStdString(item.dt));
|
||||||
|
i5->setFlags(i5->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
auto* i6 = new QTableWidgetItem(QString::fromStdString(item.thing));
|
||||||
|
i6->setFlags(i6->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
auto* i7 = new QTableWidgetItem(QString::fromStdString(item.remark));
|
||||||
|
i7->setFlags(i7->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
tw_->setItem(row, 0, i1);
|
||||||
|
tw_->setItem(row, 1, i2);
|
||||||
|
tw_->setItem(row, 2, i3);
|
||||||
|
tw_->setItem(row, 3, i4);
|
||||||
|
tw_->setItem(row, 4, i5);
|
||||||
|
tw_->setItem(row, 5, i6);
|
||||||
|
tw_->setItem(row, 6, i7);
|
||||||
|
}
|
||||||
|
CalcShow();
|
||||||
|
over_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterForm::CalcShow()
|
||||||
|
{
|
||||||
|
statistic_->Calculate(result_);
|
||||||
|
auto* d = SharedData::instance();
|
||||||
|
ui->edCashIn->setText(QString::number(d->ttCashIn_ / 100.0));
|
||||||
|
ui->edCashOut->setText(QString::number(d->ttCashOut_ / 100.0));
|
||||||
|
ui->edCreditIn->setText(QString::number(d->ttCreditIn_ / 100.0));
|
||||||
|
ui->edCreditOut->setText(QString::number(d->ttCreditOut_ / 100.0));
|
||||||
|
ui->edCreditCash->setText(QString::number(d->ttCreditCash_ / 100.0));
|
||||||
|
ui->edCreditPay->setText(QString::number(d->ttCashPay_ / 100.0));
|
||||||
|
|
||||||
|
auto ret1 = GetClassifyCash(result_, true);
|
||||||
|
auto ret2 = GetClassifyCash(result_, false);
|
||||||
|
|
||||||
|
ui->lwCashCl->clear();
|
||||||
|
for (const auto& item : ret1) {
|
||||||
|
ui->lwCashCl->addItem(QString("%1 => %2/%3")
|
||||||
|
.arg(QString::fromStdString(item.first))
|
||||||
|
.arg(QString::number(item.second.first / 100.0))
|
||||||
|
.arg(QString::number(item.second.second / 100.0)));
|
||||||
|
}
|
||||||
|
ui->lwCreditCl->clear();
|
||||||
|
for (const auto& item : ret2) {
|
||||||
|
ui->lwCreditCl->addItem(QString("%1 => %2/%3")
|
||||||
|
.arg(QString::fromStdString(item.first))
|
||||||
|
.arg(QString::number(item.second.first / 100.0))
|
||||||
|
.arg(QString::number(item.second.second / 100.0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t FilterForm::rePayValue(int accID)
|
||||||
|
{
|
||||||
|
RepayRecordList reuslt;
|
||||||
|
if (!repaySqlOpr_->GetRepayResult(reuslt, accID)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int32_t sum = 0;
|
||||||
|
for (const auto& item : reuslt) {
|
||||||
|
sum += item.money;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilterForm::Filter(const AccountRecordList& list, AccountRecordList& result)
|
||||||
|
{
|
||||||
|
auto* d = SharedData::instance();
|
||||||
|
result.clear();
|
||||||
|
for (const auto& item : list) {
|
||||||
|
if (d->flType) {
|
||||||
|
if (item.payType != d->type.toStdString()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d->flKeys) {
|
||||||
|
auto qkeys = d->key.toUpper();
|
||||||
|
auto skeys = QString::fromStdString(item.thing).toUpper();
|
||||||
|
if (!skeys.contains(qkeys)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (d->filter) {
|
||||||
|
case CashFilter::FIL_BETWEEN: {
|
||||||
|
if (item.money < d->lowMoney || item.money > d->highMoney) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CashFilter::FIL_HIGHER: {
|
||||||
|
if (item.money <= d->highMoney) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CashFilter::FIL_LOWER: {
|
||||||
|
if (item.money >= d->lowMoney) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (d->flClassify) {
|
||||||
|
auto qkeys = d->classify.toUpper();
|
||||||
|
auto skeys = QString::fromStdString(item.classify).toUpper();
|
||||||
|
if (!skeys.contains(qkeys)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d->flDays) {
|
||||||
|
auto days = d->days;
|
||||||
|
QDateTime datetime = QDateTime::fromString(QString::fromStdString(item.dt), "yyyy-MM-dd hh:mm:ss");
|
||||||
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
|
if (datetime.daysTo(now) > days) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push_back(item);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::pair<uint32_t, uint32_t>>> FilterForm::GetClassifyCash(const AccountRecordList& list,
|
||||||
|
bool isCash)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::pair<uint32_t, uint32_t>>> ret;
|
||||||
|
std::unordered_map<std::string, std::pair<uint32_t, uint32_t>> classifyMap;
|
||||||
|
for (const auto& item : list) {
|
||||||
|
if (isCash) {
|
||||||
|
if (item.payType == "现金支出") {
|
||||||
|
if (!classifyMap.count(item.classify)) {
|
||||||
|
classifyMap[item.classify] = {0, 0};
|
||||||
|
}
|
||||||
|
classifyMap[item.classify].first += item.money;
|
||||||
|
} else if (item.payType == "现金收入") {
|
||||||
|
if (!classifyMap.count(item.classify)) {
|
||||||
|
classifyMap[item.classify] = {0, 0};
|
||||||
|
}
|
||||||
|
classifyMap[item.classify].second += item.money;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (item.payType == "信用支出") {
|
||||||
|
if (!classifyMap.count(item.classify)) {
|
||||||
|
classifyMap[item.classify] = {0, 0};
|
||||||
|
}
|
||||||
|
classifyMap[item.classify].first += item.money;
|
||||||
|
} else if (item.payType == "信用收入") {
|
||||||
|
if (!classifyMap.count(item.classify)) {
|
||||||
|
classifyMap[item.classify] = {0, 0};
|
||||||
|
}
|
||||||
|
classifyMap[item.classify].second += item.money;
|
||||||
|
} else if (item.payType == "信用借款") {
|
||||||
|
// 信用借款
|
||||||
|
if (!classifyMap.count(item.classify)) {
|
||||||
|
classifyMap[item.classify] = {0, 0};
|
||||||
|
}
|
||||||
|
classifyMap[item.classify].first += item.money;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& item : classifyMap) {
|
||||||
|
ret.emplace_back(item.first, item.second);
|
||||||
|
}
|
||||||
|
std::sort(ret.begin(), ret.end(),
|
||||||
|
[](const std::pair<std::string, std::pair<uint32_t, uint32_t>>& a,
|
||||||
|
const std::pair<std::string, std::pair<uint32_t, uint32_t>>& b) {
|
||||||
|
auto at = a.second.first + a.second.second;
|
||||||
|
auto bt = b.second.first + b.second.second;
|
||||||
|
return at > bt;
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void FilterForm::ShowContextMenu(const QPoint& pos)
|
||||||
|
{
|
||||||
|
QList<QTableWidgetItem*> selectedItems = tw_->selectedItems();
|
||||||
|
if (selectedItems.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu menu(this);
|
||||||
|
|
||||||
|
if (selectedItems.size() != 7) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QAction* acFile = menu.addAction("查看附件");
|
||||||
|
int id = selectedItems[0]->text().toInt();
|
||||||
|
QString fileName;
|
||||||
|
|
||||||
|
for (const auto& item : result_) {
|
||||||
|
if (item.id == id) {
|
||||||
|
fileName = QString::fromStdString(item.additionFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TransMenu(id, menu, selectedItems[1]);
|
||||||
|
connect(acFile, &QAction::triggered, [this, selectedItems, id, fileName]() {
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "警告", "附件文件名为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString mediaDir = QString::fromStdString(Util::GetMediaDir());
|
||||||
|
QString filePath = QDir(mediaDir).filePath(fileName);
|
||||||
|
if (!QFile::exists(filePath)) {
|
||||||
|
QMessageBox::critical(this, "错误", QString("文件不存在: %1").arg(filePath));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!QDesktopServices::openUrl(QUrl::fromLocalFile(filePath))) {
|
||||||
|
QMessageBox::critical(nullptr, "错误", "无法打开图片文件");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
QAction* acEdit = menu.addAction("编辑");
|
||||||
|
connect(acEdit, &QAction::triggered, [this, id, selectedItems]() {
|
||||||
|
RecordEdit* re = new RecordEdit(this, comSqlOpr_, repaySqlOpr_);
|
||||||
|
AccountRecord* recPtr = nullptr;
|
||||||
|
for (auto& item : result_) {
|
||||||
|
if (item.id == id) {
|
||||||
|
re->record_ = item;
|
||||||
|
recPtr = &item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
re->exec();
|
||||||
|
|
||||||
|
// headers << "ID" << "类型" << "分类" << "金额" << "日期" << "内容" << "备注";
|
||||||
|
if (!re->modify_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sqlOpr_->UpdateAccount(re->record_)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedItems[1]->setText(QString::fromStdString(re->record_.payType));
|
||||||
|
selectedItems[2]->setText(QString::fromStdString(re->record_.classify));
|
||||||
|
selectedItems[3]->setText(QString::number(re->record_.money / 100.0));
|
||||||
|
selectedItems[4]->setText(QString::fromStdString(re->record_.dt));
|
||||||
|
selectedItems[5]->setText(QString::fromStdString(re->record_.thing));
|
||||||
|
selectedItems[6]->setText(QString::fromStdString(re->record_.remark));
|
||||||
|
|
||||||
|
*recPtr = re->record_;
|
||||||
|
CalcShow();
|
||||||
|
});
|
||||||
|
|
||||||
|
QAction* acDelete = menu.addAction("删除");
|
||||||
|
connect(acDelete, &QAction::triggered, [this, id, selectedItems]() {
|
||||||
|
if (QMessageBox::question(this, "确认删除", "确定删除记录吗?") != QMessageBox::Yes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sqlOpr_->DeleteAccount(id)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从结果列表中移除记录
|
||||||
|
for (auto it = result_.begin(); it != result_.end(); ++it) {
|
||||||
|
if (it->id == id) {
|
||||||
|
result_.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从表格中移除行
|
||||||
|
tw_->removeRow(selectedItems[0]->row());
|
||||||
|
CalcShow();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.exec(tw_->viewport()->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterForm::TransMenu(int id, QMenu& menu, QTableWidgetItem* item)
|
||||||
|
{
|
||||||
|
QString payType;
|
||||||
|
for (const auto& item : result_) {
|
||||||
|
if (item.id == id) {
|
||||||
|
payType = QString::fromStdString(item.payType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (payType.isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "警告", QString("未找到ID为%1的支付类型。").arg(id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据支付类型执行不同操作
|
||||||
|
QAction* acFile = nullptr;
|
||||||
|
QString pur;
|
||||||
|
if (payType == "现金支出") {
|
||||||
|
acFile = menu.addAction("转为信用支出");
|
||||||
|
pur = "信用支出";
|
||||||
|
} else if (payType == "现金收入") {
|
||||||
|
acFile = menu.addAction("转为信用收入");
|
||||||
|
pur = "信用收入";
|
||||||
|
} else if (payType == "信用支出") {
|
||||||
|
acFile = menu.addAction("转为现金支出");
|
||||||
|
pur = "现金支出";
|
||||||
|
} else if (payType == "信用收入") {
|
||||||
|
acFile = menu.addAction("转为现金收入");
|
||||||
|
pur = "现金收入";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acFile == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(acFile, &QAction::triggered, [this, id, pur, item]() {
|
||||||
|
// 执行支付类型转换逻辑
|
||||||
|
if (QMessageBox::question(this, "确认转换", QString("确定将ID为%1的记录转为%2吗?").arg(id).arg(pur),
|
||||||
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||||
|
// 1. 更新数据库中的支付类型
|
||||||
|
bool done = false;
|
||||||
|
for (auto& item : result_) {
|
||||||
|
if (item.id != id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item.payType = pur.toStdString();
|
||||||
|
if (!sqlOpr_->UpdateAccount(item)) {
|
||||||
|
QMessageBox::critical(this, "错误", "更新数据库失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
item->setText(pur);
|
||||||
|
CalcShow();
|
||||||
|
QMessageBox::information(this, "成功", QString("ID为%1的记录已成功转为%2。").arg(id).arg(pur));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
52
filterform.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef FILTERFORM_H
|
||||||
|
#define FILTERFORM_H
|
||||||
|
|
||||||
|
#include "SqlOpr.h"
|
||||||
|
#include "statistic.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QTableWidget>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FilterForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterForm : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FilterForm(QWidget* parent, std::unique_ptr<ACTSqlOpr>& sqlOpr, std::unique_ptr<ComSqlOpr>& comSqlOpr,
|
||||||
|
std::unique_ptr<RepaySqlOpr>& repaySqlOpr);
|
||||||
|
~FilterForm();
|
||||||
|
int exec() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool Filter(const AccountRecordList& list, AccountRecordList& result);
|
||||||
|
static std::vector<std::pair<std::string, std::pair<uint32_t, uint32_t>>> GetClassifyCash(const AccountRecordList& list,
|
||||||
|
bool isCash);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ShowResult();
|
||||||
|
void ShowContextMenu(const QPoint& pos);
|
||||||
|
void TransMenu(int id, QMenu& menu, QTableWidgetItem* item);
|
||||||
|
void CalcShow();
|
||||||
|
int32_t rePayValue(int accID);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool over_{};
|
||||||
|
QTableWidget* tw_{};
|
||||||
|
AccountRecordList result_;
|
||||||
|
std::shared_ptr<Statistic> statistic_;
|
||||||
|
std::unique_ptr<ACTSqlOpr>& sqlOpr_;
|
||||||
|
std::unique_ptr<ComSqlOpr>& comSqlOpr_;
|
||||||
|
std::unique_ptr<RepaySqlOpr>& repaySqlOpr_;
|
||||||
|
Ui::FilterForm* ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILTERFORM_H
|
||||||
248
filterform.ui
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>FilterForm</class>
|
||||||
|
<widget class="QDialog" name="FilterForm">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1472</width>
|
||||||
|
<height>710</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>1.清单</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPrePage">
|
||||||
|
<property name="text">
|
||||||
|
<string>上一页</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCurPage">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edTotalPage">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNextPage">
|
||||||
|
<property name="text">
|
||||||
|
<string>下一页</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>2.统计</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>总计现金支出:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCashOut"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>总计现金收入:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCashIn"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>总计信用支出:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCreditOut"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>总计信用收入:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCreditIn"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>总计信用借款:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCreditCash"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>总计信用还款:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCreditPay"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>现金分类占比(支出/收入):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="lwCashCl"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>信用分类占比(支出/收入):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="lwCreditCl"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
31
main.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "mainwidget.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFile>
|
||||||
|
#include <SingleApplication>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
SingleApplication a(argc, argv);
|
||||||
|
// a.setStyle("fusion");
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MainWidget w;
|
||||||
|
|
||||||
|
QObject::connect(&a, &SingleApplication::instanceStarted, &w, [&w]() {
|
||||||
|
w.showNormal();
|
||||||
|
w.raise();
|
||||||
|
w.activateWindow();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
QFile file(":/qss/flatgray.css");
|
||||||
|
if (file.open(QFile::ReadOnly)) {
|
||||||
|
a.setStyleSheet(file.readAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
w.show();
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
344
mainwidget.cpp
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
#include "mainwidget.h"
|
||||||
|
#include "./ui_mainwidget.h"
|
||||||
|
#include "filterform.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
MainWidget::MainWidget(QWidget* parent) : QDialog(parent), ui(new Ui::MainWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
BaseInit();
|
||||||
|
Init();
|
||||||
|
RefreshData();
|
||||||
|
setWindowTitle("账单记录器V1.0.5");
|
||||||
|
Calculate();
|
||||||
|
|
||||||
|
auto size = Util::GetMainSize();
|
||||||
|
resize(size.first, size.second);
|
||||||
|
|
||||||
|
setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint);
|
||||||
|
setWindowIcon(QIcon("://resource/ico.ico"));
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWidget::~MainWidget()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWidget::Init()
|
||||||
|
{
|
||||||
|
Util::Init();
|
||||||
|
auto dbPath = Util::GetWorkDir() + "/account.db";
|
||||||
|
sqlOpr_ = std::make_unique<ACTSqlOpr>();
|
||||||
|
if (!sqlOpr_->OpenDb(dbPath)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
comSqlOpr_ = std::make_unique<ComSqlOpr>(sqlOpr_->GetDb());
|
||||||
|
repaySqlOpr_ = std::make_unique<RepaySqlOpr>(sqlOpr_->GetDb());
|
||||||
|
statistic_ = std::make_shared<Statistic>(repaySqlOpr_);
|
||||||
|
|
||||||
|
auto mediaDir = Util::GetMediaDir();
|
||||||
|
if (!QDir(QString::fromStdString(mediaDir)).exists()) {
|
||||||
|
QDir().mkdir(QString::fromStdString(mediaDir));
|
||||||
|
}
|
||||||
|
ui->timeEdit->setDisplayFormat("HH:mm:ss");
|
||||||
|
ui->rbNoLimit->setChecked(true);
|
||||||
|
ui->btnRecord->setStyleSheet("background-color: #b1a5ccff;");
|
||||||
|
ui->dateEdit->setDate(QDate::currentDate());
|
||||||
|
ui->timeEdit->setTime(QTime::currentTime());
|
||||||
|
ui->cbClassify->setEditable(true);
|
||||||
|
|
||||||
|
ui->edCash->setValidator(new QDoubleValidator(0.0, 10000000.0, 2, this));
|
||||||
|
ui->edHighCash->setValidator(new QDoubleValidator(0.0, 10000000.0, 2, this));
|
||||||
|
ui->edLowCash->setValidator(new QDoubleValidator(0.0, 10000000.0, 2, this));
|
||||||
|
ui->edDays->setValidator(new QIntValidator(0, 10000000, this));
|
||||||
|
|
||||||
|
ui->lbTotal->setStyleSheet("QLabel {"
|
||||||
|
"font-size: 20px;"
|
||||||
|
"color: blue;"
|
||||||
|
"}");
|
||||||
|
|
||||||
|
ui->lbCurCash->setStyleSheet("QLabel {"
|
||||||
|
"color: blue;"
|
||||||
|
"}");
|
||||||
|
ui->lbCredit->setStyleSheet("QLabel {"
|
||||||
|
"color: blue;"
|
||||||
|
"}");
|
||||||
|
|
||||||
|
connect(ui->btnClassifyAdd, &QPushButton::clicked, this, &MainWidget::AddClassify);
|
||||||
|
connect(ui->btnClassifyDel, &QPushButton::clicked, this, &MainWidget::DelClassify);
|
||||||
|
connect(ui->btnRecord, &QPushButton::clicked, this, &MainWidget::Record);
|
||||||
|
connect(ui->btnSet, &QPushButton::clicked, this, [this]() {
|
||||||
|
QProcess process;
|
||||||
|
auto editor = Util::GetEditor();
|
||||||
|
QStringList args;
|
||||||
|
args << QString::fromStdString(Util::GetConfigPath());
|
||||||
|
process.startDetached(QString::fromStdString(editor), args);
|
||||||
|
process.waitForStarted();
|
||||||
|
});
|
||||||
|
connect(ui->btnSearch, &QPushButton::clicked, this, &MainWidget::Search);
|
||||||
|
connect(ui->btnSetNow, &QPushButton::clicked, this, [this]() {
|
||||||
|
ui->dateEdit->setDate(QDate::currentDate());
|
||||||
|
ui->timeEdit->setTime(QTime::currentTime());
|
||||||
|
});
|
||||||
|
connect(ui->btnAddFile, &QPushButton::clicked, this, &MainWidget::SelectImg);
|
||||||
|
connect(ui->btnClearFile, &QPushButton::clicked, this, [this]() { ui->edFile->clear(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWidget::RefreshData()
|
||||||
|
{
|
||||||
|
if (!RefreshClassify()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWidget::Calculate()
|
||||||
|
{
|
||||||
|
AccountRecordList list;
|
||||||
|
if (!sqlOpr_->GetAccountList(list)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算账户余额等信息
|
||||||
|
statistic_->Calculate(list);
|
||||||
|
|
||||||
|
auto* d = SharedData::instance();
|
||||||
|
auto curCash = static_cast<int32_t>(Util::GetCurCash() * 100);
|
||||||
|
auto curSave = static_cast<int32_t>(Util::GetCurSave() * 100);
|
||||||
|
|
||||||
|
auto curRemain = d->ttCashIn_ - d->ttCashOut_ + curCash - d->ttCashPay_ + d->ttCreditCash_;
|
||||||
|
ui->lbCurCash->setText(QString::number(curRemain / 100.0));
|
||||||
|
|
||||||
|
auto creditOutTotal = d->ttCreditOut_ - d->ttCashPay_ + d->ttCreditCash_;
|
||||||
|
QString credit = QString("%1/%2").arg(creditOutTotal / 100.0, 0, 'f', 2).arg(d->ttCreditIn_ / 100.0, 0, 'f', 2);
|
||||||
|
ui->lbCredit->setText(credit);
|
||||||
|
|
||||||
|
auto youHave = curRemain + d->ttCreditIn_ - (d->ttCreditOut_ + d->ttCreditCash_ - d->ttCashPay_);
|
||||||
|
ui->lbTotal->setText("¥" + QString::number(youHave / 100.0));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWidget::closeEvent(QCloseEvent* event)
|
||||||
|
{
|
||||||
|
auto size = this->size();
|
||||||
|
Util::SetMainSize(size.width(), size.height());
|
||||||
|
QWidget::closeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWidget::BaseInit()
|
||||||
|
{
|
||||||
|
ui->cbCashType->addItem("现金支出");
|
||||||
|
ui->cbCashType->addItem("现金收入");
|
||||||
|
ui->cbCashType->addItem("信用支出");
|
||||||
|
ui->cbCashType->addItem("信用收入");
|
||||||
|
ui->cbCashType->addItem("信用借款");
|
||||||
|
ui->cbCashType->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWidget::RefreshClassify()
|
||||||
|
{
|
||||||
|
ClassifyRecordList classifyList;
|
||||||
|
if (!comSqlOpr_->GetClassifyList(classifyList)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(comSqlOpr_->GetLastErr()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ui->cbClassify->clear();
|
||||||
|
for (const auto& classify : classifyList) {
|
||||||
|
ui->cbClassify->addItem(QString::fromStdString(classify.value));
|
||||||
|
}
|
||||||
|
if (!classifyList.empty()) {
|
||||||
|
ui->cbClassify->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWidget::SelectImg()
|
||||||
|
{
|
||||||
|
QString imagePath =
|
||||||
|
QFileDialog::getOpenFileName(this, "选择图片", QDir::homePath(), "图片文件 (*.jpg *.jpeg *.png *.bmp *.gif)");
|
||||||
|
if (imagePath.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ui->edFile->setText(imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWidget::AddClassify()
|
||||||
|
{
|
||||||
|
// 弹出输入对话框
|
||||||
|
bool ok;
|
||||||
|
QString text = QInputDialog::getText(this, tr("添加分类"), tr("请输入分类名称:"), QLineEdit::Normal, "", &ok);
|
||||||
|
text = text.trimmed();
|
||||||
|
|
||||||
|
if (!ok || text.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先检查是否已存在
|
||||||
|
if (comSqlOpr_->CheckClassifyExist(text.toStdString())) {
|
||||||
|
QMessageBox::warning(this, tr("错误"), tr("分类已存在"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonRecord record;
|
||||||
|
record.key = "分类";
|
||||||
|
record.value = text.toStdString();
|
||||||
|
record.type = "";
|
||||||
|
|
||||||
|
if (!comSqlOpr_->InserItem(record)) {
|
||||||
|
QMessageBox::warning(this, tr("错误"), tr("添加分类失败"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RefreshClassify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWidget::DelClassify()
|
||||||
|
{
|
||||||
|
auto curClassify = ui->cbClassify->currentText();
|
||||||
|
if (curClassify == "默认") {
|
||||||
|
QMessageBox::warning(this, "错误", "默认分类无法删除");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (QMessageBox::question(this, "删除分类", QString("确定删除分类<%1>吗?").arg(curClassify)) != QMessageBox::Yes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!comSqlOpr_->DeleteItem(curClassify.toStdString())) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(comSqlOpr_->GetLastErr()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RefreshClassify();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWidget::Record()
|
||||||
|
{
|
||||||
|
// 确认添加
|
||||||
|
if (QMessageBox::question(this, "确认添加", "确定添加记录吗?") != QMessageBox::Yes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 款项分类
|
||||||
|
auto curType = ui->cbCashType->currentText();
|
||||||
|
|
||||||
|
// 基础分类
|
||||||
|
auto curClassify = ui->cbClassify->currentText();
|
||||||
|
|
||||||
|
// 记录事项
|
||||||
|
auto thing = ui->lineEdit->text().trimmed();
|
||||||
|
if (thing.isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "错误", "记录事项不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间日期
|
||||||
|
auto date = ui->dateEdit->date();
|
||||||
|
auto time = ui->timeEdit->time();
|
||||||
|
QDateTime dateTime(date, time);
|
||||||
|
auto dateTimeStr = dateTime.toString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// 金额
|
||||||
|
// 查看附件
|
||||||
|
auto attach = ui->edFile->text().trimmed();
|
||||||
|
if (!attach.isEmpty()) {
|
||||||
|
QFile file(attach);
|
||||||
|
if (!file.exists()) {
|
||||||
|
QMessageBox::warning(this, "错误", "附件文件不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AccountRecord record;
|
||||||
|
record.money = Util::CashInt(ui->edCash->text().toDouble());
|
||||||
|
record.thing = thing.toStdString();
|
||||||
|
record.dt = dateTimeStr.toStdString();
|
||||||
|
record.classify = curClassify.toStdString();
|
||||||
|
record.payType = curType.toStdString();
|
||||||
|
if (!attach.isEmpty()) {
|
||||||
|
record.additionFile = Util::NewUUIDName(attach).toStdString();
|
||||||
|
}
|
||||||
|
if (!sqlOpr_->AppendAccount(record)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!attach.isEmpty()) {
|
||||||
|
QFile::copy(attach, QString::fromStdString(Util::GetMediaDir() + "/" + record.additionFile));
|
||||||
|
};
|
||||||
|
Calculate();
|
||||||
|
QMessageBox::information(this, "提示", "添加成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWidget::Search()
|
||||||
|
{
|
||||||
|
auto* d = SharedData::instance();
|
||||||
|
if (ui->ckType->isChecked()) {
|
||||||
|
d->flType = true;
|
||||||
|
d->type = ui->cbCashType->currentText();
|
||||||
|
} else {
|
||||||
|
d->flType = false;
|
||||||
|
}
|
||||||
|
if (ui->ckKey->isChecked()) {
|
||||||
|
d->flKeys = true;
|
||||||
|
d->key = ui->edKey->text().trimmed();
|
||||||
|
if (d->key.isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "错误", "搜索关键字不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d->flKeys = false;
|
||||||
|
}
|
||||||
|
if (ui->ckDays->isChecked()) {
|
||||||
|
d->flDays = true;
|
||||||
|
if (ui->edDays->text().isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "错误", "天数不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->days = ui->edDays->text().toInt();
|
||||||
|
} else {
|
||||||
|
d->flDays = false;
|
||||||
|
}
|
||||||
|
if (ui->rbBetween->isChecked()) {
|
||||||
|
d->filter = CashFilter::FIL_BETWEEN;
|
||||||
|
if (ui->edLowCash->text().isEmpty() || ui->edHighCash->text().isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "错误", "金额范围不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->lowMoney = static_cast<int>(ui->edLowCash->text().toDouble() * 100);
|
||||||
|
d->highMoney = static_cast<int>(ui->edHighCash->text().toDouble() * 100);
|
||||||
|
} else if (ui->rbHigh->isChecked()) {
|
||||||
|
d->filter = CashFilter::FIL_HIGHER;
|
||||||
|
if (ui->edHighCash->text().isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "错误", "金额高范围不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->highMoney = static_cast<int>(ui->edHighCash->text().toDouble() * 100);
|
||||||
|
} else if (ui->rbLow->isChecked()) {
|
||||||
|
d->filter = CashFilter::FIL_LOWER;
|
||||||
|
if (ui->edLowCash->text().isEmpty()) {
|
||||||
|
QMessageBox::warning(this, "错误", "金额低范围不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->lowMoney = static_cast<int>(ui->edLowCash->text().toDouble() * 100);
|
||||||
|
} else {
|
||||||
|
d->filter = CashFilter::FIL_NO_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui->ckClassify->isChecked()) {
|
||||||
|
d->flClassify = true;
|
||||||
|
d->classify = ui->cbClassify->currentText();
|
||||||
|
} else {
|
||||||
|
d->flClassify = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterForm* filterForm = new FilterForm(this, sqlOpr_, comSqlOpr_, repaySqlOpr_);
|
||||||
|
filterForm->exec();
|
||||||
|
|
||||||
|
Calculate();
|
||||||
|
}
|
||||||
50
mainwidget.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef MAINWIDGET_H
|
||||||
|
#define MAINWIDGET_H
|
||||||
|
|
||||||
|
#include "SqlOpr.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "statistic.h"
|
||||||
|
#include <QDialog>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
namespace Ui {
|
||||||
|
class MainWidget;
|
||||||
|
}
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class MainWidget : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWidget(QWidget* parent = nullptr);
|
||||||
|
~MainWidget();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool RefreshData();
|
||||||
|
bool Calculate();
|
||||||
|
void closeEvent(QCloseEvent* event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BaseInit();
|
||||||
|
bool RefreshClassify();
|
||||||
|
void SelectImg();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool AddClassify();
|
||||||
|
bool DelClassify();
|
||||||
|
void Record();
|
||||||
|
void Search();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Statistic> statistic_;
|
||||||
|
std::unique_ptr<ACTSqlOpr> sqlOpr_;
|
||||||
|
std::unique_ptr<ComSqlOpr> comSqlOpr_;
|
||||||
|
std::unique_ptr<RepaySqlOpr> repaySqlOpr_;
|
||||||
|
Ui::MainWidget* ui;
|
||||||
|
};
|
||||||
|
#endif // MAINWIDGET_H
|
||||||
341
mainwidget.ui
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWidget</class>
|
||||||
|
<widget class="QDialog" name="MainWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>687</width>
|
||||||
|
<height>237</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWidget</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lbTotal">
|
||||||
|
<property name="text">
|
||||||
|
<string>NULL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>剩余总现金(元):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lbCurCash">
|
||||||
|
<property name="text">
|
||||||
|
<string>NULL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>信用收支(元)(支出/收入):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lbCredit">
|
||||||
|
<property name="text">
|
||||||
|
<string>NULL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>款项类型:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cbCashType">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDateEdit" name="dateEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTimeEdit" name="timeEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSetNow">
|
||||||
|
<property name="text">
|
||||||
|
<string>设置为现在</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClassifyAdd">
|
||||||
|
<property name="text">
|
||||||
|
<string>分类增</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClassifyDel">
|
||||||
|
<property name="text">
|
||||||
|
<string>分类删</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSet">
|
||||||
|
<property name="text">
|
||||||
|
<string>设定</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>记录事项:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额(元):</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCash">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cbClassify">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnRecord">
|
||||||
|
<property name="text">
|
||||||
|
<string>记录</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="ckType">
|
||||||
|
<property name="text">
|
||||||
|
<string>款项筛选</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="ckDays">
|
||||||
|
<property name="text">
|
||||||
|
<string>最近天数</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QCheckBox" name="ckKey">
|
||||||
|
<property name="text">
|
||||||
|
<string>关键字筛</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QCheckBox" name="ckClassify">
|
||||||
|
<property name="text">
|
||||||
|
<string>分类筛选</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额小:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="5">
|
||||||
|
<widget class="QLineEdit" name="edLowCash"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额大:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="7">
|
||||||
|
<widget class="QLineEdit" name="edHighCash">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QRadioButton" name="rbHigh">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额大于</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QRadioButton" name="rbLow">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额小于</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QRadioButton" name="rbBetween">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额之间</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QRadioButton" name="rbNoLimit">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额不限</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>关键字:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="5">
|
||||||
|
<widget class="QLineEdit" name="edKey"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="6">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>天范围:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="7">
|
||||||
|
<widget class="QLineEdit" name="edDays"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClearFile">
|
||||||
|
<property name="text">
|
||||||
|
<string>清除</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnAddFile">
|
||||||
|
<property name="text">
|
||||||
|
<string>添加附件图</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edFile"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSearch">
|
||||||
|
<property name="text">
|
||||||
|
<string>筛选查找</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
1
ofen
Submodule
133
recordedit.cpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include "recordedit.h"
|
||||||
|
|
||||||
|
#include "repayment.h"
|
||||||
|
#include "ui_recordedit.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
RecordEdit::RecordEdit(QWidget* parent, std::unique_ptr<ComSqlOpr>& comSqlOpr, std::unique_ptr<RepaySqlOpr>& repaySqlOpr)
|
||||||
|
: QDialog(parent), ui(new Ui::RecordEdit), comSqlOpr_(comSqlOpr), repaySqlOpr_(repaySqlOpr)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->cbCalssify->setEditable(true);
|
||||||
|
ui->timeEdit->setDisplayFormat("HH:mm:ss");
|
||||||
|
ui->edCash->setValidator(new QDoubleValidator(0.0, 10000000.0, 2, this));
|
||||||
|
ui->edId->setReadOnly(true);
|
||||||
|
connect(ui->btnModify, &QPushButton::clicked, this, &RecordEdit::Modify);
|
||||||
|
connect(ui->btnCancel, &QPushButton::clicked, this, &RecordEdit::reject);
|
||||||
|
|
||||||
|
connect(ui->btnCurDate, &QPushButton::clicked, this, [this]() {
|
||||||
|
auto curContent = ui->pedMark->toPlainText();
|
||||||
|
curContent += "\n";
|
||||||
|
auto curDt = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
|
||||||
|
curContent += curDt;
|
||||||
|
ui->pedMark->setPlainText(curContent);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->btnYiHuanQing, &QPushButton::clicked, this, [this]() {
|
||||||
|
auto curContent = ui->pedMark->toPlainText();
|
||||||
|
if (curContent.contains("已还清")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
curContent += "\n";
|
||||||
|
curContent += "已还清。";
|
||||||
|
ui->pedMark->setPlainText(curContent);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->btnRepay, &QPushButton::clicked, this, [this]() {
|
||||||
|
QString info;
|
||||||
|
info.append(QString::number(record_.id));
|
||||||
|
info.append(" ");
|
||||||
|
info.append(QString::fromStdString(record_.payType));
|
||||||
|
info.append(" ");
|
||||||
|
info.append(QString::fromStdString(record_.dt));
|
||||||
|
info.append(" ");
|
||||||
|
info.append(QString::fromStdString(record_.classify));
|
||||||
|
|
||||||
|
auto* payment = new Repayment(this, repaySqlOpr_);
|
||||||
|
payment->SetInformation(info);
|
||||||
|
payment->SetRecord(record_);
|
||||||
|
payment->exec();
|
||||||
|
});
|
||||||
|
|
||||||
|
setWindowTitle("编辑");
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordEdit::~RecordEdit()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RecordEdit::exec()
|
||||||
|
{
|
||||||
|
modify_ = false;
|
||||||
|
ShowData();
|
||||||
|
if (!over_) {
|
||||||
|
return QDialog::Rejected;
|
||||||
|
}
|
||||||
|
return QDialog::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordEdit::ShowData()
|
||||||
|
{
|
||||||
|
over_ = false;
|
||||||
|
ClassifyRecordList classifyList;
|
||||||
|
if (!comSqlOpr_->GetClassifyList(classifyList)) {
|
||||||
|
QMessageBox::warning(this, "错误", QString::fromStdString(comSqlOpr_->GetLastErr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ui->cbCalssify->clear();
|
||||||
|
for (const auto& classify : classifyList) {
|
||||||
|
ui->cbCalssify->addItem(QString::fromStdString(classify.value));
|
||||||
|
}
|
||||||
|
if (!classifyList.empty()) {
|
||||||
|
ui->cbCalssify->setCurrentText(QString::fromStdString(record_.classify));
|
||||||
|
}
|
||||||
|
ui->edId->setText(QString::number(record_.id));
|
||||||
|
ui->cbType->addItem("现金支出");
|
||||||
|
ui->cbType->addItem("现金收入");
|
||||||
|
ui->cbType->addItem("信用支出");
|
||||||
|
ui->cbType->addItem("信用收入");
|
||||||
|
ui->cbType->addItem("信用借款");
|
||||||
|
QDateTime datetime = QDateTime::fromString(QString::fromStdString(record_.dt), "yyyy-MM-dd hh:mm:ss");
|
||||||
|
ui->dateEdit->setDate(datetime.date());
|
||||||
|
ui->timeEdit->setTime(datetime.time());
|
||||||
|
|
||||||
|
ui->edCash->setText(QString::number(record_.money / 100.0));
|
||||||
|
ui->pedContent->setPlainText(QString::fromStdString(record_.thing));
|
||||||
|
ui->pedMark->setPlainText(QString::fromStdString(record_.remark));
|
||||||
|
|
||||||
|
ui->cbType->setCurrentText(QString::fromStdString(record_.payType));
|
||||||
|
if (record_.payType == "现金支出" || record_.payType == "现金收入") {
|
||||||
|
ui->btnRepay->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
ui->btnRepay->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
over_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordEdit::GetData()
|
||||||
|
{
|
||||||
|
record_.classify = ui->cbCalssify->currentText().toStdString();
|
||||||
|
record_.payType = ui->cbType->currentText().toStdString();
|
||||||
|
QDateTime datetime;
|
||||||
|
datetime.setDate(ui->dateEdit->date());
|
||||||
|
datetime.setTime(ui->timeEdit->time());
|
||||||
|
auto strMoney = ui->edCash->text();
|
||||||
|
record_.money = Util::CashInt(strMoney.toDouble());
|
||||||
|
record_.dt = datetime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
|
||||||
|
record_.thing = ui->pedContent->toPlainText().toStdString();
|
||||||
|
record_.remark = ui->pedMark->toPlainText().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecordEdit::Modify()
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, "确认修改", "确定修改记录吗?") != QMessageBox::Yes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modify_ = true;
|
||||||
|
GetData();
|
||||||
|
accept();
|
||||||
|
}
|
||||||
39
recordedit.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef RECORDEDIT_H
|
||||||
|
#define RECORDEDIT_H
|
||||||
|
|
||||||
|
#include "SqlOpr.h"
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RecordEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordEdit : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RecordEdit(QWidget* parent, std::unique_ptr<ComSqlOpr>& comSqlOpr, std::unique_ptr<RepaySqlOpr>& repaySqlOpr);
|
||||||
|
~RecordEdit();
|
||||||
|
|
||||||
|
public:
|
||||||
|
int exec() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool modify_ = false;
|
||||||
|
AccountRecord record_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ShowData();
|
||||||
|
void GetData();
|
||||||
|
void Modify();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool autoChange_{false};
|
||||||
|
bool over_{};
|
||||||
|
std::unique_ptr<RepaySqlOpr>& repaySqlOpr_;
|
||||||
|
std::unique_ptr<ComSqlOpr>& comSqlOpr_;
|
||||||
|
Ui::RecordEdit* ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RECORDEDIT_H
|
||||||
206
recordedit.ui
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>RecordEdit</class>
|
||||||
|
<widget class="QDialog" name="RecordEdit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>305</width>
|
||||||
|
<height>386</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>序号:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edId"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>类型:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cbType">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>分类:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cbCalssify">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>金额:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edCash"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>日期:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDateEdit" name="dateEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTimeEdit" name="timeEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>内容:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="pedContent"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>备注:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnYiHuanQing">
|
||||||
|
<property name="text">
|
||||||
|
<string>已还清</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnRepay">
|
||||||
|
<property name="text">
|
||||||
|
<string>还款</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnCurDate">
|
||||||
|
<property name="text">
|
||||||
|
<string>当前时间</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="pedMark"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnModify">
|
||||||
|
<property name="text">
|
||||||
|
<string>修改</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnCancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>取消</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
225
repayment.cpp
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#include "repayment.h"
|
||||||
|
#include "ui_repayment.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
Repayment::Repayment(QWidget* parent, std::unique_ptr<RepaySqlOpr>& repaySqlOpr)
|
||||||
|
: QDialog(parent), ui(new Ui::Repayment), repaySqlOpr_(repaySqlOpr)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
Init();
|
||||||
|
setWindowTitle("还款情况");
|
||||||
|
resize(800, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
Repayment::~Repayment()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Repayment::exec()
|
||||||
|
{
|
||||||
|
ui->lbInfo->setText(info_);
|
||||||
|
ShowData();
|
||||||
|
if (!over_) {
|
||||||
|
return QDialog::Rejected;
|
||||||
|
}
|
||||||
|
return QDialog::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repayment::SetInformation(const QString& info)
|
||||||
|
{
|
||||||
|
info_ = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repayment::SetRecord(const AccountRecord& record)
|
||||||
|
{
|
||||||
|
record_ = record;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repayment::ShowData()
|
||||||
|
{
|
||||||
|
over_ = false;
|
||||||
|
RepayRecordList reuslt;
|
||||||
|
if (!repaySqlOpr_->GetRepayResult(reuslt, record_.id)) {
|
||||||
|
QMessageBox::critical(this, "错误", "获取还款记录失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tw_->setRowCount(reuslt.size());
|
||||||
|
for (int row = 0; row < reuslt.size(); ++row) {
|
||||||
|
QTableWidgetItem* item = new QTableWidgetItem(QString::number(reuslt[row].id));
|
||||||
|
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||||
|
tw_->setItem(row, 0, item);
|
||||||
|
|
||||||
|
item = new QTableWidgetItem(QString::number(reuslt[row].accID));
|
||||||
|
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
||||||
|
tw_->setItem(row, 1, item);
|
||||||
|
|
||||||
|
item = new QTableWidgetItem(QString::number(Util::CashDouble(reuslt[row].money)));
|
||||||
|
tw_->setItem(row, 2, item);
|
||||||
|
|
||||||
|
item = new QTableWidgetItem(QString::fromStdString(reuslt[row].dt));
|
||||||
|
tw_->setItem(row, 3, item);
|
||||||
|
|
||||||
|
item = new QTableWidgetItem(QString::fromStdString(reuslt[row].remark));
|
||||||
|
tw_->setItem(row, 4, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->edPay->setText(QString::number(Util::CashDouble(record_.money)) + "元");
|
||||||
|
|
||||||
|
// 统计还了多少钱
|
||||||
|
BasicAnasys(reuslt);
|
||||||
|
over_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repayment::Init()
|
||||||
|
{
|
||||||
|
ui->edPay->setReadOnly(true);
|
||||||
|
ui->edResult->setReadOnly(true);
|
||||||
|
|
||||||
|
auto* lay = new QVBoxLayout(this);
|
||||||
|
tw_ = new QTableWidget(this);
|
||||||
|
|
||||||
|
QStringList headers;
|
||||||
|
headers << "ID" << "记录ID" << "金额" << "日期" << "备注";
|
||||||
|
|
||||||
|
tw_->setColumnCount(headers.size());
|
||||||
|
tw_->setHorizontalHeaderLabels(headers);
|
||||||
|
tw_->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
|
||||||
|
tw_->setColumnWidth(0, 50);
|
||||||
|
tw_->setColumnWidth(1, 50);
|
||||||
|
tw_->setColumnWidth(2, 100);
|
||||||
|
tw_->setColumnWidth(3, 150);
|
||||||
|
tw_->setColumnWidth(4, 100);
|
||||||
|
|
||||||
|
lay->addWidget(tw_);
|
||||||
|
ui->widget->setLayout(lay);
|
||||||
|
tw_->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
connect(tw_, &QTableWidget::customContextMenuRequested, this, &Repayment::ShowContextMenu);
|
||||||
|
connect(ui->btnSave, &QPushButton::clicked, this, &Repayment::Save);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repayment::ShowContextMenu(const QPoint& pos)
|
||||||
|
{
|
||||||
|
QList<QTableWidgetItem*> selectedItems = tw_->selectedItems();
|
||||||
|
if (selectedItems.isEmpty()) {
|
||||||
|
QAction* acAdd = new QAction("添加", this);
|
||||||
|
QMenu menu(this);
|
||||||
|
connect(acAdd, &QAction::triggered, this, [this]() {
|
||||||
|
bool ok = false;
|
||||||
|
double amount =
|
||||||
|
QInputDialog::getDouble(this, "录入金额", "请输入金额:", 0.0, 0.0, 1000000.0, 2, &ok, Qt::WindowFlags(), 1.0);
|
||||||
|
|
||||||
|
if (!ok || amount <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int row = tw_->rowCount();
|
||||||
|
tw_->insertRow(row);
|
||||||
|
|
||||||
|
QString currentDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
auto* nId = new QTableWidgetItem("");
|
||||||
|
nId->setFlags(nId->flags() & ~Qt::ItemIsEditable);
|
||||||
|
tw_->setItem(row, 0, nId);
|
||||||
|
|
||||||
|
auto* rIdItem = new QTableWidgetItem(QString::number(record_.id));
|
||||||
|
rIdItem->setFlags(rIdItem->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
tw_->setItem(row, 1, rIdItem);
|
||||||
|
tw_->setItem(row, 2, new QTableWidgetItem(QString::number(amount, 'f', 2)));
|
||||||
|
|
||||||
|
auto* dateCur = new QTableWidgetItem(currentDateTime);
|
||||||
|
dateCur->setFlags(dateCur->flags() & ~Qt::ItemIsEditable);
|
||||||
|
|
||||||
|
tw_->setItem(row, 3, dateCur);
|
||||||
|
tw_->setItem(row, 4, new QTableWidgetItem(""));
|
||||||
|
|
||||||
|
tw_->resizeRowToContents(row);
|
||||||
|
tw_->scrollToItem(tw_->item(row, 0));
|
||||||
|
});
|
||||||
|
menu.addAction(acAdd);
|
||||||
|
menu.exec(tw_->viewport()->mapToGlobal(pos));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItems.size() == 5) {
|
||||||
|
QAction* acDel = new QAction("删除", this);
|
||||||
|
QMenu menu(this);
|
||||||
|
connect(acDel, &QAction::triggered, this, [this, selectedItems]() {
|
||||||
|
auto strId = selectedItems[0]->text();
|
||||||
|
if (strId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int id = strId.toInt();
|
||||||
|
// 确认
|
||||||
|
if (QMessageBox::No == QMessageBox::question(this, "删除", "确定删除吗?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!repaySqlOpr_->deleteRepayRecord(id)) {
|
||||||
|
QMessageBox::critical(this, "错误", "删除失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tw_->removeRow(selectedItems[0]->row());
|
||||||
|
});
|
||||||
|
menu.addAction(acDel);
|
||||||
|
menu.exec(tw_->viewport()->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Repayment::Save()
|
||||||
|
{
|
||||||
|
int rowCount = tw_->rowCount();
|
||||||
|
if (rowCount < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int row = 0; row < rowCount; ++row) {
|
||||||
|
auto* id = tw_->item(row, 0);
|
||||||
|
auto* rId = tw_->item(row, 1);
|
||||||
|
auto* amount = tw_->item(row, 2);
|
||||||
|
auto* date = tw_->item(row, 3);
|
||||||
|
auto* note = tw_->item(row, 4);
|
||||||
|
|
||||||
|
auto idText = id->text();
|
||||||
|
if (idText.isEmpty()) {
|
||||||
|
RepayRecord rd;
|
||||||
|
rd.dt = date->text().toStdString();
|
||||||
|
rd.accID = record_.id;
|
||||||
|
rd.money = Util::CashInt(amount->text().toDouble());
|
||||||
|
rd.remark = note->text().toStdString();
|
||||||
|
if (!repaySqlOpr_->InsertRepayRecord(rd)) {
|
||||||
|
QMessageBox::critical(this, "错误", "添加还款记录失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
id->setText(QString::number(rd.id));
|
||||||
|
} else {
|
||||||
|
RepayRecord rd;
|
||||||
|
rd.id = idText.toInt();
|
||||||
|
rd.dt = date->text().toStdString();
|
||||||
|
rd.accID = record_.id;
|
||||||
|
rd.money = Util::CashInt(amount->text().toDouble());
|
||||||
|
rd.remark = note->text().toStdString();
|
||||||
|
if (!repaySqlOpr_->updateRepayRecord(rd)) {
|
||||||
|
QMessageBox::critical(this, "错误", "更新还款记录失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::information(this, "提示", "保存成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repayment::BasicAnasys(const RepayRecordList& rList)
|
||||||
|
{
|
||||||
|
int32_t total{};
|
||||||
|
for (const auto& rd : rList) {
|
||||||
|
total += rd.money;
|
||||||
|
}
|
||||||
|
if (total >= record_.money) {
|
||||||
|
ui->edResult->setText("剩余" + QString::number(Util::CashDouble(total - record_.money)) + "元,已还清。");
|
||||||
|
} else {
|
||||||
|
ui->edResult->setText("剩余" + QString::number(Util::CashDouble(record_.money - total)) + "元,未还清。");
|
||||||
|
}
|
||||||
|
}
|
||||||
41
repayment.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef REPAYMENT_H
|
||||||
|
#define REPAYMENT_H
|
||||||
|
|
||||||
|
#include "SqlOpr.h"
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QTableWidget>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Repayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Repayment : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Repayment(QWidget* parent, std::unique_ptr<RepaySqlOpr>& repaySqlOpr);
|
||||||
|
~Repayment();
|
||||||
|
|
||||||
|
public:
|
||||||
|
int exec() override;
|
||||||
|
void SetInformation(const QString& info);
|
||||||
|
void SetRecord(const AccountRecord& record);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ShowData();
|
||||||
|
void Init();
|
||||||
|
void ShowContextMenu(const QPoint& pos);
|
||||||
|
void Save();
|
||||||
|
void BasicAnasys(const RepayRecordList& rList);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool over_{};
|
||||||
|
QString info_;
|
||||||
|
Ui::Repayment* ui;
|
||||||
|
AccountRecord record_;
|
||||||
|
QTableWidget* tw_{};
|
||||||
|
std::unique_ptr<RepaySqlOpr>& repaySqlOpr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REPAYMENT_H
|
||||||
86
repayment.ui
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Repayment</class>
|
||||||
|
<widget class="QDialog" name="Repayment">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>476</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>统计</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lbInfo">
|
||||||
|
<property name="text">
|
||||||
|
<string>NULL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>总白条:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edPay"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>结果:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="edResult"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSave">
|
||||||
|
<property name="text">
|
||||||
|
<string>保存</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>详情</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
5
res.qrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>resource/ico.ico</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
1
resource/SimpleAccount.rc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
IDI_APP_ICON ICON "ico.ico"
|
||||||
BIN
resource/ico.ico
Normal file
|
After Width: | Height: | Size: 66 KiB |
28
resource/qss.qrc
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>qss/flatgray.css</file>
|
||||||
|
<file>qss/flatgray/add_bottom.png</file>
|
||||||
|
<file>qss/flatgray/add_left.png</file>
|
||||||
|
<file>qss/flatgray/add_right.png</file>
|
||||||
|
<file>qss/flatgray/add_top.png</file>
|
||||||
|
<file>qss/flatgray/arrow_bottom.png</file>
|
||||||
|
<file>qss/flatgray/arrow_left.png</file>
|
||||||
|
<file>qss/flatgray/arrow_right.png</file>
|
||||||
|
<file>qss/flatgray/arrow_top.png</file>
|
||||||
|
<file>qss/flatgray/branch_close.png</file>
|
||||||
|
<file>qss/flatgray/branch_open.png</file>
|
||||||
|
<file>qss/flatgray/calendar_nextmonth.png</file>
|
||||||
|
<file>qss/flatgray/calendar_prevmonth.png</file>
|
||||||
|
<file>qss/flatgray/checkbox_checked.png</file>
|
||||||
|
<file>qss/flatgray/checkbox_checked_disable.png</file>
|
||||||
|
<file>qss/flatgray/checkbox_parcial.png</file>
|
||||||
|
<file>qss/flatgray/checkbox_parcial_disable.png</file>
|
||||||
|
<file>qss/flatgray/checkbox_unchecked.png</file>
|
||||||
|
<file>qss/flatgray/checkbox_unchecked_disable.png</file>
|
||||||
|
<file>qss/flatgray/menu_checked.png</file>
|
||||||
|
<file>qss/flatgray/radiobutton_checked.png</file>
|
||||||
|
<file>qss/flatgray/radiobutton_checked_disable.png</file>
|
||||||
|
<file>qss/flatgray/radiobutton_unchecked.png</file>
|
||||||
|
<file>qss/flatgray/radiobutton_unchecked_disable.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
694
resource/qss/flatgray.css
Normal file
@@ -0,0 +1,694 @@
|
|||||||
|
QPalette{background:#FFFFFF;}*{outline:0px;color:#57595B;}
|
||||||
|
|
||||||
|
QGraphicsView{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
qproperty-backgroundBrush:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[form="true"],QLabel[frameShape="1"]{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
border-radius:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[form="bottom"]{
|
||||||
|
background:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[form="bottom"] .QFrame{
|
||||||
|
border:1px solid #57595B;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[form="bottom"] QLabel,QWidget[form="title"] QLabel{
|
||||||
|
border-radius:0px;
|
||||||
|
color:#57595B;
|
||||||
|
background:none;
|
||||||
|
border-style:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[form="title"],QWidget[nav="left"],QWidget[nav="top"] QAbstractButton{
|
||||||
|
border-style:none;
|
||||||
|
border-radius:0px;
|
||||||
|
padding:5px;
|
||||||
|
color:#57595B;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[nav="top"] QAbstractButton:hover,QWidget[nav="top"] QAbstractButton:pressed,QWidget[nav="top"] QAbstractButton:checked{
|
||||||
|
border-style:solid;
|
||||||
|
border-width:0px 0px 2px 0px;
|
||||||
|
padding:4px 4px 2px 4px;
|
||||||
|
border-color:#575959;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[nav="left"] QAbstractButton{
|
||||||
|
border-radius:0px;
|
||||||
|
color:#57595B;
|
||||||
|
background:none;
|
||||||
|
border-style:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[nav="left"] QAbstractButton:hover{
|
||||||
|
color:#FFFFFF;
|
||||||
|
background-color:#575959;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[nav="left"] QAbstractButton:checked,QWidget[nav="left"] QAbstractButton:pressed{
|
||||||
|
color:#57595B;
|
||||||
|
border-style:solid;
|
||||||
|
border-width:0px 0px 0px 2px;
|
||||||
|
padding:4px 4px 4px 2px;
|
||||||
|
border-color:#575959;
|
||||||
|
background-color:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[video="true"] QLabel{
|
||||||
|
color:#57595B;
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[video="true"] QLabel:focus{
|
||||||
|
border:1px solid #575959;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit:read-only{
|
||||||
|
background-color:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
border-radius:3px;
|
||||||
|
padding:2px;
|
||||||
|
background:none;
|
||||||
|
selection-background-color:#575959;
|
||||||
|
selection-color:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit:focus,QTextEdit:focus,QPlainTextEdit:focus,QSpinBox:focus,QDoubleSpinBox:focus,QComboBox:focus,QDateEdit:focus,QTimeEdit:focus,QDateTimeEdit:focus,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QSpinBox:hover,QDoubleSpinBox:hover,QComboBox:hover,QDateEdit:hover,QTimeEdit:hover,QDateTimeEdit:hover{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit[echoMode="2"]{
|
||||||
|
lineedit-password-character:9679;
|
||||||
|
}
|
||||||
|
|
||||||
|
.QFrame{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
border-radius:3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.QGroupBox{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
border-radius:5px;
|
||||||
|
margin-top:9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.QGroupBox::title{
|
||||||
|
subcontrol-origin:margin;
|
||||||
|
position:relative;
|
||||||
|
left:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.QPushButton,.QToolButton{
|
||||||
|
border-style:none;
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
color:#57595B;
|
||||||
|
padding:5px;
|
||||||
|
min-height:15px;
|
||||||
|
border-radius:5px;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.QPushButton:hover,.QToolButton:hover{
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.QPushButton:pressed,.QToolButton:pressed{
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.QToolButton::menu-indicator{
|
||||||
|
image:None;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton#btnMenu,QPushButton#btnMenu_Min,QPushButton#btnMenu_Max,QPushButton#btnMenu_Close{
|
||||||
|
border-radius:3px;
|
||||||
|
color:#57595B;
|
||||||
|
padding:3px;
|
||||||
|
margin:0px;
|
||||||
|
background:none;
|
||||||
|
border-style:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton#btnMenu:hover,QPushButton#btnMenu_Min:hover,QPushButton#btnMenu_Max:hover{
|
||||||
|
color:#FFFFFF;
|
||||||
|
margin:1px 1px 2px 1px;
|
||||||
|
background-color:rgba(51,127,209,230);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton#btnMenu_Close:hover{
|
||||||
|
color:#FFFFFF;
|
||||||
|
margin:1px 1px 2px 1px;
|
||||||
|
background-color:rgba(238,0,0,128);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator{
|
||||||
|
width:15px;
|
||||||
|
height:15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator::unchecked{
|
||||||
|
image:url(:/qss/flatgray/radiobutton_unchecked.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator::unchecked:disabled{
|
||||||
|
image:url(:/qss/flatgray/radiobutton_unchecked_disable.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator::checked{
|
||||||
|
image:url(:/qss/flatgray/radiobutton_checked.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator::checked:disabled{
|
||||||
|
image:url(:/qss/flatgray/radiobutton_checked_disable.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{
|
||||||
|
padding:0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator,QGroupBox::indicator,QTreeView::indicator,QListView::indicator,QTableView::indicator{
|
||||||
|
width:13px;
|
||||||
|
height:13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator:unchecked,QGroupBox::indicator:unchecked,QTreeView::indicator:unchecked,QListView::indicator:unchecked,QTableView::indicator:unchecked{
|
||||||
|
image:url(:/qss/flatgray/checkbox_unchecked.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator:unchecked:disabled,QGroupBox::indicator:unchecked:disabled,QTreeView::indicator:unchecked:disabled,QListView::indicator:unchecked:disabled,QTableView::indicator:unchecked:disabled{
|
||||||
|
image:url(:/qss/flatgray/checkbox_unchecked_disable.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator:checked,QGroupBox::indicator:checked,QTreeView::indicator:checked,QListView::indicator:checked,QTableView::indicator:checked{
|
||||||
|
image:url(:/qss/flatgray/checkbox_checked.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled,QTreeView::indicator:checked:disabled,QListView::indicator:checked:disabled,QTableView::indicator:checked:disabled{
|
||||||
|
image:url(:/qss/flatgray/checkbox_checked_disable.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator:indeterminate,QGroupBox::indicator:indeterminate,QTreeView::indicator:indeterminate,QListView::indicator:indeterminate,QTableView::indicator:indeterminate{
|
||||||
|
image:url(:/qss/flatgray/checkbox_parcial.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator:indeterminate:disabled,QGroupBox::indicator:indeterminate:disabled,QTreeView::indicator:indeterminate:disabled,QListView::indicator:indeterminate:disabled,QTableView::indicator:indeterminate:disabled{
|
||||||
|
image:url(:/qss/flatgray/checkbox_parcial_disable.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimeEdit::up-button,QDateEdit::up-button,QDateTimeEdit::up-button,QDoubleSpinBox::up-button,QSpinBox::up-button{
|
||||||
|
image:url(:/qss/flatgray/add_top.png);
|
||||||
|
width:10px;
|
||||||
|
height:10px;
|
||||||
|
padding:2px 5px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimeEdit::down-button,QDateEdit::down-button,QDateTimeEdit::down-button,QDoubleSpinBox::down-button,QSpinBox::down-button{
|
||||||
|
image:url(:/qss/flatgray/add_bottom.png);
|
||||||
|
width:10px;
|
||||||
|
height:10px;
|
||||||
|
padding:0px 5px 2px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimeEdit::up-button:pressed,QDateEdit::up-button:pressed,QDateTimeEdit::up-button:pressed,QDoubleSpinBox::up-button:pressed,QSpinBox::up-button:pressed{
|
||||||
|
top:-2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimeEdit::down-button:pressed,QDateEdit::down-button:pressed,QDateTimeEdit::down-button:pressed,QDoubleSpinBox::down-button:pressed,QSpinBox::down-button:pressed,QSpinBox::down-button:pressed{
|
||||||
|
bottom:-2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox::down-arrow,QDateEdit[calendarPopup="true"]::down-arrow,QTimeEdit[calendarPopup="true"]::down-arrow,QDateTimeEdit[calendarPopup="true"]::down-arrow{
|
||||||
|
image:url(:/qss/flatgray/add_bottom.png);
|
||||||
|
width:10px;
|
||||||
|
height:10px;
|
||||||
|
right:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox::drop-down,QDateEdit::drop-down,QTimeEdit::drop-down,QDateTimeEdit::drop-down{
|
||||||
|
subcontrol-origin:padding;
|
||||||
|
subcontrol-position:top right;
|
||||||
|
width:15px;
|
||||||
|
border-left-width:0px;
|
||||||
|
border-left-style:solid;
|
||||||
|
border-top-right-radius:3px;
|
||||||
|
border-bottom-right-radius:3px;
|
||||||
|
border-left-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox::drop-down:on{
|
||||||
|
top:1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenuBar::item{
|
||||||
|
color:#57595B;
|
||||||
|
background-color:#E4E4E4;
|
||||||
|
margin:0px;
|
||||||
|
padding:3px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu,QMenuBar,QMenu:disabled,QMenuBar:disabled{
|
||||||
|
color:#57595B;
|
||||||
|
background-color:#E4E4E4;
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::item{
|
||||||
|
padding:3px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::indicator{
|
||||||
|
width:20px;
|
||||||
|
height:13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::indicator::checked{
|
||||||
|
image:url(:/qss/flatgray/menu_checked.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::right-arrow{
|
||||||
|
image:url(:/qss/flatgray/arrow_right.png);
|
||||||
|
width:13px;
|
||||||
|
height:13px;
|
||||||
|
padding:0px 3px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::item:selected,QMenuBar::item:selected{
|
||||||
|
color:#57595B;
|
||||||
|
border:0px solid #B6B6B6;
|
||||||
|
background:#F6F6F6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::separator{
|
||||||
|
height:1px;
|
||||||
|
background:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar{
|
||||||
|
min-height:10px;
|
||||||
|
background:#E4E4E4;
|
||||||
|
border-radius:5px;
|
||||||
|
text-align:center;
|
||||||
|
border:1px solid #E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar:chunk{
|
||||||
|
border-radius:5px;
|
||||||
|
background-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::groove:horizontal{
|
||||||
|
height:8px;
|
||||||
|
border-radius:4px;
|
||||||
|
background:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::add-page:horizontal{
|
||||||
|
height:8px;
|
||||||
|
border-radius:4px;
|
||||||
|
background:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::sub-page:horizontal{
|
||||||
|
height:8px;
|
||||||
|
border-radius:4px;
|
||||||
|
background:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::handle:horizontal{
|
||||||
|
width:13px;
|
||||||
|
margin-top:-3px;
|
||||||
|
margin-bottom:-3px;
|
||||||
|
border-radius:6px;
|
||||||
|
background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #FFFFFF,stop:0.8 #B6B6B6);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::groove:vertical{
|
||||||
|
width:8px;
|
||||||
|
border-radius:4px;
|
||||||
|
background:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::add-page:vertical{
|
||||||
|
width:8px;
|
||||||
|
border-radius:4px;
|
||||||
|
background:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::sub-page:vertical{
|
||||||
|
width:8px;
|
||||||
|
border-radius:4px;
|
||||||
|
background:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::handle:vertical{
|
||||||
|
height:14px;
|
||||||
|
margin-left:-3px;
|
||||||
|
margin-right:-3px;
|
||||||
|
border-radius:6px;
|
||||||
|
background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #FFFFFF,stop:0.8 #B6B6B6);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar:horizontal{
|
||||||
|
background:#E4E4E4;
|
||||||
|
padding:0px;
|
||||||
|
border-radius:6px;
|
||||||
|
max-height:12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal{
|
||||||
|
background:#B6B6B6;
|
||||||
|
min-width:50px;
|
||||||
|
border-radius:6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal:hover{
|
||||||
|
background:#575959;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:horizontal:pressed{
|
||||||
|
background:#575959;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:horizontal{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::sub-page:horizontal{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-line:horizontal{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::sub-line:horizontal{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar:vertical{
|
||||||
|
background:#E4E4E4;
|
||||||
|
padding:0px;
|
||||||
|
border-radius:6px;
|
||||||
|
max-width:12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical{
|
||||||
|
background:#B6B6B6;
|
||||||
|
min-height:50px;
|
||||||
|
border-radius:6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical:hover{
|
||||||
|
background:#575959;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::handle:vertical:pressed{
|
||||||
|
background:#575959;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:vertical{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::sub-page:vertical{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-line:vertical{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::sub-line:vertical{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollArea{
|
||||||
|
border:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeView,QListView,QTableView,QTabWidget::pane{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
selection-background-color:#F6F6F6;
|
||||||
|
selection-color:#57595B;
|
||||||
|
alternate-background-color:#F6F6F6;
|
||||||
|
gridline-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeView::branch:closed:has-children{
|
||||||
|
margin:4px;
|
||||||
|
border-image:url(:/qss/flatgray/branch_open.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeView::branch:open:has-children{
|
||||||
|
margin:4px;
|
||||||
|
border-image:url(:/qss/flatgray/branch_close.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeView,QListView,QTableView,QSplitter::handle,QTreeView::branch{
|
||||||
|
background:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView::item:selected,QListView::item:selected,QTreeView::item:selected{
|
||||||
|
color:#57595B;
|
||||||
|
background:#E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView::item:hover,QListView::item:hover,QTreeView::item:hover,QHeaderView,QHeaderView::section,QTableCornerButton:section{
|
||||||
|
color:#57595B;
|
||||||
|
background:#F6F6F6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView::item,QListView::item,QTreeView::item{
|
||||||
|
padding:1px;
|
||||||
|
margin:0px;
|
||||||
|
border:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHeaderView::section,QTableCornerButton:section{
|
||||||
|
padding:3px;
|
||||||
|
margin:0px;
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
border-left-width:0px;
|
||||||
|
border-right-width:1px;
|
||||||
|
border-top-width:0px;
|
||||||
|
border-bottom-width:1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
color:#57595B;
|
||||||
|
margin:0px;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:selected{
|
||||||
|
border-style:solid;
|
||||||
|
border-color:#575959;
|
||||||
|
background:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:top,QTabBar::tab:bottom{
|
||||||
|
padding:3px 8px 3px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:left,QTabBar::tab:right{
|
||||||
|
padding:8px 3px 8px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:top:selected{
|
||||||
|
border-width:2px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:right:selected{
|
||||||
|
border-width:0px 0px 0px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:bottom:selected{
|
||||||
|
border-width:0px 0px 2px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:left:selected{
|
||||||
|
border-width:0px 2px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:first:top:selected,QTabBar::tab:first:bottom:selected{
|
||||||
|
border-left-width:1px;
|
||||||
|
border-left-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:first:left:selected,QTabBar::tab:first:right:selected{
|
||||||
|
border-top-width:1px;
|
||||||
|
border-top-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:last:top:selected,QTabBar::tab:last:bottom:selected{
|
||||||
|
border-right-width:1px;
|
||||||
|
border-right-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabBar::tab:last:left:selected,QTabBar::tab:last:right:selected{
|
||||||
|
border-bottom-width:1px;
|
||||||
|
border-bottom-color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStatusBar::item{
|
||||||
|
border:0px solid #E4E4E4;
|
||||||
|
border-radius:3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolBox::tab,QWidget[form="panel"]{
|
||||||
|
padding:3px;
|
||||||
|
border-radius:5px;
|
||||||
|
color:#57595B;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[flag="paneltitle"]{
|
||||||
|
border-bottom-left-radius:0px;
|
||||||
|
border-bottom-right-radius:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[flag="panelcontrol"]{
|
||||||
|
border-top-width:0px;
|
||||||
|
border-top-left-radius:0px;
|
||||||
|
border-top-right-radius:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolTip{
|
||||||
|
border:0px solid #57595B;
|
||||||
|
padding:1px;
|
||||||
|
color:#57595B;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolBox::tab:selected{
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F6F6F6,stop:1 #F6F6F6);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPrintPreviewDialog QToolButton{
|
||||||
|
border:0px solid #57595B;
|
||||||
|
border-radius:0px;
|
||||||
|
margin:0px;
|
||||||
|
padding:3px;
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColorDialog QPushButton,QFileDialog QPushButton{
|
||||||
|
min-width:80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton#qt_calendar_prevmonth{
|
||||||
|
icon-size:0px;
|
||||||
|
min-width:20px;
|
||||||
|
image:url(:/qss/flatgray/calendar_prevmonth.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton#qt_calendar_nextmonth{
|
||||||
|
icon-size:0px;
|
||||||
|
min-width:20px;
|
||||||
|
image:url(:/qss/flatgray/calendar_nextmonth.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton#qt_calendar_prevmonth,QToolButton#qt_calendar_nextmonth,QToolButton#qt_calendar_monthbutton,QToolButton#qt_calendar_yearbutton{
|
||||||
|
border:0px solid #57595B;
|
||||||
|
border-radius:3px;
|
||||||
|
margin:3px 3px 3px 3px;
|
||||||
|
padding:3px;
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton#qt_calendar_prevmonth:hover,QToolButton#qt_calendar_nextmonth:hover,QToolButton#qt_calendar_monthbutton:hover,QToolButton#qt_calendar_yearbutton:hover,QToolButton#qt_calendar_prevmonth:pressed,QToolButton#qt_calendar_nextmonth:pressed,QToolButton#qt_calendar_monthbutton:pressed,QToolButton#qt_calendar_yearbutton:pressed{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCalendarWidget QSpinBox#qt_calendar_yearedit{
|
||||||
|
margin:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCalendarWidget QToolButton::menu-indicator{
|
||||||
|
image:None;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCalendarWidget QTableView{
|
||||||
|
border-width:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCalendarWidget QWidget#qt_calendar_navigationbar{
|
||||||
|
border:1px solid #B6B6B6;
|
||||||
|
border-width:1px 1px 0px 1px;
|
||||||
|
background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E4E4E4,stop:1 #E4E4E4);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView[model="true"]::item{
|
||||||
|
padding:0px;
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView QLineEdit,QTableView QComboBox,QTableView QSpinBox,QTableView QDoubleSpinBox,QTableView QDateEdit,QTableView QTimeEdit,QTableView QDateTimeEdit{
|
||||||
|
border-width:0px;
|
||||||
|
border-radius:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView QLineEdit:focus,QTableView QComboBox:focus,QTableView QSpinBox:focus,QTableView QDoubleSpinBox:focus,QTableView QDateEdit:focus,QTableView QTimeEdit:focus,QTableView QDateTimeEdit:focus{
|
||||||
|
border-width:0px;
|
||||||
|
border-radius:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{
|
||||||
|
background:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTabWidget::pane:top{top:-1px;}
|
||||||
|
QTabWidget::pane:bottom{bottom:-1px;}
|
||||||
|
QTabWidget::pane:left{right:-1px;}
|
||||||
|
QTabWidget::pane:right{left:-1px;}
|
||||||
|
|
||||||
|
QDialog,QDial,#QUIWidgetMain{
|
||||||
|
background-color:#FFFFFF;
|
||||||
|
color:#57595B;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialogButtonBox>QPushButton{
|
||||||
|
min-width:50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QListView[noborder="true"],QTreeView[noborder="true"],QTabWidget[noborder="true"]::pane{
|
||||||
|
border-width:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolBar>*,QStatusBar>*{
|
||||||
|
margin:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*:disabled,QMenu::item:disabled,QTabBar:tab:disabled,QHeaderView::section:disabled{
|
||||||
|
background:#FFFFFF;
|
||||||
|
border-color:#E4E4E4;
|
||||||
|
color:#B6B6B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel:disabled{
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*TextColor:#57595B*/
|
||||||
|
/*PanelColor:#FFFFFF*/
|
||||||
|
/*BorderColor:#B6B6B6*/
|
||||||
|
/*NormalColorStart:#E4E4E4*/
|
||||||
|
/*NormalColorEnd:#E4E4E4*/
|
||||||
|
/*DarkColorStart:#F6F6F6*/
|
||||||
|
/*DarkColorEnd:#F6F6F6*/
|
||||||
|
/*HighColor:#575959*/
|
||||||
BIN
resource/qss/flatgray/add_bottom.png
Normal file
|
After Width: | Height: | Size: 336 B |
BIN
resource/qss/flatgray/add_left.png
Normal file
|
After Width: | Height: | Size: 370 B |
BIN
resource/qss/flatgray/add_right.png
Normal file
|
After Width: | Height: | Size: 358 B |
BIN
resource/qss/flatgray/add_top.png
Normal file
|
After Width: | Height: | Size: 332 B |
BIN
resource/qss/flatgray/arrow_bottom.png
Normal file
|
After Width: | Height: | Size: 337 B |
BIN
resource/qss/flatgray/arrow_left.png
Normal file
|
After Width: | Height: | Size: 376 B |
BIN
resource/qss/flatgray/arrow_right.png
Normal file
|
After Width: | Height: | Size: 360 B |
BIN
resource/qss/flatgray/arrow_top.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
resource/qss/flatgray/branch_close.png
Normal file
|
After Width: | Height: | Size: 263 B |
BIN
resource/qss/flatgray/branch_open.png
Normal file
|
After Width: | Height: | Size: 444 B |
BIN
resource/qss/flatgray/calendar_nextmonth.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
resource/qss/flatgray/calendar_prevmonth.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
resource/qss/flatgray/checkbox_checked.png
Normal file
|
After Width: | Height: | Size: 616 B |
BIN
resource/qss/flatgray/checkbox_checked_disable.png
Normal file
|
After Width: | Height: | Size: 639 B |
BIN
resource/qss/flatgray/checkbox_parcial.png
Normal file
|
After Width: | Height: | Size: 341 B |
BIN
resource/qss/flatgray/checkbox_parcial_disable.png
Normal file
|
After Width: | Height: | Size: 331 B |
BIN
resource/qss/flatgray/checkbox_unchecked.png
Normal file
|
After Width: | Height: | Size: 612 B |
BIN
resource/qss/flatgray/checkbox_unchecked_disable.png
Normal file
|
After Width: | Height: | Size: 646 B |
BIN
resource/qss/flatgray/menu_checked.png
Normal file
|
After Width: | Height: | Size: 542 B |
BIN
resource/qss/flatgray/radiobutton_checked.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
resource/qss/flatgray/radiobutton_checked_disable.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
resource/qss/flatgray/radiobutton_unchecked.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
resource/qss/flatgray/radiobutton_unchecked_disable.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
42
statistic.cpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#include "statistic.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
Statistic::Statistic(std::unique_ptr<RepaySqlOpr>& repaySqlOpr) : repaySqlOpr_(repaySqlOpr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistic::~Statistic()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Statistic::Calculate(const AccountRecordList& list)
|
||||||
|
{
|
||||||
|
auto* d = SharedData::instance();
|
||||||
|
d->ClearTt();
|
||||||
|
|
||||||
|
for (const auto& item : list) {
|
||||||
|
if (item.payType == "现金支出") {
|
||||||
|
d->ttCashOut_ += item.money;
|
||||||
|
} else if (item.payType == "现金收入") {
|
||||||
|
d->ttCashIn_ += item.money;
|
||||||
|
} else if (item.payType == "信用支出") {
|
||||||
|
d->ttCreditOut_ += item.money;
|
||||||
|
RepayRecordList repayList;
|
||||||
|
if (repaySqlOpr_->GetRepayResult(repayList, item.id)) {
|
||||||
|
for (const auto& repay : repayList) {
|
||||||
|
d->ttCashPay_ += repay.money;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (item.payType == "信用收入") {
|
||||||
|
d->ttCreditIn_ += item.money;
|
||||||
|
} else if (item.payType == "信用借款") {
|
||||||
|
d->ttCreditCash_ += item.money;
|
||||||
|
RepayRecordList repayList;
|
||||||
|
if (repaySqlOpr_->GetRepayResult(repayList, item.id)) {
|
||||||
|
for (const auto& repay : repayList) {
|
||||||
|
d->ttCashPay_ += repay.money;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
statistic.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef STATISTIC_H
|
||||||
|
#define STATISTIC_H
|
||||||
|
|
||||||
|
#include "SqlOpr.h"
|
||||||
|
|
||||||
|
class Statistic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Statistic(std::unique_ptr<RepaySqlOpr>& repaySqlOpr);
|
||||||
|
~Statistic();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Calculate(const AccountRecordList& list);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<RepaySqlOpr>& repaySqlOpr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STATISTIC_H
|
||||||
145
util.cpp
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
#include "util.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
static std::string gConfigPath;
|
||||||
|
static std::string gWorkDir;
|
||||||
|
static nlohmann::json gConfig;
|
||||||
|
|
||||||
|
void GenerateDefaultConfig(const std::string& path)
|
||||||
|
{
|
||||||
|
nlohmann::json config;
|
||||||
|
config["MainWidth"] = 1000;
|
||||||
|
config["MainHeight"] = 600;
|
||||||
|
config["Editor"] = "Notepad";
|
||||||
|
config["MediaDir"] = "./Media";
|
||||||
|
config["CurCash"] = 0;
|
||||||
|
config["CurSave"] = 0;
|
||||||
|
std::ofstream configFile(path);
|
||||||
|
configFile << config.dump(4);
|
||||||
|
configFile.close();
|
||||||
|
gConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
Util::Util()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Util::Init()
|
||||||
|
{
|
||||||
|
gWorkDir = QDir::homePath().toStdString() + "/.config/SimpleAccount";
|
||||||
|
if (!QDir(QString::fromStdString(gWorkDir)).exists()) {
|
||||||
|
QDir().mkdir(QString::fromStdString(gWorkDir));
|
||||||
|
}
|
||||||
|
gConfigPath = gWorkDir + "/config.json";
|
||||||
|
return LoadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Util::GetWorkDir()
|
||||||
|
{
|
||||||
|
return gWorkDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Util::GetMediaDir()
|
||||||
|
{
|
||||||
|
return gConfig["MediaDir"].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Util::GetConfigPath()
|
||||||
|
{
|
||||||
|
return gConfigPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<int, int> Util::GetMainSize()
|
||||||
|
{
|
||||||
|
return std::make_pair(gConfig["MainWidth"].get<int>(), gConfig["MainHeight"].get<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Util::SetMainSize(int w, int h)
|
||||||
|
{
|
||||||
|
LoadConfig();
|
||||||
|
|
||||||
|
gConfig["MainWidth"] = w;
|
||||||
|
gConfig["MainHeight"] = h;
|
||||||
|
|
||||||
|
std::ofstream configFile(gConfigPath);
|
||||||
|
if (!configFile.is_open()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
configFile << gConfig.dump(4);
|
||||||
|
configFile.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Util::GetEditor()
|
||||||
|
{
|
||||||
|
return gConfig["Editor"].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Util::NewUUIDName(const QString& path)
|
||||||
|
{
|
||||||
|
QFileInfo fileInfo(path);
|
||||||
|
QString originalSuffix = fileInfo.suffix();
|
||||||
|
QString newName = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||||
|
if (!originalSuffix.isEmpty()) {
|
||||||
|
newName += "." + originalSuffix;
|
||||||
|
}
|
||||||
|
return newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Util::GetCurCash()
|
||||||
|
{
|
||||||
|
return gConfig["CurCash"].get<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Util::GetCurSave()
|
||||||
|
{
|
||||||
|
return gConfig["CurSave"].get<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Util::CashInt(double cash)
|
||||||
|
{
|
||||||
|
return static_cast<int32_t>(round(cash * 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
double Util::CashDouble(int cash)
|
||||||
|
{
|
||||||
|
return static_cast<double>(cash) / 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Util::LoadConfig()
|
||||||
|
{
|
||||||
|
QFile file(QString::fromStdString(gConfigPath));
|
||||||
|
if (file.exists()) {
|
||||||
|
std::ifstream configFile(gConfigPath);
|
||||||
|
if (!configFile.is_open()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gConfig = nlohmann::json::parse(configFile);
|
||||||
|
configFile.close();
|
||||||
|
} else {
|
||||||
|
GenerateDefaultConfig(gConfigPath);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedData::~SharedData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedData* SharedData::instance()
|
||||||
|
{
|
||||||
|
static SharedData data;
|
||||||
|
return &data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedData::ClearTt()
|
||||||
|
{
|
||||||
|
ttCashOut_ = 0;
|
||||||
|
ttCashIn_ = 0;
|
||||||
|
ttCreditIn_ = 0;
|
||||||
|
ttCreditOut_ = 0;
|
||||||
|
ttCreditCash_ = 0;
|
||||||
|
ttCashPay_ = 0;
|
||||||
|
}
|
||||||
79
util.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef UTIL_H
|
||||||
|
#define UTIL_H
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QString>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Util();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool Init();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::string GetWorkDir();
|
||||||
|
static std::string GetMediaDir();
|
||||||
|
static std::string GetConfigPath();
|
||||||
|
static std::pair<int, int> GetMainSize();
|
||||||
|
static bool SetMainSize(int w, int h);
|
||||||
|
static std::string GetEditor();
|
||||||
|
static QString NewUUIDName(const QString& path);
|
||||||
|
static double GetCurCash();
|
||||||
|
static double GetCurSave();
|
||||||
|
static int CashInt(double cash);
|
||||||
|
static double CashDouble(int cash);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool LoadConfig();
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CashFilter {
|
||||||
|
FIL_NO_LIMIT = 0,
|
||||||
|
FIL_LOWER,
|
||||||
|
FIL_HIGHER,
|
||||||
|
FIL_BETWEEN
|
||||||
|
};
|
||||||
|
|
||||||
|
class SharedData
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SharedData() = default;
|
||||||
|
~SharedData();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static SharedData* instance();
|
||||||
|
|
||||||
|
// 条件
|
||||||
|
public:
|
||||||
|
bool flType{};
|
||||||
|
QString type{};
|
||||||
|
bool flDays{};
|
||||||
|
bool flKeys{};
|
||||||
|
bool flClassify{};
|
||||||
|
QString classify{};
|
||||||
|
QString key{};
|
||||||
|
int days{};
|
||||||
|
int lowMoney{};
|
||||||
|
int highMoney{};
|
||||||
|
CashFilter filter{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void ClearTt();
|
||||||
|
|
||||||
|
// 结果
|
||||||
|
public:
|
||||||
|
int32_t ttCashOut_{};
|
||||||
|
int32_t ttCashIn_{};
|
||||||
|
int32_t ttCreditIn_{};
|
||||||
|
int32_t ttCreditOut_{};
|
||||||
|
int32_t ttCreditCash_{};
|
||||||
|
// 还款金额
|
||||||
|
int32_t ttCashPay_{};
|
||||||
|
// 不计算现有现金的理论现金
|
||||||
|
int32_t ttCash_{};
|
||||||
|
};
|
||||||
|
#endif // UTIL_H
|
||||||