Commit 00e8427b by NitefullWind

1. 整合会员项目代码。

parent 7d49c018
#include "fmbackup.h"
#include "fmp_vip_settings.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QDir>
#include <QFile>
#include <QApplication>
#include <QDebug>
FMBackup* FMBackup::_instance = nullptr;
FMBackup::FMBackup()
{
connect();
}
FMBackup* FMBackup::instance()
{
if(_instance == nullptr) {
_instance = new FMBackup();
}
return _instance;
}
bool FMBackup::connect()
{
bool isOk;
QString backupPath = qApp->applicationDirPath()+"/backup/";
QDir dir;
if(!dir.exists(backupPath)) {
dir.mkdir(backupPath);
}
QString dbname = backupPath + "backupReq.db";
if(!QFile::exists(dbname)) {
isOk = createTable(dbname);
} else {
_db = QSqlDatabase::addDatabase("QSQLITE");
_db.setDatabaseName(dbname);
isOk =_db.open();
}
VIP_INFO() << QString::fromLocal8Bit("连接数据库:") << dbname;
if(!isOk) {
VIP_WARN() << QString::fromLocal8Bit("连接失败:") << _db.lastError().text();
}
return isOk;
}
bool FMBackup::createTable(const QString &dbname)
{
_db = QSqlDatabase::addDatabase("QSQLITE");
_db.setDatabaseName(dbname);
_db.open();
QSqlQuery query(_db);
// 创建表
bool isOk = query.exec("create table tbl_req(id integer PRIMARY KEY autoincrement, url varchar(200), req text)");
VIP_INFO() << QString::fromLocal8Bit("创建数据库:") << dbname;
if (!isOk) {
VIP_WARN() << QString::fromLocal8Bit("创建数据库失败:") << query.lastError().text();
}
return isOk;
}
int FMBackup::insertNewRow()
{
if(!_db.isOpen()) {
connect();
}
QSqlQuery query(_db);
bool isOk = query.exec(QString("insert into tbl_req('url','req') values('','');"));
isOk &= query.exec("select last_insert_rowid();");
int id = -1;
if(isOk && query.next()) {
id = query.record().value(0).toInt();
}
return id;
}
bool FMBackup::updateReqData(const int id, const QString url, const QString &reqData)
{
if(!_db.isOpen()) {
connect();
}
QSqlQuery query(_db);
bool isOk = query.exec(QString("update tbl_req set url = '%1', req='%2' where id=%3")
.arg(url)
.arg(reqData)
.arg(id));
VIP_INFO() << QString::fromLocal8Bit("备份数据:") << reqData;
if (!isOk) {
VIP_WARN() << QString::fromLocal8Bit("备份失败:") << query.lastError().text();
}
return isOk;
}
bool FMBackup::removeReqData(const int &id)
{
QSqlQuery query(_db);
bool isOk = query.exec(QString("delete from tbl_req where id==%1").arg(id));
if(!isOk) {
VIP_WARN() << QString::fromLocal8Bit("删除数据时出现错误:") << query.lastError().text();
}
return isOk;
}
QSqlQuery FMBackup::reqDataQuery() const
{
QSqlQuery query(_db);
bool isOk = query.exec("select * from tbl_req");
if(!isOk) {
VIP_WARN() << QString::fromLocal8Bit("查询数据时出现错误:") << query.lastError().text();
}
return query;
}
bool FMBackup::reset()
{
QSqlQuery query(_db);
bool isOk = query.exec("VACUUM");
VIP_INFO() << QString::fromLocal8Bit("数据库重置: ") << isOk;
return isOk;
}
#ifndef FMBACKUP_H
#define FMBACKUP_H
#include <QSqlDatabase>
#include <QSqlRecord>
class FMBackup
{
public:
static FMBackup* instance();
bool updateReqData(const int id, const QString url, const QString &reqData);
bool removeReqData(const int &id);
int insertNewRow();
QSqlQuery reqDataQuery() const;
bool reset();
private:
FMBackup();
static FMBackup* _instance;
QSqlDatabase _db;
bool connect();
bool createTable(const QString &dbname);
private:
class privateFMBackup
{
public:
~privateFMBackup()
{
if(FMBackup::_instance != nullptr) {
delete FMBackup::_instance;
FMBackup::_instance = nullptr;
}
}
};
};
#endif // FMBACKUP_H
#include "resend.h"
#include "fmbackup.h"
#include "fmnetwork.h"
#include "fmp_vip_settings.h"
#include <QSqlQuery>
#include <QSqlRecord>
#include <QNetworkReply>
#include <QDebug>
ReSend::ReSend()
{
}
ReSend::~ReSend()
{
}
void ReSend::trySend()
{
QSqlRecord record;
QSqlQuery reqDataQuery = FMBackup::instance()->reqDataQuery();
while(reqDataQuery.next())
{
record = reqDataQuery.record();
int id = record.value(ID).toInt();
QString url = record.value(URL).toString();
QByteArray data = record.value(DATA).toByteArray();
QByteArray rspData;
FMNetwork net;
net.send(url, data, rspData);
// 如果发送失败则不再继续发送
if(net.error != 1) {
break;
} else{
FMBackup::instance()->removeReqData(id);
VIP_INFO() << QString::fromLocal8Bit("重发响应成功:")<< rspData;
}
}
}
void ReSend::run()
{
while(true)
{
trySend();
QThread::sleep(5);
}
}
#ifndef RESEND_H
#define RESEND_H
#include <QObject>
#include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QMutex>
#include <QWaitCondition>
#define ID 0
#define URL 1
#define DATA 2
class FMApiCfg;
class ReSend : public QThread
{
Q_OBJECT
public:
ReSend();
void trySend();
~ReSend();
protected:
void run();
};
#endif // RESEND_H
#include "fmnetwork.h"
#include "global.h"
#include "fmp_vip_settings.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>
#include <QTimer>
#include <QSettings>
FMNetwork::FMNetwork(QObject *parent) :
QObject(parent),
error(FM_API_SUCCESS),
_nam(new QNetworkAccessManager),
_req(new QNetworkRequest)
{
}
FMNetwork::~FMNetwork()
{
del_p(_nam);
del_p(_req);
}
int FMNetwork::send(const QString &url, const QByteArray &reqData, QByteArray &rspData)
{
error = FM_API_SUCCESS;
VIP_INFO() << "Send Url: " << url;
VIP_INFO() << "Send Data: " << reqData;
_req->setUrl(url);
// 设置请求头
_req->setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
_req->setHeader(QNetworkRequest::ContentLengthHeader, reqData.length());
auto reply = _nam->post(*_req, reqData);
// 使用定时器处理超时
QEventLoop loop;
connect(_nam, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()));
QTimer timer;
timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()),&loop,SLOT(quit()));
timer.start(1000 * 30);
loop.exec();
if(timer.isActive())
{
timer.stop();
if (reply->error() == QNetworkReply::NoError) {
rspData = reply->readAll();
} else {
int err = reply->error();
error = FM_API_NETWORERROR;
errorMsg = netErrInfo(err);
}
}else{
error = FM_API_TIMEOUT;
}
return error;
}
QString FMNetwork::netErrInfo(int code)
{
QSettings setting(AppDirPath+"/FMVip.cfg", QSettings::IniFormat);
setting.setIniCodec("GBK");
setting.beginGroup("NetworkError");
QString key = QString::number(code);
if(!setting.contains(key)) {
key = "default";
}
QString errInfo = setting.value(key).toString();
setting.endGroup();
return errInfo;
}
#ifndef FMNETWORK_H
#define FMNETWORK_H
#include <QObject>
#include <QJsonObject>
class QNetworkAccessManager;
class QNetworkRequest;
class FMNetwork : public QObject
{
Q_OBJECT
public:
explicit FMNetwork(QObject *parent = 0);
~FMNetwork();
int send(const QString &url, const QByteArray &reqData, QByteArray &rspData);
int error;
QString errorMsg;
private:
QNetworkAccessManager *_nam;
QNetworkRequest *_req;
QString netErrInfo(int code);
};
#endif // FMNETWORK_H
#include <fmp_logger_i.h>
#include "fmp_ve_handlers.h"
#include "fmp_vip.h"
FMPStartEventHandler::FMPStartEventHandler(ctkPluginContext *ctx, FMPVip *vip)
: FMPVipEventHandler(FMP_TOPICS_SERVICES FMPE_SERVICE_ACK_START "/"
+ QString::number(ctx->getPlugin()->getPluginId()), vip),
_ctx(ctx)
{
FMPProps props;
props[ctkEventConstants::EVENT_TOPIC] = _topic;
_ctx->registerService<ctkEventHandler>(this, props);
}
void FMPStartEventHandler::handleEvent(const ctkEvent &event)
{
if (_vip) {
if (event.getProperty(FMP_PROPKEY_AGREED).toBool()) {
_vip->StartVip();
}
else {
FMP_WARN_CTX(_ctx) << "Refused start request" << event.getTopic();
}
}
else {
FMP_DEBUG_CTX(_ctx) << "No handler instance for event" << event.getTopic();
}
}
#ifndef FMP_MANAGER_EVENT_HANDLERS_H
#define FMP_MANAGER_EVENT_HANDLERS_H
#include <QObject>
#include <service/event/ctkEventConstants.h>
#include <service/event/ctkEventHandler.h>
class FMPVip;
class FMPVipEventHandler : public ctkEventHandler
{
public:
explicit FMPVipEventHandler(const QString &topic, FMPVip *vip) : _vip(vip), _topic(topic) {}
protected:
FMPVip* _vip;
const QString _topic;
};
/**
* 升级事件处理类
* @brief The FMPUpgradeEventHandler class
*/
class FMPStartEventHandler : public QObject, public FMPVipEventHandler
{
Q_OBJECT
Q_INTERFACES(ctkEventHandler)
public:
explicit FMPStartEventHandler(ctkPluginContext *ctx, FMPVip *vip);
void handleEvent(const ctkEvent &event);
private:
ctkPluginContext* _ctx;
};
#endif // FMP_MANAGER_EVENT_HANDLERS_H
#include "fmp_vip_p.h"
#include "fmp_ve_handlers.h"
class ctkPluginContext;
FMPVip::FMPVip(ctkPluginContext *context)
: FMPVipInterface(context),
_inited(false),
d_ptr(new FMPVipPrivate(this))
{
FMPStartEventHandler *handler = new FMPStartEventHandler(_ctx, this);
}
int FMPVip::StopService()
{
if (!_inited) return FMP_SUCCESS;
Q_D(FMPVip);
return d->StopService();
}
int FMPVip::StartVip()
{
Q_D(FMPVip);
return d->StartVip();
}
#ifndef FMP_VIP_H
#define FMP_VIP_H
#include <QObject>
#include "fmp_vip_i.h"
class FMPVipPrivate;
class FMPVip : public QObject, public FMPVipInterface
{
Q_OBJECT
Q_INTERFACES(FMPBaseInterface)
Q_INTERFACES(FMPVipInterface)
Q_DECLARE_PRIVATE(FMPVip)
public:
FMPVip(ctkPluginContext *context);
int StopService();
int StartVip();
private:
bool _inited;
FMPVipPrivate* d_ptr;
};
#endif // FMP_VIP_H
#-------------------------------------------------
#
# Project created by QtCreator 2017-01-11T15:59:15
#
#-------------------------------------------------
TEMPLATE = lib
QT += core gui network sql
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
SOURCES += \
fmp_vip.cpp \
fmp_vip_p.cpp \
fmp_vip_plugin.cpp \
backup/fmbackup.cpp \
backup/resend.cpp \
task/fmtask.cpp \
task/fmtasknownd.cpp \
task/session.cpp \
task/taskfactory.cpp \
task/taskfinal.cpp \
task/taskfund.cpp \
task/tasklogin.cpp \
task/taskothers.cpp \
task/taskpay.cpp \
windows/fmcouponwidget.cpp \
windows/fmloading.cpp \
windows/fmmsgwnd.cpp \
windows/fmvipfund.cpp \
windows/fmviplogin.cpp \
windows/fmviporder.cpp \
windows/fmvippanel.cpp \
windows/fmvipwnd.cpp \
fmnetwork.cpp \
fmvipdispatcher.cpp \
fmp_ve_handlers.cpp \
fmp_vip_server.cpp \
fmp_vip_settings.cpp
HEADERS +=\
fmp_vip.h \
fmp_vip_i.h \
fmp_vip_p.h \
fmp_vip_plugin_p.h \
backup/fmbackup.h \
backup/resend.h \
task/fmtask.h \
task/fmtasknownd.h \
task/session.h \
task/taskfactory.h \
task/taskfinal.h \
task/taskfund.h \
task/tasklogin.h \
task/taskothers.h \
task/taskpay.h \
windows/fmcouponwidget.h \
windows/fmloading.h \
windows/fmmsgwnd.h \
windows/fmvipfund.h \
windows/fmviplogin.h \
windows/fmviporder.h \
windows/fmvippanel.h \
windows/fmvipwnd.h \
fmnetwork.h \
fmvipdispatcher.h \
global.h \
fmp_ve_handlers.h \
fmp_vip_server.h \
fmp_vip_settings.h
unix {
target.path = /usr/lib
INSTALLS += target
}
#Target name
VER = $$system($$PWD/../fmprc.bat $$TARGET)
ORIGIN_TARGET = $$TARGET
TARGET = $${TARGET}_$${VER}
#Header path
INCLUDEPATH += $$PWD/../include/ctk \
+= $$PWD/../include/interface \
INCLUDEPATH += ./task ./windows ./backup
#Library path
LIBS += -L$$PWD/../lib
win32 {
LIBS += -lws2_32 -luser32
}
CONFIG(debug, debug|release) {
#Linking library
LIBS += -lCTKCored -lCTKPluginFrameworkd
#Destination path
DESTDIR = $$PWD/../debug/plugins
} else {
LIBS += -lCTKCore -lCTKPluginFramework
DESTDIR = $$PWD/../release/plugins
}
#
RESOURCES += \
res/$${ORIGIN_TARGET}.qrc \
res/img.qrc
win32 {
RC_FILE += res/$${ORIGIN_TARGET}.rc
system($$PWD/../fmprc.bat $$PWD/version.h $$ORIGIN_TARGET)
}
else {
system($$PWD/../fmprc.sh $$PWD/version.h $$ORIGIN_TARGET)
}
FORMS += \
windows/forms/fmcouponwidget.ui \
windows/forms/fmloading.ui \
windows/forms/fmmsgwnd.ui \
windows/forms/fmvipfund.ui \
windows/forms/fmviplogin.ui \
windows/forms/fmviporder.ui \
windows/forms/fmvippanel.ui
#ifndef FMP_VIP_I_H
#define FMP_VIP_I_H
#include <fmp_plugin_i.h>
/**
* 业务插件接口,必须继承自 FMPluginInterface
* @brief The FMPVipInterface class
*/
class FMPVipInterface : public FMPluginInterface
{
public:
explicit FMPVipInterface(ctkPluginContext *ctx) : FMPluginInterface(ctx) {}
virtual int StartVip() = 0;
};
Q_DECLARE_INTERFACE(FMPVipInterface, "com.fmp.vip")
#endif // FMP_LOGGER_I_H
#include "fmp_vip_p.h"
#include <fmp_settings_i.h>
#include <QCoreApplication>
#include <QDateTime>
#include <ctkPluginContext.h>
#include <ctkServiceReference.h>
#include "fmp_vip_server.h"
#include "fmp_vip_settings.h"
#include "fmp_logger_i.h"
#include "resend.h"
#include <QDebug>
FMPVipPrivate::FMPVipPrivate(FMPVip *vip):
q_ptr(vip)
{
connect(this, &FMPVipPrivate::startVip, this, &FMPVipPrivate::onStartVip);
}
int FMPVipPrivate::StartVip()
{
Q_Q(FMPVip);
FMPLoggerInterface *logger = q->GetService<FMPLoggerInterface>(q->_ctx);
FMP_INFO(logger) << "Vip start";
_settings = q->GetService<FMPSettingsInterface>(q->_ctx);
FMPVipSettings::instance()->init(_settings, logger);
emit startVip();
q->_inited = true;
return FMP_SUCCESS;
}
int FMPVipPrivate::StopService()
{
Q_Q(FMPVip);
//! Clean up
q->_inited = false;
return FMP_SUCCESS;
}
void FMPVipPrivate::onStartVip()
{
auto resend = new ReSend();
resend->start();
FMPVipServer::instance();
}
#ifndef FMP_VIP_P_H
#define FMP_VIP_P_H
#include <QObject>
#include "fmp_vip.h"
class FMPSettingsInterface;
class FMPVipPrivate : public QObject
{
Q_OBJECT
Q_DECLARE_PUBLIC(FMPVip)
public:
FMPVipPrivate(FMPVip *vip);
int StopService();
int StartVip();
signals:
void startVip();
private slots:
void onStartVip();
public:
FMPVip *q_ptr;
private:
FMPSettingsInterface *_settings;
};
#endif // FMP_VIP_P_H
/*=============================================================================
Library: CTK
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=============================================================================*/
#include "fmp_vip_plugin_p.h"
#include "fmp_vip.h"
#include <QtPlugin>
#include <QStringList>
#include <QDebug>
FMPVipPlugin::FMPVipPlugin()
: _vip_service(0)
{
}
void FMPVipPlugin::start(ctkPluginContext* context)
{
_vip_service = new FMPVip(context);
context->registerService<FMPVipInterface>( _vip_service);
}
void FMPVipPlugin::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
if (_vip_service)
{
delete _vip_service;
_vip_service = 0;
}
}
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
Q_EXPORT_PLUGIN2(fmp_vip, FMPVipPlugin)
#endif
#ifndef FMP_VIP_PLUGIN_P_H
#define FMP_VIP_PLUGIN_P_H
#include <ctkPluginActivator.h>
class FMPVip;
class FMPVipPlugin : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_INTERFACES(ctkPluginActivator)
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
Q_PLUGIN_METADATA(IID "com_fmp_vip")
#endif
public:
explicit FMPVipPlugin();
void start(ctkPluginContext* context);
void stop(ctkPluginContext* context);
private:
FMPVip* _vip_service;
}; // FMPVipPlugin
#endif // FMP_VIP_PLUGIN_P_H
#include "fmp_vip_server.h"
#include "fmvipdispatcher.h"
#include "fmp_vip_settings.h"
#include <QTcpSocket>
#include <QDebug>
FMPVipServer *FMPVipServer::instance()
{
static FMPVipServer server;
return &server;
}
FMPVipServer::FMPVipServer() :
QTcpServer(),
socket(nullptr),
dispatcher(new FMVipDispatcher(this))
{
Listen(23770);
connect(this, &QTcpServer::newConnection, this, &FMPVipServer::onNewConnection);
}
void FMPVipServer::Listen(quint16 port)
{
if(!this->listen(QHostAddress::Any, port)) {
VIP_ERROR() << "Listen error: " << this->errorString();
}
}
void FMPVipServer::Write(const QByteArray &data)
{
if(socket->write(data) == -1) {
VIP_ERROR() << "Write error: " <<socket->error() << socket->errorString();
}
}
void FMPVipServer::onNewConnection()
{
socket = nextPendingConnection();
connect(socket, &QTcpSocket::disconnected, this, &FMPVipServer::onDisconnected);
connect(socket, &QTcpSocket::readyRead, this, &FMPVipServer::onReadyRead);
}
void FMPVipServer::onDisconnected()
{
VIP_DEBUG() << "Socket disconnected.";
}
void FMPVipServer::onReadyRead()
{
QByteArray recvData = socket->readAll();
FMSOCKEHEADER header = {0};
memcpy(&header, recvData.data(), sizeof(FMSOCKEHEADER));
if(header.flag != FMSOCKFLAG) {
VIP_WARN() << "Incompatible protocol.";
return;
}
QByteArray rspData;
dispatcher->doTask(recvData.mid(sizeof(FMSOCKEHEADER)), rspData);
Write(rspData);
}
#ifndef FMP_VIP_SERVER_H
#define FMP_VIP_SERVER_H
#include <QTcpServer>
#define FMSOCKFLAG 0x4d46
class FMVipDispatcher;
typedef struct {
int flag;
int ver;
int len;
}FMSOCKEHEADER;
class FMPVipServer : public QTcpServer
{
public:
static FMPVipServer *instance();
void Listen(quint16 port);
void Write(const QByteArray &data);
//signals:
private slots:
void onNewConnection();
void onDisconnected();
void onReadyRead();
private:
explicit FMPVipServer();
QTcpSocket *socket;
FMVipDispatcher *dispatcher;
};
#endif // FMP_VIP_SERVER_H
#include "fmp_vip_settings.h"
#include <fmp_settings_i.h>
#include <QDebug>
FMPVipSettings::FMPVipSettings(QObject *parent) : QObject(parent)
{
}
FMPVipSettings *FMPVipSettings::instance()
{
static FMPVipSettings vipSettings;
return &vipSettings;
}
void FMPVipSettings::init(FMPSettingsInterface *settings, FMPLoggerInterface *logger)
{
this->_settings = settings;
this->_logger = logger;
}
FMPLoggerInterface *FMPVipSettings::getLogger()
{
return _logger;
}
QString FMPVipSettings::getServerUrl()
{
return _GetValue(FMP_INIKEY_VIPSERVER).toString();
}
QVariant FMPVipSettings::_GetValue(const QString &key, QVariant defaultValue)
{
if (_settings) {
return _settings->GetValue(key);
}
else {
VIP_WARN() << "Settings service not available";
}
return defaultValue;
}
bool FMPVipSettings::_SetValue(const QString &key, QVariant value)
{
if (_settings) {
_settings->SetValue(key, value);
return true;
}
else {
VIP_WARN() << "Settings service not available";
}
return false;
}
#ifndef FMP_VIP_SETTINGS_H
#define FMP_VIP_SETTINGS_H
#include <QObject>
#include <QVariant>
#include <fmp_logger_i.h>
class FMPSettingsInterface;
class FMPVipSettings : public QObject
{
Q_OBJECT
public:
static FMPVipSettings *instance();
void init(FMPSettingsInterface *settings, FMPLoggerInterface *logger);
FMPLoggerInterface *getLogger();
QString getServerUrl();
private:
explicit FMPVipSettings(QObject *parent = 0);
QVariant _GetValue(const QString &key, QVariant defaultValue = 0);
bool _SetValue(const QString &key, QVariant value);
private:
FMPSettingsInterface *_settings;
FMPLoggerInterface *_logger;
};
#define VIP_DEBUG() FMP_DEBUG(FMPVipSettings::instance()->getLogger())
#define VIP_INFO() FMP_INFO(FMPVipSettings::instance()->getLogger())
#define VIP_WARN() FMP_WARN(FMPVipSettings::instance()->getLogger())
#define VIP_ERROR() FMP_ERROR(FMPVipSettings::instance()->getLogger())
#endif // FMP_VIP_SETTINGS_H
#include <QMenu>
#include <QAction>
#include <QTimer>
#include "fmp_vip_settings.h"
#include <winsock2.h>
#include "fmvipdispatcher.h"
#include "fmtask.h"
#include "taskfactory.h"
#include "fmp_vip_server.h"
FMVipDispatcher::FMVipDispatcher(QObject *parent) :
QObject(parent),
// FMApiRelay(),
// _posSocketTimer(new QTimer(this)),
fmTask(nullptr)
// server(new FMPVipServer(this))
{
// connect(this, SIGNAL(doTask()), this, SLOT(onDoTask()));
// _posSocketTimer->setInterval(5000);
// connect(_posSocketTimer, SIGNAL(timeout()), SLOT(onCheckSocket()));
// connect(this, SIGNAL(startSocketTimer()), _posSocketTimer, SLOT(start()));
// connect(this, SIGNAL(stopSocketTimer()), _posSocketTimer, SLOT(stop()));
// server->Listen(23770);
}
FMVipDispatcher::~FMVipDispatcher()
{
// del_p(_posSocketTimer);
}
//BOOL FMVipDispatcher::Transfer(LPSTR data, LPSTR &rsp, UINT &rsp_len)
//{
// if (strcmp(data, QuitCMD) != 0 && !_posSocketTimer->isActive()) {
// emit startSocketTimer();
// mutex.lock();
// reqData = QByteArray(data);
// emit doTask();
// condition.wait(&mutex);
// mutex.unlock();
// rsp = rspData.data();
// rsp_len = rspData.length();
// emit stopSocketTimer();
// }
// return true;
//}
void FMVipDispatcher::doTask(const QByteArray &reqData, QByteArray &rspData)
{
VIP_INFO() << "Recv POS reqData: " << reqData;
fmTask = TaskFactory::Task(reqData);
if (fmTask == nullptr) {
rspData = QString::fromLocal8Bit("{\"msg:\":\"未知的请求类型\"}").toUtf8();
} else {
rspData = fmTask->doTask();
}
VIP_INFO() << "Send to pos: " << rspData;
// condition.wakeAll();
del_p(fmTask);
}
//void FMVipDispatcher::onCheckSocket()
//{
// if(_socket <=0 ) {
// emit stopSocketTimer();
// return;
// }
// WORD wVersionRequested;
// WSADATA wsaData;
// wVersionRequested = MAKEWORD(2, 2);
// WSAStartup(wVersionRequested, &wsaData);
// HANDLE closeEvent = WSACreateEvent();
// WSAEventSelect(_socket, closeEvent, FD_CLOSE);
// DWORD dwRet = WaitForSingleObject(closeEvent, 0);
// if(dwRet == WSA_WAIT_EVENT_0) {
// onDisconnected();
// }
// WSACloseEvent(closeEvent);
// WSACleanup();
//}
//void FMVipDispatcher::onDisconnected()
//{
// fmTask->stopTask();
// FMMsgWnd::FailureWnd(QString::fromLocal8Bit("操作时间过长,POS已断开Socket连接,请重新操作!"));
// condition.wakeAll();
//}
#ifndef FMVIPDISPATCHER_H
#define FMVIPDISPATCHER_H
#include <QObject>
#include <QMutex>
#include <QWaitCondition>
#include <QSystemTrayIcon>
//#include "fmapirelay.h"
class FMTask;
class FMPVipServer;
class FMVipDispatcher : public QObject/*, public FMApiRelay*/
{
Q_OBJECT
public:
explicit FMVipDispatcher(QObject *parent = 0);
~FMVipDispatcher();
void doTask(const QByteArray &reqData, QByteArray &rspData);
private:
QMutex mutex;
QWaitCondition condition;
// QByteArray reqData;
// QByteArray rspData;
QTimer *_posSocketTimer;
FMTask *fmTask;
FMPVipServer *server;
//protected:
//// BOOL Transfer(LPSTR data, LPSTR &rsp, UINT &rsp_len);
//signals:
// void doTask();
// void startSocketTimer();
// void stopSocketTimer();
//public slots:
// void onDoTask();
// void onCheckSocket();
// void onDisconnected();
};
#endif // FMVIPDISPATCHER_H
#ifndef GLOBAL_H
#define GLOBAL_H
#include <QObject>
#include <QApplication>
#include <string>
// 商家信息
#define APP_ID "T007"
#define KEY_CODE "98d094a7-0d07-4cf5-b23b-d18783f0d76a"
#define PARTNER_ID "a8bee0dd-09d1-4fa9-a9eb-80cb36d3d611"
// 请求类型链表
const static QStringList FM_Type_List = QString(
"member_check_request,"
"coupon_check_request,"
"member_charge_request,"
"order_request,"
"integral_request,"
"order_refund_request,"
"charge_refund_request,"
"order_revoke_request" ).split(",");
// 服务端请求类型
const static int FM_Server_Type[] = {1001,1006,1002,1003,1007,1004,1004,1005};
// 请求类型的枚举值
enum FM_TYPE {
FM_Login,
FM_Coupon,
FM_Fund,
FM_Pay,
FM_Final,
FM_Order_Refund,
FM_Charge_Refund,
FM_Order_Revoke
};
// JSON数据各字段名称
#ifndef POSPROPS
#define POSPROPS
struct PP{
PP()
{
AppId = "appId";
PartnerId = "partnerId";
T = "t";
StoreId = "store_id";
PosId = "pos_id";
OperatorId = "operator_id";
BussinessDate = "business_date";
Fm_cmd = "fm_cmd";
FM_Type = "FM_Type";
TransId = "trans_id";
Member_sign = "member_sign";
Name = "name";
Birthday = "birthday";
Amount = "amount";
Mobile = "mobile";
Fm_open_id = "fm_open_id";
CanPay = "CanPay";
Score = "score";
StatusCode = "statusCode";
Msg = "msg";
Prompt = "prompt";
Coupon = "coupon"; // 优惠券查询时的优惠券号
CodeAmount = "codeAmount";
ScoreAmount = "scoreAmount";
IsUseScore = "isUseScore";
Coupons = "coupons";
Transaction = "transactions";
OrderAmount = "order_amount";
PaidAmount = "paid_amount";
StandardAmount = "standard_amount";
Fm_id = "fm_id";
Pay_ids = "pay_ids";
Pay_id = "pay_id";
Pay_str = "pay_str";
Paid_total_amount= "paid_total_amount";
Pay_transId = "pay_transId";
CouponList = "couponList"; // 代金券列表
Coupon_code = "code"; // 优惠券 / 代金券编码
Coupon_disAmount = "disAmount"; // 代金券抵扣金额
Coupon_desc = "desc"; // 代金券描述
CouponMap = "payCouponMap"; // 代金券map
Products = "products";
ConsumeNum = "consume_num";
Price = "price";
ProductId = "pid";
Print1 = "print1";
Print2 = "print2";
ChargeAmount = "charge_amount";
CashAmount = "cashAmount";
Print = "print";
ThirdAmount = "thirdAmount";
}
QString AppId ;
QString PartnerId ;
QString T ;
QString StoreId ;
QString PosId ;
QString OperatorId ;
QString BussinessDate ;
QString Fm_cmd ;
QString FM_Type ;
QString TransId ;
QString Member_sign ;
QString Name ;
QString Birthday ;
QString Amount ;
QString Mobile ;
QString Fm_open_id ;
QString CanPay ;
QString Score ;
QString StatusCode ;
QString Msg ;
QString Prompt ;
QString Coupon ;
// 支付
QString CodeAmount ;
QString ScoreAmount ;
QString IsUseScore ;
QString Coupons ;
QString Transaction ;
QString OrderAmount ;
QString PaidAmount ;
QString StandardAmount ;
QString Fm_id ;
// 支付方式
QString Pay_ids ;
QString Pay_id ;
QString Pay_str ;
QString Paid_total_amount ;
QString Pay_transId ;
QString CouponList ;
QString Coupon_code ;
QString Coupon_disAmount ;
QString Coupon_desc ;
QString CouponMap ;
// 产品
QString Products ;
QString ConsumeNum ;
QString Price ;
QString ProductId ;
QString Print1 ;
QString Print2 ;
// 充值
QString ChargeAmount ;
QString CashAmount ;
QString Print ;
QString ThirdAmount ;
};
const static PP PosProps;
#endif
// Pos端属性与服务端属性映射配置
#ifndef FMPROPSMAP
#define FMPROPSMAP
typedef std::map<QString, QString> PropsMap;
const PropsMap::value_type PropsMapPairs[] =
{
PropsMap::value_type(PosProps.Fm_cmd, "reqType"),
PropsMap::value_type(PosProps.Member_sign, "code"),
PropsMap::value_type(PosProps.StoreId, "storeId"),
PropsMap::value_type(PosProps.PosId, "stationId"),
PropsMap::value_type(PosProps.OperatorId, "operatorId"),
PropsMap::value_type(PosProps.Mobile, "mobile"),
PropsMap::value_type(PosProps.TransId, "transId"),
PropsMap::value_type(PosProps.Coupon, "couponCode"),
PropsMap::value_type(PosProps.BussinessDate,"businessDate")
};
static PropsMap PosToServerProps(PropsMapPairs, PropsMapPairs + (sizeof(PropsMapPairs)/sizeof(PropsMapPairs[0])));
class FMPropsMap
{
public:
static QString get(QString posProp) {
PropsMap::iterator it = PosToServerProps.find(posProp);
if(it != PosToServerProps.end()) {
return it->second;
}
return posProp;
}
};
#endif
#define ServerProps(posProp) FMPropsMap::get(posProp)
// 签名字段
const static QString SignProps[] = {
PosProps.AppId,
PosProps.PartnerId,
PosProps.T,
ServerProps(PosProps.Fm_cmd),
ServerProps(PosProps.StoreId),
ServerProps(PosProps.PosId),
ServerProps(PosProps.OperatorId)
};
// 默认要从POS请求中拷贝到服务请求的字段
const static QString DefaultProps[] = {
PosProps.StoreId,
PosProps.PosId,
PosProps.OperatorId,
PosProps.BussinessDate
};
// 删除指针宏
#define del_p(p) \
if ((p) != nullptr) { \
delete p; \
p = nullptr; \
} \
#ifndef ERRORTYPE
#define ERRORTYPE
/**
* error info.
*/
enum {
FM_API_SUCCESS = 100,
FM_API_ERROR,
FM_API_TIMEOUT,
FM_API_BADJSON,
FM_API_NETWORERROR,
FM_API_SERVERERROR,
FM_API_WINDOWCLOSE
};
// 返回错误信息的json
#define ErrorMsgJson "{\"statusCode\":%1,\"msg\":\"%2\",\"prompt\":0}"
#define ErrorNeedPayCode "fmv:请使用支付码付款"
typedef std::map<const int, const char*> FMErrorMap;
const FMErrorMap::value_type fm_error_pairs[] =
{
FMErrorMap::value_type(FM_API_SUCCESS, "Success"),
FMErrorMap::value_type(FM_API_ERROR, "Error"),
FMErrorMap::value_type(FM_API_TIMEOUT, "Timeout"),
FMErrorMap::value_type(FM_API_BADJSON, "Invalid json data"),
FMErrorMap::value_type(FM_API_NETWORERROR, "Network error"),
FMErrorMap::value_type(FM_API_SERVERERROR, "Server error"),
FMErrorMap::value_type(FM_API_WINDOWCLOSE, "Window is closed")
};
const FMErrorMap fm_error(fm_error_pairs, fm_error_pairs + (sizeof fm_error_pairs / sizeof fm_error_pairs[0]));
#endif
#define AppDirPath qApp->applicationDirPath()
#define QuitCMD "{\"reqType\":-1}"
#endif // GLOBAL_H
<RCC>
<qresource prefix="/">
<file>img/account.png</file>
<file>img/alert_bg.png</file>
<file>img/btn_close.png</file>
<file>img/chk_checked.png</file>
<file>img/chk_unchecked.png</file>
<file>img/coupon_select.png</file>
<file>img/coupon_separator.png</file>
<file>img/FMVip.ico</file>
<file>img/img_logo.png</file>
<file>img/img_logo_today.png</file>
<file>img/loading.gif</file>
<file>img/tip_error.png</file>
<file>img/tip_ok.png</file>
<file>img/tip_warning.png</file>
</qresource>
</RCC>
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by fmproxy_service.rc
// ¶һĬֵ
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
#include "fmtask.h"
#include "fmnetwork.h"
#include <QDateTime>
#include <QSettings>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QCryptographicHash>
#include "fmp_vip_settings.h"
#define RunFunction(function) do { \
function##(); \
if(error() != FM_API_SUCCESS) { \
VIP_WARN() << QString("Task error %1: %2").arg(error()).arg(errorString()); \
return QString(ErrorMsgJson).arg(error()).arg(errorString()).toLatin1(); \
} \
} while(0);
FMTask::FMTask(QJsonObject &jsonObj, FM_TYPE fmType, Session *session, QObject *parent) :
QObject(parent),
posReqJsonObj(jsonObj),
_window(nullptr),
isCreator(false),
_FM_Type(fmType),
preTask(nullptr),
_error(FM_API_SUCCESS),
_errorMsg("")
{
if(session == 0) {
_session = new Session();
isCreator = true;
} else {
_session = session;
}
}
FMTask::~FMTask()
{
del_p(_window);
del_p(preTask);
if(isCreator) {
del_p(_session);
}
}
QByteArray FMTask::doTask()
{
VIP_DEBUG() << __FUNCTION__;
RunFunction(copyPros);
RunFunction(setWindow);
RunFunction(showWindow);
RunFunction(packagePOSRsp);
QJsonDocument json(posRspJsonObj);
return json.toJson(QJsonDocument::Compact);
}
void FMTask::stopTask()
{
VIP_DEBUG() << __FUNCTION__;
if(preTask != nullptr) {
preTask->stopTask();
}
if(_window != nullptr) {
_window->close();
_window = nullptr;
}
setError(FM_API_WINDOWCLOSE);
}
void FMTask::copyPros()
{
VIP_DEBUG() << __FUNCTION__;
for(int i=0; i<sizeof(DefaultProps)/sizeof(DefaultProps[0]); ++i) {
QString posPro = DefaultProps[i];
serverReqJsonObj[ServerProps(posPro)] = posReqJsonObj[posPro];
}
}
void FMTask::showWindow()
{
VIP_DEBUG() << __FUNCTION__;
QString sL[] = {
PosProps.OperatorId,
PosProps.BussinessDate,
};
for(int i=0; i<sizeof(sL)/sizeof(sL[0]); ++i) {
QString s = sL[i];
_session->addData(s, posReqJsonObj[s].toString());
}
if(_window != nullptr) {
_window->initWnd(this->session());
int ret = _window->exec();
if(ret == -1) {
setError(FM_API_WINDOWCLOSE);
}
}
}
bool FMTask::sendToServer(bool isShowMsg)
{
VIP_DEBUG() << __FUNCTION__;
// 固定部分
serverReqJsonObj[PosProps.AppId] = APP_ID;
serverReqJsonObj[PosProps.PartnerId] = PARTNER_ID;
serverReqJsonObj[PosProps.T] = QString::number(QDateTime::currentMSecsSinceEpoch());
serverReqJsonObj[ServerProps(PosProps.Fm_cmd)] = FM_Server_Type[FM_Type()];
packageServerReq();
QJsonDocument json(serverReqJsonObj);
QByteArray data = json.toJson(QJsonDocument::Compact);
url = QString("%1?sign=%2").arg(FMPVipSettings::instance()->getServerUrl()).arg(sign());
QByteArray rspData;
FMNetwork net;
net.send(url, data, rspData);
// 网络错误
if(net.error != FM_API_SUCCESS) {
setError(net.error, net.errorMsg);
} else {
QJsonParseError jsonErr;
QJsonDocument rspJson = QJsonDocument::fromJson(rspData, &jsonErr);
// Json错误
if(jsonErr.error != QJsonParseError::NoError) {
setError(FM_API_BADJSON);
} else {
serverRspJsonObj = rspJson.object();
// 服务器返回的错误
if(serverRspJsonObj.contains("errcode")) {
setError(FM_API_SERVERERROR, serverRspJsonObj["errcode"].toInt(), serverRspJsonObj["errmsg"].toString());
}
}
}
VIP_INFO() << "Server rsponse: " << serverRspJsonObj;
if(_window != nullptr) {
_window->setIsBusy(false);
}
bool isOk = (error() == FM_API_SUCCESS);
if(!isOk && isShowMsg)
{
FMMsgWnd::FailureWnd(errorString(), _window);
}
return isOk;
}
QJsonValue FMTask::searchJsonValue(QJsonObject &searchJson, QString searchKey)
{
if(searchJson.contains(searchKey)) {
return searchJson[searchKey];
} else {
foreach(QString key , searchJson.keys()) {
if(searchJson[key].isObject()) {
QJsonObject ob = searchJson[key].toObject();
QJsonValue value = searchJsonValue(ob, searchKey);
if(!value.isNull()){
return value;
}
}
}
}
return QJsonValue();
}
QJsonValue FMTask::getServerJsonValue(const QString prop)
{
return searchJsonValue(serverRspJsonObj, ServerProps(prop));
}
QJsonValue FMTask::getPosJsonValue(const QString prop)
{
return searchJsonValue(posReqJsonObj, prop);
}
QString FMTask::sign() const
{
VIP_DEBUG() << __FUNCTION__;
// 解析JSON插入MAP中按字典排序
QMap<QString, QString> mapData;
for(int i=0; i<sizeof(SignProps)/sizeof(SignProps[0]); ++i) {
QString word = SignProps[i];
if(serverReqJsonObj[word].isDouble()) {
mapData[word] = QString::number(serverReqJsonObj[word].toDouble());
} else {
mapData[word] = serverReqJsonObj[word].toString();
}
}
if (serverRspJsonObj[ServerProps(PosProps.Fm_cmd)].toInt() == FM_Server_Type[FM_Fund]) {
mapData[ServerProps(PosProps.TransId)] = serverReqJsonObj[ServerProps(PosProps.TransId)].toString();
}
// 使用URL键值对的格式拼接
QString sb = "";
foreach(QString key , mapData.keys())
{
sb += (key + "=" + mapData.value(key) + "&");
}
sb.remove(sb.length() - 1, 1); // 去掉最后一个&
sb.append(KEY_CODE);
QByteArray bt;
bt.append(sb);
VIP_INFO() << "Sign String: " << bt;
QByteArray md5Bt = QCryptographicHash::hash(bt, QCryptographicHash::Md5);
return md5Bt.toHex();
}
#ifndef FMTASK_H
#define FMTASK_H
#include "fmvipwnd.h"
#include "fmmsgwnd.h"
#include "session.h"
#include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
class FMTask : public QObject
{
Q_OBJECT
public:
explicit FMTask(QJsonObject &jsonObj, FM_TYPE fmType, Session *session = 0, QObject *parent = 0);
~FMTask();
virtual QByteArray doTask();
virtual void stopTask();
void setFM_Type(const FM_TYPE fmType) {_FM_Type = fmType;}
FM_TYPE FM_Type() const { return _FM_Type;}
Session* session() const {return _session;}
QJsonValue searchJsonValue(QJsonObject &searchJson, QString searchKey);
QJsonValue getServerJsonValue(const QString prop);
QJsonValue getPosJsonValue(const QString prop);
protected:
// 从配置文件中拷贝数据信息
void copyPros();
virtual void setWindow(){}
virtual void showWindow();
virtual void packageServerReq() = 0;
virtual bool sendToServer(bool isShowMsg = true);
virtual void packagePOSRsp() = 0;
protected:
QJsonObject posReqJsonObj;
QJsonObject posRspJsonObj;
QJsonObject serverReqJsonObj;
QJsonObject serverRspJsonObj;
FMVipWnd *_window;
Session *_session;
bool isCreator;
FM_TYPE _FM_Type;
QString url;
FMTask *preTask;
private:
QString sign() const;
/**
* @brief FMError
* define error.
*/
typedef int FMError;
public:
FMError error() const {return _error;}
void setError(const FMError error)
{ _error = error; _errorMsg = "";}
void setError(const FMError error, const QString errorMsg)
{ _error = error; _errorMsg = errorMsg;}
void setError(const FMError error, const int errorCode, const QString errorMsg)
{ _error = error; _errorMsg = QString("[%1]%2").arg(errorCode).arg(errorMsg);}
QString errorString() {
if(fm_error.find(_error) == fm_error.end()) {
return "Undefine Error";
} else {
if(_errorMsg != "")
return _errorMsg;
return fm_error.at(_error);
}
}
private:
FMError _error;
QString _errorMsg;
};
#endif // FMTASK_H
#include "fmtasknownd.h"
#include "fmp_vip_settings.h"
#include <QJsonDocument>
FMTaskNoWnd::FMTaskNoWnd(QJsonObject &jsonObj, FM_TYPE fmType, Session *session, QObject *parent) :
FMTask(jsonObj, fmType, session, parent)
{
}
QByteArray FMTaskNoWnd::doTask()
{
// void (FMTaskNoWnd::*runFuns[])() = {
// copyPros,
// sendToServer,
// packagePOSRsp
// };
// int index = 0;
// for (void(FMTaskNoWnd::*fun)() : runFuns) {
// (this->*fun)();
// qDebug() << "Run over function: " << index++;
// if(error() != FM_API_SUCCESS) {
// qDebug() << QString("Task error %1: %2").arg(error()).arg(errorString());
// return QString(ErrorMsgJson).arg(error()).arg(errorString()).toLatin1();
// }
// }
copyPros();
bool isOk = sendToServer();
if(!isOk) {
VIP_WARN() << QString("Task error %1: %2").arg(error()).arg(errorString());
return QString(ErrorMsgJson).arg(error()).arg(errorString()).toLatin1();
}
packagePOSRsp();
QJsonDocument json(posRspJsonObj);
return json.toJson(QJsonDocument::Compact);
}
#ifndef FMTASKNOWND_H
#define FMTASKNOWND_H
#include "fmtask.h"
class FMTaskNoWnd : public FMTask
{
Q_OBJECT
public:
explicit FMTaskNoWnd(QJsonObject &jsonObj, FM_TYPE fmType, Session* session = 0, QObject *parent = 0);
virtual QByteArray doTask();
protected:
virtual void packageServerReq() = 0;
virtual void packagePOSRsp() = 0;
};
#endif // FMTASKNOWND_H
#include "session.h"
#include <QDebug>
Session::Session()
{
}
Session::~Session()
{
}
QVariant Session::data(const QString key) const
{
QVariant value;
if (_sessionDataMap.contains(key)) {
value = _sessionDataMap[key];
}
return value;
}
void Session::addData(const QString key, const QVariant value)
{
_sessionDataMap[key] = value;
}
void Session::addData(const QString key, const QMap<QString, Coupon> couponMap)
{
QVariantMap v_couponMap;
foreach(const Coupon coupon , couponMap) {
QVariant v;
v.setValue(coupon);
v_couponMap[coupon.code] = v;
}
addData(key, v_couponMap);
}
QMap<QString, Coupon> Session::getCouponMap(const QString key)
{
QVariantMap v_couponMap = data(key).toMap();
QMap<QString, Coupon> couponMap;
foreach(const QVariant v_coupon , v_couponMap) {
Coupon coupon = v_coupon.value<Coupon>();
couponMap[coupon.code] = coupon;
}
return couponMap;
}
#ifndef SESSION_H
#define SESSION_H
#include <QVariant>
#include "global.h"
// 代金券结构体
struct Coupon
{
Coupon() {
code = "";
disAmount = 0.0;
desc = "";
}
Coupon(const Coupon& C) {
code = C.code;
disAmount = C.disAmount;
desc = C.desc;
}
Coupon(const QString &c, const double amount, const QString &d) {
code = c;
disAmount = amount;
desc = d;
}
QString code;
double disAmount;
QString desc;
};
Q_DECLARE_METATYPE(Coupon) // 使Coupon类型可以和QVariant类型互相转换
class Session
{
public:
Session();
Session(const Session& other) {
this->_sessionDataMap = other.sessionDataMap();
}
~Session();
Session &operator =(const Session& other) {
this->_sessionDataMap = other.sessionDataMap();
return *this;
}
QVariant data(const QString key) const;
void addData(const QString key, const QVariant value);
void addData(const QString key, const QMap<QString, Coupon> couponMap);
QMap<QString, Coupon> getCouponMap(const QString key);
QMap<QString, QVariant> sessionDataMap() const { return this->_sessionDataMap;}
void setSessionDataMap(const QMap<QString, QVariant> &dataMap) {this->_sessionDataMap = dataMap;}
private:
QMap<QString, QVariant> _sessionDataMap;
};
#endif // SESSION_H
#include "taskfactory.h"
#include "tasklogin.h"
#include "taskpay.h"
#include "taskfund.h"
#include "taskfinal.h"
#include "taskothers.h"
#include "global.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QDebug>
TaskFactory::TaskFactory(QObject *parent) : QObject(parent)
{
}
FMTask* TaskFactory::Task(QByteArray data)
{
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(data, &error);
QJsonObject jsonObj = doc.object();
FMTask* task = nullptr;
FM_TYPE type = (FM_TYPE)FM_Type_List.indexOf(jsonObj["fm_cmd"].toString());
switch (type) {
case FM_Login: {
task = new TaskLogin(jsonObj);
break;
}
case FM_Fund: {
task = new TaskFund(jsonObj);
break;
}
case FM_Pay: {
task = new TaskPay(jsonObj);
break;
}
case FM_Final: {
task = new TaskFinal(jsonObj);
break;
}
case FM_Coupon: {
task = new TaskCoupon(jsonObj);
break;
}
case FM_Order_Refund: {
task = new TaskRefundOrder(jsonObj);
break;
}
case FM_Order_Revoke: {
task = new TaskRefundPay(jsonObj);
break;
}
case FM_Charge_Refund: {
task = new TaskRefundOrder(jsonObj);
break;
}
default:
break;
}
return task;
}
#ifndef TASKFACTORY_H
#define TASKFACTORY_H
#include <QObject>
#include "fmtask.h"
class TaskFactory : public QObject
{
Q_OBJECT
public:
explicit TaskFactory(QObject *parent = 0);
static FMTask* Task(QByteArray data);
};
#endif // TASKFACTORY_H
#include "taskfinal.h"
#include "fmbackup.h"
#include <QDateTime>
#include <QJsonDocument>
TaskFinal::TaskFinal(QJsonObject &jsonObj, QObject *parent)
:FMTaskNoWnd(jsonObj, FM_Final, 0, parent)
{
}
void TaskFinal::packageServerReq()
{
std::vector<QString> p1;
p1.push_back(PosProps.Fm_id);
p1.push_back(PosProps.TransId);
foreach (auto prop , p1) {
serverRspJsonObj[ServerProps(prop)] = getPosJsonValue(prop);
}
QJsonObject trans;
std::vector<QString> p2;
p2.push_back(PosProps.Fm_open_id);
p2.push_back(PosProps.OrderAmount);
p2.push_back(PosProps.PaidAmount);
foreach (auto prop , p2) {
trans[ServerProps(prop)] = getPosJsonValue(prop);
}
QJsonArray coupons = getPosJsonValue(PosProps.Coupons).toArray();
// 储值金、积分、第三方、代金券
int codeAmount=0, scoreAmount=0, cashAmount=0, thirdAmount=0;
trans["thirdPayType"] = 4;
foreach(auto pay_v , getPosJsonValue(PosProps.Pay_ids).toArray())
{
QJsonObject pay_ob = pay_v.toObject();
QString type = pay_ob[PosProps.Pay_id].toString();
if(type == "24") {
codeAmount = pay_ob[PosProps.Paid_total_amount].toInt();
} else if(type == "25") {
scoreAmount = pay_ob[PosProps.Paid_total_amount].toInt();
} else if(type == "77") { // 代金券
coupons.append(pay_ob[PosProps.Coupon_code].toString());
} else if(type == "72" || type == "73") {
thirdAmount = pay_ob[PosProps.Paid_total_amount].toInt();
trans[ServerProps(PosProps.Pay_transId)] = pay_ob[PosProps.Pay_transId];
if (type == "72") { // 支付宝
trans["thirdPayType"] = 1;
} else if(type == "73") { // 微信
trans["thirdPayType"] = 2;
}
}
}
trans[ServerProps(PosProps.Coupons)] = coupons;
cashAmount = getPosJsonValue(PosProps.PaidAmount).toInt() - codeAmount -scoreAmount - thirdAmount;
trans[ServerProps(PosProps.CodeAmount)] = codeAmount;
trans[ServerProps(PosProps.ScoreAmount)] = scoreAmount;
trans[ServerProps(PosProps.CashAmount)] = cashAmount;
trans[ServerProps(PosProps.ThirdAmount)] = thirdAmount;
// 产品列表
QJsonArray propducts;
foreach(auto pValue , getPosJsonValue(PosProps.Products).toArray())
{
auto po = pValue.toObject();
QJsonObject spo;
std::vector<QString> p;
p.push_back(PosProps.ConsumeNum);
p.push_back(PosProps.Price);
p.push_back(PosProps.ProductId);
foreach(auto prop , p) {
spo[ServerProps(prop)] = po[prop];
}
propducts.append(spo);
}
trans[ServerProps(PosProps.Products)] = propducts;
serverReqJsonObj[ServerProps(PosProps.Transaction)] = trans;
}
bool TaskFinal::sendToServer(bool isShowMsg)
{
Q_UNUSED(isShowMsg);
FMTask::sendToServer(false);
// 备份
if(error() == FM_API_NETWORERROR) {
if(searchJsonValue(serverReqJsonObj,ServerProps(PosProps.CodeAmount)).toInt() == 0 &&
searchJsonValue(serverReqJsonObj,ServerProps(PosProps.ScoreAmount)).toInt() == 0 &&
searchJsonValue(serverReqJsonObj,ServerProps(PosProps.Coupons)).toArray().isEmpty()) {
QString fm_id = backup();
if(!fm_id.isEmpty()){
setError(FM_API_SUCCESS);
serverRspJsonObj[ServerProps(PosProps.StatusCode)] = FM_API_SUCCESS;
serverRspJsonObj[ServerProps(PosProps.Msg)] = QString::fromLocal8Bit("结算成功");
serverRspJsonObj[ServerProps(PosProps.Fm_id)] = fm_id;
serverRspJsonObj[ServerProps(PosProps.Prompt)] = 1;
serverRspJsonObj[ServerProps(PosProps.Print1)] = "";
serverRspJsonObj[ServerProps(PosProps.Print2)] = "";
}
}
}
bool isOk = (error() == FM_API_SUCCESS);
if(!isOk)
{
FMMsgWnd::FailureWnd(errorString(), _window);
}
return isOk;
}
void TaskFinal::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
p.push_back(PosProps.Fm_id);
p.push_back(PosProps.Print1);
p.push_back(PosProps.Print2);
foreach(auto prop , p)
{
posRspJsonObj[prop] = getServerJsonValue(prop);
}
posRspJsonObj[PosProps.Prompt] = 1;
}
QString TaskFinal::backup()
{
int newId = FMBackup::instance()->insertNewRow();
QString uuid = QString("E%1%2%3%4")
.arg(getPosJsonValue(PosProps.StoreId).toString())
.arg(getPosJsonValue(PosProps.PosId).toString().toInt(), 2, 10, QChar('0'))
.arg(QDateTime::currentDateTime().toString("yyMMdd"))
.arg(newId, 5, 10, QChar('0'));
QJsonDocument json(serverReqJsonObj);
bool isOk = FMBackup::instance()->updateReqData(newId, this->url, json.toJson(QJsonDocument::Compact));
if(isOk && uuid.length()==20) {
return uuid;
}
return "";
}
#ifndef TASKFINAL_H
#define TASKFINAL_H
#include "fmtasknownd.h"
class TaskFinal : public FMTaskNoWnd
{
Q_OBJECT
public:
explicit TaskFinal(QJsonObject &jsonObj, QObject* parent=0);
void packageServerReq();
bool sendToServer(bool isShowMsg);
void packagePOSRsp();
private:
QString backup();
};
#endif // TASKFINAL_H
#include "taskfund.h"
#include "fmvipfund.h"
#include "tasklogin.h"
TaskFund::TaskFund(QJsonObject &jsonObj, QObject *parent)
:FMTask(jsonObj, FM_Fund, 0, parent)
{
}
QByteArray TaskFund::doTask()
{
preTask = new TaskLogin(posReqJsonObj, _session, this);
preTask->session()->addData(PosProps.FM_Type, FM_Fund);
QByteArray loginRst = preTask->doTask();
if(preTask->error() != FM_API_SUCCESS) {
return loginRst;
}
return FMTask::doTask();
}
void TaskFund::setWindow()
{
_window = new FMVipFund;
connect(qobject_cast<FMVipFund*>(_window), SIGNAL(fund()), this, SLOT(onFund()));
session()->addData(PosProps.ChargeAmount, getPosJsonValue(PosProps.ChargeAmount));
}
void TaskFund::packageServerReq()
{
serverReqJsonObj[ServerProps(PosProps.TransId)] = getPosJsonValue(PosProps.TransId);
QJsonObject trans;
trans[ServerProps(PosProps.Fm_open_id)] = session()->data(PosProps.Fm_open_id).toString();
trans[ServerProps(PosProps.ChargeAmount)] = session()->data(PosProps.ChargeAmount).toInt();
trans[ServerProps(PosProps.CashAmount)] = session()->data(PosProps.ChargeAmount).toInt();
serverReqJsonObj[ServerProps(PosProps.Transaction)] = trans;
}
void TaskFund::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
p.push_back(PosProps.Fm_id);
p.push_back(PosProps.Print);
foreach (QString prop , p) {
posRspJsonObj[prop] = getServerJsonValue(prop);
}
posRspJsonObj[PosProps.Prompt] = 1;
posRspJsonObj[PosProps.Fm_open_id] = session()->data(PosProps.Fm_open_id).toString();
}
void TaskFund::onFund()
{
sendToServer();
_window->close();
}
#ifndef TASKFUND_H
#define TASKFUND_H
#include "fmtask.h"
class TaskFund : public FMTask
{
Q_OBJECT
public:
explicit TaskFund(QJsonObject &jsonObj, QObject* parent=0);
QByteArray doTask();
void setWindow();
void packageServerReq();
void packagePOSRsp();
private slots:
void onFund();
};
#endif // TASKFUND_H
#include "tasklogin.h"
#include "fmviplogin.h"
#include "fmp_vip_settings.h"
TaskLogin::TaskLogin(QJsonObject &jsonObj, Session *session, QObject *parent)
:FMTask(jsonObj, FM_Login, session, parent)
{
}
void TaskLogin::setWindow()
{
_window = new FMVipLogin;
connect(qobject_cast<FMVipLogin*>(_window), &FMVipLogin::login, this, &TaskLogin::onLogin);
}
void TaskLogin::packageServerReq()
{
serverReqJsonObj[ServerProps(PosProps.Member_sign)] = _session->data(PosProps.Member_sign).toString();
}
void TaskLogin::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
p.push_back(PosProps.Fm_open_id);
foreach (QString prop , p) {
posRspJsonObj[prop] = getServerJsonValue(prop);
}
posRspJsonObj[PosProps.Prompt] = 0;
}
void TaskLogin::onLogin()
{
bool isOk = sendToServer();
if(!isOk) {
if(_window != nullptr) {
_window->close();
}
return;
}
// 认证失败
if(getServerJsonValue(PosProps.StatusCode).toInt() != FM_API_SUCCESS) {
QString info = serverRspJsonObj[ServerProps(PosProps.Msg)].toString();
VIP_WARN() << "Login failed: " << info;
FMMsgWnd::FailureWnd(info, _window);
}
// 认证成功但限制用支付码
// else if((session()->data(PosProps.FM_Type).toInt() == FM_Pay) &&
// (getServerJsonValue(PosProps.CanPay).toInt() != 1)) {
// VIP_WARN() << ErrorNeedPayCode;
// FMMsgWnd::FailureWnd(ErrorNeedPayCode);
// }
// 认证成功
else {
QString account = getServerJsonValue(PosProps.Fm_open_id).toString();
QString birthday = getServerJsonValue(PosProps.Birthday).toString();
QString name = getServerJsonValue(PosProps.Name).toString();
if(session()->data(PosProps.FM_Type).toInt() == FM_Login) {
FMMsgWnd::LoginSuccess(account,name,birthday, _window);
} else {
session()->addData(PosProps.Name, name);
session()->addData(PosProps.Amount, getServerJsonValue(PosProps.Amount).toInt());
session()->addData(PosProps.Birthday, birthday);
session()->addData(PosProps.Mobile, getServerJsonValue(PosProps.Mobile).toString());
session()->addData(PosProps.Fm_open_id, account);
session()->addData(PosProps.Score, getServerJsonValue(PosProps.Score).toInt());
QMap<QString, QVariant> couponMap;
foreach (auto value , getServerJsonValue(PosProps.CouponList).toArray())
{
QJsonObject couponOb = value.toObject();
QString code = couponOb[ServerProps(PosProps.Coupon_code)].toString();
double amount = couponOb[ServerProps(PosProps.Coupon_disAmount)].toInt() / 100.0;
QString desc = couponOb[ServerProps(PosProps.Coupon_desc)].toString();
Coupon c(code, amount, desc);
QVariant v;
v.setValue(c);
couponMap[code] = v;
}
session()->addData(PosProps.CouponMap, couponMap);
}
_window->close();
}
if(_window!=nullptr) {
_window->resetWnd();
}
}
#ifndef TASKLOGIN_H
#define TASKLOGIN_H
#include "fmtask.h"
class TaskLogin : public FMTask
{
Q_OBJECT
public:
explicit TaskLogin(QJsonObject &jsonObj, Session* session = 0, QObject* parent=0);
private:
void setWindow() override;
void packageServerReq();
void packagePOSRsp();
public slots:
void onLogin();
};
#endif // TASKLOGIN_H
#include "taskothers.h"
TaskCoupon::TaskCoupon(QJsonObject &jsonObj, QObject *parent)
:FMTaskNoWnd(jsonObj, FM_Coupon, 0, parent)
{
}
void TaskCoupon::packageServerReq()
{
serverReqJsonObj[ServerProps(PosProps.Coupon)] = getPosJsonValue(PosProps.Coupon);
}
void TaskCoupon::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.Fm_open_id);
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
foreach(auto prop , p) {
posRspJsonObj[prop] = getServerJsonValue(ServerProps(prop));
}
posRspJsonObj["pid"] = serverRspJsonObj["productCode"];
posRspJsonObj[PosProps.Prompt] = 1;
}
TaskRefundPay::TaskRefundPay(QJsonObject &jsonObj, QObject *parent)
:FMTaskNoWnd(jsonObj, FM_Order_Revoke, 0, parent)
{
}
void TaskRefundPay::packageServerReq()
{
serverReqJsonObj[ServerProps(PosProps.TransId)] = getPosJsonValue(PosProps.TransId);
}
void TaskRefundPay::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
foreach(auto prop , p) {
posRspJsonObj[prop] = getServerJsonValue(ServerProps(prop));
}
posRspJsonObj[PosProps.Prompt] = 1;
}
TaskRefundOrder::TaskRefundOrder(QJsonObject &jsonObj, QObject *parent)
:FMTaskNoWnd(jsonObj, FM_Order_Refund, 0, parent)
{
}
void TaskRefundOrder::packageServerReq()
{
QJsonObject trans;
trans[ServerProps(PosProps.Fm_id)] = getPosJsonValue(PosProps.Fm_id);
serverReqJsonObj[ServerProps(PosProps.Transaction)] = trans;
}
void TaskRefundOrder::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
foreach(auto prop , p) {
posRspJsonObj[prop] = getServerJsonValue(ServerProps(prop));
}
posRspJsonObj[PosProps.Prompt] = 1;
}
#ifndef TASKOTHERS_H
#define TASKOTHERS_H
#include "fmtasknownd.h"
// 优惠券查询
class TaskCoupon : public FMTaskNoWnd
{
Q_OBJECT
public:
explicit TaskCoupon(QJsonObject &jsonObj, QObject *parent = 0);
void packageServerReq();
void packagePOSRsp();
};
// 支付退款
class TaskRefundPay : public FMTaskNoWnd
{
Q_OBJECT
public:
explicit TaskRefundPay(QJsonObject &jsonObj, QObject *parent = 0);
void packageServerReq();
void packagePOSRsp();
};
// 整单退款
class TaskRefundOrder : public FMTaskNoWnd
{
Q_OBJECT
public:
explicit TaskRefundOrder(QJsonObject &jsonObj, QObject *parent = 0);
void packageServerReq();
void packagePOSRsp();
};
#endif // TASKOTHERS_H
#include "taskpay.h"
#include "fmviporder.h"
#include "tasklogin.h"
TaskPay::TaskPay(QJsonObject &jsonObj, QObject *parent)
:FMTask(jsonObj, FM_Pay, 0, parent)
{
}
QByteArray TaskPay::doTask()
{
preTask = new TaskLogin(posReqJsonObj, _session, this);
preTask->session()->addData(PosProps.FM_Type, FM_Pay);
QByteArray loginRst = preTask->doTask();
if(preTask->error() != FM_API_SUCCESS) {
return loginRst;
}
this->_session = preTask->session();
return FMTask::doTask();
}
void TaskPay::setWindow()
{
_window = new FMVipOrder;
std::vector<QString> p;
p.push_back(PosProps.OrderAmount);
p.push_back(PosProps.PaidAmount);
p.push_back(PosProps.StandardAmount);
foreach (QString prop , p) {
session()->addData(prop, getPosJsonValue(prop).toInt());
}
connect(qobject_cast<FMVipOrder*>(_window), SIGNAL(pay()), this, SLOT(onPay()));
}
void TaskPay::packageServerReq()
{
QJsonObject transObj;
transObj[ServerProps(PosProps.Fm_open_id)] = session()->data(PosProps.Fm_open_id).toString();
transObj[ServerProps(PosProps.CodeAmount)] = session()->data(PosProps.CodeAmount).toInt();
transObj[ServerProps(PosProps.IsUseScore)] = session()->data(PosProps.IsUseScore).toInt();
QJsonArray couponArr;
foreach (auto code , session()->data(PosProps.CouponMap).toMap().keys())
{
couponArr.append(code);
}
transObj[ServerProps(PosProps.Coupons)] = couponArr;
serverReqJsonObj[ServerProps(PosProps.Transaction)] = transObj;
serverReqJsonObj[ServerProps(PosProps.TransId)] = getPosJsonValue(PosProps.TransId);
}
void TaskPay::packagePOSRsp()
{
std::vector<QString> p;
p.push_back(PosProps.StatusCode);
p.push_back(PosProps.Msg);
p.push_back(PosProps.Fm_id);
foreach (QString prop , p) {
posRspJsonObj[prop] = getServerJsonValue(prop);
}
posRspJsonObj[PosProps.Prompt] = 1;
posRspJsonObj[PosProps.Fm_open_id] = session()->data(PosProps.Fm_open_id).toString();
QJsonArray pay_ids;
QJsonObject pay_id;
pay_id[PosProps.Pay_id] = "24";
pay_id[PosProps.Pay_str] = QString::fromLocal8Bit("会员储值金支付");
pay_id[PosProps.Paid_total_amount] = getServerJsonValue(PosProps.CodeAmount);
pay_ids.append(pay_id);
pay_id[PosProps.Pay_id] = "25";
pay_id[PosProps.Pay_str] = QString::fromLocal8Bit("会员积分支付");
pay_id[PosProps.Paid_total_amount] = getServerJsonValue(PosProps.ScoreAmount);
pay_ids.append(pay_id);
foreach(auto coupon , getServerJsonValue(PosProps.Coupons).toArray()) {
QJsonObject cp = coupon.toObject();
pay_id[PosProps.Pay_id] = "77";
pay_id[PosProps.Pay_str] = QString::fromLocal8Bit("代金券支付");
pay_id[PosProps.Paid_total_amount] = cp[PosProps.Coupon_disAmount];
pay_id[PosProps.Coupon_code] = cp[ServerProps(PosProps.Coupon_code)];
pay_ids.append(pay_id);
}
posRspJsonObj[PosProps.Pay_id] = pay_ids;
posRspJsonObj["forward"] = posReqJsonObj["forward"];
}
void TaskPay::onPay()
{
sendToServer();
_window->close();
}
#ifndef TASKPAY_H
#define TASKPAY_H
#include "fmtask.h"
class TaskPay : public FMTask
{
Q_OBJECT
public:
explicit TaskPay(QJsonObject &jsonObj, QObject* parent=0);
QByteArray doTask();
void setWindow();
void packageServerReq();
void packagePOSRsp();
private slots:
void onPay();
};
#endif // TASKPAY_H
#include "fmcouponwidget.h"
#include "ui_fmcouponwidget.h"
#include <QPainter>
FMCouponWidget::FMCouponWidget(Coupon conpon, QWidget *parent) :
QWidget(parent),
ui(new Ui::FMCouponWidget)
{
ui->setupUi(this);
ui->code_lab->setText(conpon.code);
ui->amount_lab->setText(QString::number(conpon.disAmount, 'f', 2));
ui->desc_lab->setText(conpon.desc);
}
FMCouponWidget::~FMCouponWidget()
{
delete ui;
}
void FMCouponWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
#ifndef FMCOUPONWIDGET_H
#define FMCOUPONWIDGET_H
#include <QWidget>
#include "session.h"
namespace Ui {
class FMCouponWidget;
}
class FMCouponWidget : public QWidget
{
Q_OBJECT
public:
explicit FMCouponWidget(Coupon conpon, QWidget *parent = 0);
~FMCouponWidget();
void paintEvent(QPaintEvent *event);
private:
Ui::FMCouponWidget *ui;
};
#endif // FMCOUPONWIDGET_H
#include "fmloading.h"
#include "ui_fmloading.h"
#include <QDebug>
FMLoading::FMLoading(QDialog *parent) :
QDialog(parent),
ui(new Ui::FMLoading)
{
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_TranslucentBackground, true);
movie = new QMovie(":/img/loading.gif");
movie->start();
connect(movie, SIGNAL(finished()), movie, SLOT(start()));
ui->loading_lbl->setMovie(movie);
}
FMLoading::~FMLoading()
{
if(movie != NULL) {
delete movie;
movie = NULL;
}
delete ui;
}
#ifndef FMLOADING_H
#define FMLOADING_H
#include <QDialog>
#include <QMovie>
namespace Ui {
class FMLoading;
}
class FMLoading : public QDialog
{
Q_OBJECT
public:
explicit FMLoading(QDialog *parent = 0);
~FMLoading();
private:
Ui::FMLoading *ui;
QMovie *movie;
};
#endif // FMLOADING_H
#include "fmmsgwnd.h"
#include "ui_fmmsgwnd.h"
#include <QDebug>
FMMsgWnd::FMMsgWnd(QDialog *parent) :
QDialog(parent),
ui(new Ui::FMMsgWnd)
{
ui->setupUi(this);
setAttribute(Qt::WA_TranslucentBackground);
this->setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
}
FMMsgWnd::~FMMsgWnd()
{
delete ui;
}
void FMMsgWnd::show(InfoType type, const QString &info)
{
QString iconUrl;
switch (type) {
case InfoType::T_Normal:
iconUrl = "";
break;
case InfoType::T_Success:
iconUrl = ":/tip_ok.png";
break;
case InfoType::T_Failure:
iconUrl = ":/tip_error.png";
break;
case InfoType::T_Warning:
iconUrl = ":/tip_warning.png";
break;
case InfoType::T_LoginSuccess:
ui->label_msg->setText(QString::fromLocal8Bit("会员认证成功"));
iconUrl = ":/tip_ok.png";
break;
default:
iconUrl = "";
break;
}
if(iconUrl != ""){
QPixmap icon(iconUrl);
ui->label_logo->setPixmap(icon);
}
ui->label_msg->setText(info);
QDialog::exec();
}
void FMMsgWnd::FailureWnd(const QString &info, QDialog *parent)
{
FMMsgWnd window(parent);
window.setGeometry(parent->geometry());
window.show(FMMsgWnd::T_Failure, info);
}
void FMMsgWnd::WarningWnd(const QString &info, QDialog *parent)
{
FMMsgWnd window(parent);
window.setGeometry(parent->geometry());
window.show(FMMsgWnd::T_Warning, info);
}
void FMMsgWnd::SuccessWnd(const QString &info, QDialog *parent)
{
FMMsgWnd window(parent);
window.setGeometry(parent->geometry());
window.show(FMMsgWnd::T_Success, info);
}
void FMMsgWnd::LoginSuccess(const QString &account, const QString &name, const QString &birthday, QDialog *parent)
{
FMMsgWnd window(parent);
window.setGeometry(parent->geometry());
QString info = QString::fromLocal8Bit("账号:%1\n姓名:%2\n生日:%3").arg(account).arg(name).arg(birthday);
window.show(FMMsgWnd::T_LoginSuccess, info);
}
void FMMsgWnd::on_btn_confirm_clicked()
{
this->close();
}
#ifndef FMMSGWND_H
#define FMMSGWND_H
#include "fmvipwnd.h"
namespace Ui {
class FMMsgWnd;
}
class FMMsgWnd : public QDialog
{
Q_OBJECT
public:
explicit FMMsgWnd(QDialog *parent = 0);
~FMMsgWnd();
enum InfoType
{
T_Normal,
T_Success,
T_Failure,
T_Warning,
T_LoginSuccess
};
void show(InfoType type = T_Normal, const QString &info = "");
static void FailureWnd(const QString &info, QDialog *parent=0);
static void WarningWnd(const QString &info, QDialog *parent=0);
static void SuccessWnd(const QString &info, QDialog *parent=0);
static void LoginSuccess(const QString &account, const QString &name, const QString &birthday, QDialog *parent=0);
private slots:
void on_btn_confirm_clicked();
private:
Ui::FMMsgWnd *ui;
};
#endif // FMMSGWND_H
#include "fmvipfund.h"
//#include "fmvipforward.h"
#include "ui_fmvipfund.h"
FMVipFund::FMVipFund(QDialog *parent) :
FMVipWnd(parent),
ui(new Ui::FMVipFund)
{
ui->setupUi(this);
}
FMVipFund::~FMVipFund()
{
delete ui;
}
void FMVipFund::initWnd(Session *session)
{
_session = session;
QString operator_id = session->data(PosProps.OperatorId).toString();
QString business_date = session->data(PosProps.BussinessDate).toString();
QString account = session->data(PosProps.Fm_open_id).toString();
QString name = session->data(PosProps.Name).toString();
double amount = session->data(PosProps.Amount).toInt() / 100.0;
double charge_amount = session->data(PosProps.ChargeAmount).toInt() / 100.0;
QString show_amount_str = QString::number(amount, 'f', 2);
QString show_charge_amount_str = QString::number(charge_amount, 'f', 2);
ui->store_label->setText(session->data(PosProps.StoreId).toString());
ui->pos_label->setText(session->data(PosProps.PosId).toString());
ui->operator_label->setText(operator_id);
ui->bd_label->setText(business_date);
ui->id_label->setText(account);
ui->balance_label->setText(show_amount_str);
ui->amount_edit->setText(show_charge_amount_str);
ui->name_label->setText(name);
ui->fund_btn->setFocus();
}
void FMVipFund::on_fund_btn_clicked()
{
int fundAmount = ui->amount_edit->text().toDouble() * 100;
_session->addData(PosProps.ChargeAmount, fundAmount);
this->setEnabled(false);
setIsBusy(true);
emit fund();
}
#ifndef FMVIPFUND_H
#define FMVIPFUND_H
#include "fmvipwnd.h"
namespace Ui {
class FMVipFund;
}
class FMVipFund : public FMVipWnd
{
Q_OBJECT
public:
explicit FMVipFund(QDialog *parent = 0);
~FMVipFund();
void initWnd(Session *session);
signals:
void fund();
public slots:
void on_fund_btn_clicked();
private:
Ui::FMVipFund *ui;
};
#endif // FMVIPFUND_H
#include "fmviplogin.h"
#include "ui_fmviplogin.h"
#include "fmvippanel.h"
#include <QFile>
#include <QMutex>
#include "fmloading.h"
FMVipLogin::FMVipLogin(QDialog *parent) :
FMVipWnd(parent),
ui(new Ui::FMVipLogin)
{
ui->setupUi(this);
}
FMVipLogin::~FMVipLogin()
{
delete ui;
}
void FMVipLogin::initWnd(Session *session)
{
this->_session = session;
QString placeText;
if(session->data(PosProps.FM_Type).toInt() == FM_Pay) {
placeText = QString::fromLocal8Bit("输入支付码");
} else {
placeText = QString::fromLocal8Bit("输入手机号/会员码/支付码");
}
ui->store_label->setText(session->data(PosProps.StoreId).toString());
ui->pos_label->setText(session->data(PosProps.PosId).toString());
ui->operator_label->setText(session->data(PosProps.OperatorId).toString());
ui->bd_label->setText(session->data(PosProps.BussinessDate).toString());
ui->login_edit->setPlaceholderText(placeText);
}
QString FMVipLogin::getVersionInfo()
{
QByteArray versionInfo;
QFile versionFile(qApp->applicationDirPath() + "/version.dat");
bool isOk = versionFile.open(QIODevice::ReadOnly);
if(isOk) {
versionInfo = versionFile.readAll();
} else {
versionInfo = QString::fromLocal8Bit("未知").toUtf8();
}
versionFile.close();
return versionInfo;
}
void FMVipLogin::on_login_btn_clicked()
{
QString id = ui->login_edit->text();
_session->addData(PosProps.Member_sign, id);
this->setEnabled(false);
setIsBusy(true);
emit login();
}
void FMVipLogin::resetWnd()
{
this->setEnabled(true);
ui->login_edit->clear();
ui->login_edit->setFocus();
}
#ifndef FMVIPLOGIN_H
#define FMVIPLOGIN_H
#include "fmvipwnd.h"
class QNetworkReply;
namespace Ui {
class FMVipLogin;
}
class FMVipLogin : public FMVipWnd
{
Q_OBJECT
public:
explicit FMVipLogin(QDialog *parent = 0);
~FMVipLogin();
QString getVersionInfo();
void initWnd(Session *session);
protected:
void resetWnd();
signals:
void login();
public slots:
void on_login_btn_clicked();
private:
Ui::FMVipLogin *ui;
};
#endif // FMVIPLOGIN_H
#include "fmviporder.h"
#include "fmmsgwnd.h"
#include "fmcouponwidget.h"
#include "ui_fmviporder.h"
#include <QScrollBar>
FMVipOrder::FMVipOrder(QDialog *parent) :
FMVipWnd(parent),
ui(new Ui::FMVipOrder)
{
ui->setupUi(this);
}
FMVipOrder::~FMVipOrder()
{
del_p(orderInfo);
delete ui;
}
void FMVipOrder::initWnd(Session *session)
{
this->_session = session;
QString operator_id = session->data(PosProps.OperatorId).toString();
QString business_date = session->data(PosProps.BussinessDate).toString();
QString fm_id = session->data(PosProps.Fm_open_id).toString();
QString name = session->data(PosProps.Name).toString();
QString amount_str = QString::number(session->data(PosProps.Amount).toInt());
QString score_str = QString::number(session->data(PosProps.Score).toInt());
int needPay = session->data(PosProps.OrderAmount).toInt() - session->data(PosProps.PaidAmount).toInt();
QString needPay_str = QString::number(needPay);
double standard_amount = session->data(PosProps.StandardAmount).toInt() / 100.0;
orderInfo = new FMVipOrder::OrderInfo(amount_str, score_str, needPay_str);
orderInfo->setCouponMap(session->getCouponMap(PosProps.CouponMap));
ui->store_label->setText(session->data(PosProps.StoreId).toString());
ui->pos_label->setText(session->data(PosProps.PosId).toString());
ui->operator_label->setText(operator_id);
ui->bd_label->setText(business_date);
ui->id_label->setText(fm_id);
ui->point_label->setText(score_str);
ui->balance_label->setText(orderInfo->getAmountStr());
ui->price_label->setText(orderInfo->getNeedPayStr());
ui->name_label->setText(name);
initCouponItems();
connect(ui->coupon_page, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*)));
ui->pay_chk->setText(QString::fromLocal8Bit("使用积分抵用 %1 元").arg(orderInfo->getScoreAmount()));
if(standard_amount > 0) {
ui->standard_label->setText(QString::fromLocal8Bit("满 %1 元可享受储值金满额优惠").arg(standard_amount));
} else {
ui->standard_label->setText("");
}
oldPayText = DOUBLE_STR(orderInfo->getMaxWillPay());
ui->pay_edit->setText(oldPayText);
QRegExp regexp("^[0-9]+(.[0-9]{2})?$");
ui->pay_edit->setValidator(new QRegExpValidator(regexp));
setWillPayText();
}
void FMVipOrder::on_pay_btn_clicked()
{
session()->addData(PosProps.CouponMap, orderInfo->selectCouponMap);
int codeAmount = orderInfo->getPayAmount(ui->pay_edit->text());
session()->addData(PosProps.CodeAmount, codeAmount);
session()->addData(PosProps.IsUseScore, orderInfo->isUseScore());
this->setEnabled(false);
setIsBusy(true);
emit pay();
}
void FMVipOrder::on_pay_chk_clicked(bool checked)
{
orderInfo->setUseScore(checked);
setWillPayText();
}
void FMVipOrder::onItemClicked(QListWidgetItem *item)
{
QString code = item->data(Qt::UserRole).toString();
// 如果代金券已被选中则取消,否则选中
if(orderInfo->selectCouponMap.contains(code)) {
ui->coupon_page->itemWidget(item)->setStyleSheet("#FMCouponWidget{background-color: rgb(255, 255, 255); border: none; border-left: 5 solid rgb(255, 170, 37);}");
orderInfo->selectCouponMap.remove(code);
orderInfo->enoughCoupon(); // 计算一下当前代金券金额
}else{
ui->coupon_page->itemWidget(item)->setStyleSheet("#FMCouponWidget{background-color: rgb(255, 255, 255); border: none; border-image: url(:/coupon_select.png);}");
orderInfo->selectCouponMap[code] = orderInfo->couponMap()[code];
if(orderInfo->enoughCoupon())
{
FMMsgWnd::WarningWnd(QString::fromLocal8Bit("请注意代金券总额已超过待付金额!"), this);
}
}
setWillPayText();
}
void FMVipOrder::initCouponItems()
{
foreach(Coupon coupon , orderInfo->couponMap().values())
{
auto item = new QListWidgetItem();
item->setData(Qt::UserRole, coupon.code);
ui->coupon_page->addItem(item);
ui->coupon_page->update();
auto itemWidget = new FMCouponWidget(coupon);
ui->coupon_page->setItemWidget(item, itemWidget);
//item大小
item->setSizeHint (itemWidget->size());
}
}
void FMVipOrder::setWillPayText()
{
on_pay_edit_textChanged(oldPayText);
ui->pay_edit->setFocus();
ui->pay_edit->selectAll();
}
void FMVipOrder::on_coupon_prev_btn_clicked()
{
int pos = ui->coupon_page->verticalScrollBar()->value();
ui->coupon_page->verticalScrollBar()->setValue(pos - 125);
}
void FMVipOrder::on_coupon_next_btn_clicked()
{
int pos = ui->coupon_page->verticalScrollBar()->value();
ui->coupon_page->verticalScrollBar()->setValue(pos + 125);
}
void FMVipOrder::on_pay_edit_textChanged(const QString &text)
{
double num = text.toDouble();
double maxPay = orderInfo->getMaxWillPay();
if (num > maxPay) {
ui->pay_edit->setText(DOUBLE_STR(maxPay));
QString maxPay_info = QString::fromLocal8Bit("余额只需支付 %1 元");
if (maxPay >= orderInfo->getAmountStr().toDouble()) {
maxPay_info = QString::fromLocal8Bit("余额最多支付 %1 元");
}
ui->pay_max->setText(maxPay_info.arg(maxPay));
ui->pay_edit->setFocus();
ui->pay_edit->selectAll();
} else {
oldPayText = text;
ui->pay_max->setText("");
}
}
#ifndef FMVIPORDER_H
#define FMVIPORDER_H
#include <QListWidgetItem>
#include "fmvipwnd.h"
#define MIN(a,b) ((a<b) ? a : b)
#define MAX(a,b) ((a<b) ? b : a)
#define DOUBLE_STR(num) QString::number(num, 'f', 2)
namespace Ui {
class FMVipOrder;
}
class FMVipOrder : public FMVipWnd
{
Q_OBJECT
public:
explicit FMVipOrder(QDialog *parent = 0);
~FMVipOrder();
void initWnd(Session *session);
void setWillPayText();
signals:
void pay();
public slots:
void on_pay_btn_clicked();
void on_pay_chk_clicked(bool checked);
void onItemClicked(QListWidgetItem*);
private slots:
void on_coupon_prev_btn_clicked();
void on_coupon_next_btn_clicked();
void on_pay_edit_textChanged(const QString &text);
private:
class OrderInfo
{
public:
OrderInfo()
{
_amountStr = _scoreStr = _needPayStr = "";
_amount = _score = _needPay = _maxWillPay = _useScore = _couponAmount = 0;
}
OrderInfo(QString amountStr, QString scoreStr, QString needPayStr)
{
this->_amountStr = amountStr;
this->_scoreStr = scoreStr;
this->_needPayStr = needPayStr;
_amount = _amountStr.toInt() / 100.0;
_score = _scoreStr.toInt() / 100.0;
_needPay = _needPayStr.toInt() / 100.0;
_maxWillPay = _useScore = _couponAmount = 0;
setMaxWillPay();
}
QString getAmountStr()
{
return DOUBLE_STR(_amount);
}
QString getNeedPayStr()
{
return DOUBLE_STR(_needPay);
}
QString getScoreAmount()
{
return DOUBLE_STR(MIN(_score, _needPay));
}
int getPayAmount(QString amountStr)
{
int payAmount = MIN(_needPay, (amountStr.toDouble() + _couponAmount + _useScore)) * 100;
return payAmount;
}
// 代金券总额超过待付时返回true
bool enoughCoupon()
{
_couponAmount = 0.0;
foreach(auto coupon , selectCouponMap)
{
_couponAmount += coupon.disAmount;
}
bool isEnough = (_couponAmount > _needPay);
setMaxWillPay();
return isEnough;
}
void setUseScore(bool isUse)
{
if(isUse) {
_useScore = MIN(_score, _needPay);
} else {
_useScore = 0;
}
setMaxWillPay();
}
int isUseScore()
{
return (_useScore == 0 ? 0 : 1);
}
// 设置付款金额的最大值
void setMaxWillPay()
{
double willPay = _needPay - _useScore - _couponAmount;
_maxWillPay = MIN(MAX(willPay, 0), _amount);
}
double getMaxWillPay()
{
return _maxWillPay;
}
/// 代金券列表
void setCouponMap(QMap<QString, Coupon> couponMap)
{
this->_couponMap = couponMap;
_maxPage = (couponMap.count() - 1) / 6 + 1 ;
_nowPage = -1;
}
QMap<QString, Coupon> couponMap()
{
return _couponMap;
}
QMap<QString, Coupon> selectCouponMap;
private:
QString _amountStr, _scoreStr, _needPayStr;
double _amount, _score, _needPay;
QMap<QString, Coupon> _couponMap;
int _maxPage, _nowPage;
// 代金券金额 使用积分金额 余额将付金额
double _couponAmount, _useScore, _maxWillPay;
};
private:
Ui::FMVipOrder *ui;
FMVipOrder::OrderInfo *orderInfo;
QString oldPayText;
void initCouponItems();
};
#endif // FMVIPORDER_H
#include "fmvippanel.h"
//#include "fmvipforward.h"
#include "ui_fmvippanel.h"
#include "fmvipfund.h"
#include "fmvipfund.h"
#include <QFile>
FMVipPanel::FMVipPanel(QDialog *parent) :
FMVipWnd(parent),
ui(new Ui::FMVipPanel)
{
ui->setupUi(this);
}
FMVipPanel::~FMVipPanel()
{
delete ui;
}
void FMVipPanel::initWnd(Session *session)
{
this->_session = session;
ui->store_label->setText(session->data(PosProps.StoreId).toString());
ui->pos_label->setText(session->data(PosProps.PosId).toString());
ui->operator_label->setText(session->data("operator_id").toString());
ui->bd_label->setText(session->data("business_date").toString());
ui->id_label->setText(session->data("mobile").toString());
ui->balance_label->setText(session->data("amount").toString());
ui->name_label->setText(session->data("name").toString());
ui->fund_btn->setFocus();
}
void FMVipPanel::on_fund_btn_clicked()
{
}
void FMVipPanel::on_lock_btn_clicked()
{
qDebug() << __FUNCTION__;
}
void FMVipPanel::on_activate_btn_clicked()
{
qDebug() << __FUNCTION__;
}
#ifndef FMVIPPANEL_H
#define FMVIPPANEL_H
#include <fmvipwnd.h>
namespace Ui {
class FMVipPanel;
}
class FMVipPanel : public FMVipWnd
{
Q_OBJECT
public:
explicit FMVipPanel(QDialog *parent = 0);
~FMVipPanel();
void initWnd(Session *session);
public slots:
void on_fund_btn_clicked();
void on_lock_btn_clicked();
void on_activate_btn_clicked();
private:
Ui::FMVipPanel *ui;
};
#endif // FMVIPPANEL_H
#include "fmvipwnd.h"
#include <QDebug>
#include <QDesktopWidget>
#include <QPainter>
#include <QStyleOption>
#include <QJsonDocument>
#ifdef Q_OS_WIN
#include <windows.h>
#include <windowsx.h>
#endif
FMVipWnd::FMVipWnd(QDialog *parent) :
QDialog(parent),
loadingWindow(new FMLoading(this))
{
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_QuitOnClose, false);
setAttribute(Qt::WA_DeleteOnClose, false);
setIsBusy(false);
}
FMVipWnd::~FMVipWnd()
{
del_p(loadingWindow);
}
void FMVipWnd::on_close_btn_clicked()
{
this->done(-1);
}
bool FMVipWnd::close()
{
if(loadingWindow != nullptr) {
loadingWindow->hide();
}
return QDialog::close();
}
void FMVipWnd::setIsBusy(const bool isBusy)
{
if(isBusy)
{
loadingWindow->show();
}else{
loadingWindow->hide();
}
}
int FMVipWnd::exec()
{
showNormal();
::SetForegroundWindow((HWND)effectiveWinId());
::SetWindowPos( (HWND)effectiveWinId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
showNormal();
::SetForegroundWindow((HWND)effectiveWinId());
QDesktopWidget w;
QRect rc = w.availableGeometry();
setGeometry((rc.width() - width()) / 2, (rc.height() - height()) / 2, width(), height());
return QDialog::exec();
}
#ifdef Q_OS_WIN
//! Gui class member of platform
bool FMVipWnd::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(eventType);
MSG *msg = (MSG*)message;
//! true indicates the message need to be processed by DefWindowProc
bool fCallDWP = true;
bool fMsgDone = false;
switch (msg->message) {
case WM_NCHITTEST: {
*result = winNCHitTest(msg);
if (*result != HTNOWHERE) {
// HTMINBUTTON 等消息当作HTCLIENT处理
switch (*result) {
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
*result = HTCLIENT;
break;
}
fCallDWP = false;
}
break;
}
case WM_GETMINMAXINFO: {
// 最大化时的处理
MINMAXINFO *mmi = (MINMAXINFO*) (msg->lParam);
QDesktopWidget desktopWidget;
QRect desktop = desktopWidget.availableGeometry();
mmi->ptMaxSize.x = desktop.width();
mmi->ptMaxSize.y = desktop.height();
mmi->ptMaxPosition.x = desktop.x();
mmi->ptMaxPosition.y = desktop.y();
mmi->ptMinTrackSize.x = minimumWidth(); // minimum width for your window
mmi->ptMinTrackSize.y = minimumHeight(); // minimum height for your window
mmi->ptMaxTrackSize.x = maximumWidth();
mmi->ptMaxTrackSize.y = maximumHeight();
*result = 0;
fMsgDone = true;
break;
}
default:
break;
}
fMsgDone = fMsgDone || !fCallDWP;
return fMsgDone;
}
void FMVipWnd::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
long FMVipWnd::winNCHitTest(MSG *msg)
{
// Mouse position
QPoint mouse_pos(GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam));
QRect window_rect = geometry();
// Set default value (HTNOWHERE) (1,1).
USHORT uRow = 1;
USHORT uCol = 1;
bool fOnResizeBorder = false;
//! Test caption area
QRegion m_children_region(0, 0, width() - 54, 60);
QRegion new_region = m_children_region.translated(window_rect.x() , window_rect.y());
if (new_region.contains(mouse_pos)) {
//! Title regions contains the mouse position, treat it as caption area
uRow = 0;
}
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
LRESULT hitTests[3][3] =
{
{ HTTOPLEFT, fOnResizeBorder ? HTTOP : HTCAPTION, HTTOPRIGHT },
{ HTLEFT, HTNOWHERE, HTRIGHT },
{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
};
//! Test borders area
if (minimumSize() != maximumSize()) {
//! To be implemented
}
return hitTests[uRow][uCol];
}
#endif
#ifndef FMVIPWND_H
#define FMVIPWND_H
#include <QDialog>
#include <QJsonObject>
#include <QMap>
#include <QDebug>
#include "fmloading.h"
#include "session.h"
class FMVipWnd : public QDialog
{
Q_OBJECT
public:
explicit FMVipWnd(QDialog *parent = 0);
~FMVipWnd();
void setIsBusy(const bool isBusy = true);
virtual void resetWnd(){}
int exec();
bool close();
virtual void initWnd(Session* session) {this->_session = session;}
Session* session() const {return _session;}
public slots:
void on_close_btn_clicked();
private:
FMLoading* loadingWindow;
protected:
bool _isBusy;
Session *_session;
#ifdef Q_OS_WIN
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
void paintEvent(QPaintEvent *event);
protected:
long winNCHitTest(MSG *msg);
#endif
};
#endif // FMVIPWND_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FMCouponWidget</class>
<widget class="QWidget" name="FMCouponWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>220</width>
<height>116</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true">
#FMCouponWidget
{
border: 0 solid white;
border-left: 5 solid rgb(255, 170, 37);
background-color: rgb(255, 255, 255);
}
#code_lab
{
max-height: 15;
min-height: 15;
padding-bottom: 3px;
color: rgb(127,127,127);
font: 12px &quot;Microsoft YaHei&quot;;
}
#amount_lab, #currency
{
color: rgb(229, 11, 72);
font: bold 30px &quot;Microsoft YaHei&quot;;
}
#currency
{
font: bold 15px;
margin-top: 11px;
}
#desc_lab
{
max-height: 21;
min-height: 21;
color: rgb(252,255,255);
background-color: rgb(229, 11, 72);
font: bold 15px &quot;Microsoft YaHei&quot;;
margin-left: 4px;
margin-bottom: 3px;
padding: 0 10 0 10;
}
#coupon_separator
{
max-height: 1px;
border-image: url(:/img/coupon_separator.png);
margin: 0 6 10 6;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="currency">
<property name="text">
<string></string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="amount_lab">
<property name="text">
<string>40.00</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="coupon_separator"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="desc_lab">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>24</height>
</size>
</property>
<property name="text">
<string>测试代金券</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="code_lab">
<property name="text">
<string>123456789</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FMLoading</class>
<widget class="QWidget" name="FMLoading">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>124</width>
<height>124</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="QLabel" name="loading_lbl">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>124</width>
<height>124</height>
</rect>
</property>
<property name="text">
<string>loading...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment