Bladeren bron

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ScreenshotServiceImpl.java
Reiskuchen 5 jaren geleden
bovenliggende
commit
5ed7614a60

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -39,6 +39,8 @@ public class UserController {
      */
     @RequestMapping("/loginEmployee")
     public HttpRespMsg loginEmployee(@RequestParam String username, @RequestParam String password) {
+        String property = System.getProperty("java.io.tmpdir");
+        System.out.println("tomcat临时目录=="+property);
         return userService.loginEmployee(username, password);
     }
 

+ 211 - 27
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ScreenshotServiceImpl.java

@@ -25,12 +25,16 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalTime;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.regex.Pattern;
 
 /**
  * <p>
@@ -43,7 +47,7 @@ import java.util.*;
 @Service
 @Transactional
 public class ScreenshotServiceImpl extends ServiceImpl<ScreenshotMapper, Screenshot> implements ScreenshotService {
-
+    public static List<String> nKeyWordsList = new ArrayList<String>();
     public static Logger log = Logger.getLogger(ScreenshotServiceImpl.class);
 
     //检测时间间隔秒数
@@ -51,7 +55,8 @@ public class ScreenshotServiceImpl extends ServiceImpl<ScreenshotMapper, Screens
 
     @Value(value = "${upload.path}")
     private String path;
-
+    @Value("classpath:novel_words.data")
+    private org.springframework.core.io.Resource novelWords;
     @Autowired
     private RedisUtil redisUtil;
 
@@ -136,33 +141,39 @@ public class ScreenshotServiceImpl extends ServiceImpl<ScreenshotMapper, Screens
             //由于存入数据库的对象被序列化成了json字符串,所以从redis里拿方便
             members = redisUtil.members(Constant.COMMON_SOFTWARE_KEYWORDS);
         }
-        List<String> exeprocessList = ProcessUtil.getExeprocessListfromProcessStr(screenshotvo.getProcessList());
-        System.out.println("進程" + exeprocessList);
-        boolean derail = false;//判断是否匹配的开关
-        Integer lastType = null;
-        for (String textContent : textContents) {
-            for (Object member : members) {
-                //由于redis里存储的member是一个PicContentKeywords类型的json字符串,所以取出关键字内容比较
-                JSONObject jsonMember = JSON.parseObject((String) member);
-                if (textContent.toLowerCase().contains(jsonMember.getString("content").toLowerCase())) {
-                    log.info("图片文字中包含了关键词--->" + jsonMember.getString("content"));
-                    log.info("图片文字识别出的类型--->" + jsonMember.getInteger("type"));
-                    //找到对应关键字,确定图片是哪个类型的图片
-                    //结合进程判断
-                    if (exeprocessList.contains(jsonMember.getString("processName").toLowerCase())) {
-                        if (!derail) {
-                            //判断是否是第一次匹配
-                            log.info("图片中关键字对应的进程名--->" + jsonMember.getString("processName"));
-                            screenshot.setPicType(jsonMember.getInteger("type"));
-                            lastType = jsonMember.getInteger("type");
-                            derail = true;
-                        } else {
-                            if (0 == lastType) {
-                                //软件开发为主
-                                break;
-                            } else {
+
+        if (isNovel(textContents)) {
+            screenshot.setPicType(6);
+        } else {
+
+            List<String> exeprocessList = ProcessUtil.getExeprocessListfromProcessStr(screenshotvo.getProcessList());
+            System.out.println("進程" + exeprocessList);
+            boolean derail = false;//判断是否匹配的开关
+            Integer lastType = null;
+            for (String textContent : textContents) {
+                for (Object member : members) {
+                    //由于redis里存储的member是一个PicContentKeywords类型的json字符串,所以取出关键字内容比较
+                    JSONObject jsonMember = JSON.parseObject((String) member);
+                    if (textContent.toLowerCase().contains(jsonMember.getString("content").toLowerCase())) {
+                        log.info("图片文字中包含了关键词--->" + jsonMember.getString("content"));
+                        log.info("图片文字识别出的类型--->" + jsonMember.getInteger("type"));
+                        //找到对应关键字,确定图片是哪个类型的图片
+                        //结合进程判断
+                        if (exeprocessList.contains(jsonMember.getString("processName").toLowerCase())) {
+                            if (!derail) {
+                                //判断是否是第一次匹配
+                                log.info("图片中关键字对应的进程名--->" + jsonMember.getString("processName"));
                                 screenshot.setPicType(jsonMember.getInteger("type"));
                                 lastType = jsonMember.getInteger("type");
+                                derail = true;
+                            } else {
+                                if (0 == lastType) {
+                                    //软件开发为主
+                                    break;
+                                } else {
+                                    screenshot.setPicType(jsonMember.getInteger("type"));
+                                    lastType = jsonMember.getInteger("type");
+                                }
                             }
                         }
                     }
@@ -170,10 +181,183 @@ public class ScreenshotServiceImpl extends ServiceImpl<ScreenshotMapper, Screens
             }
         }
         screenshot.setIsHandle(1);
+        if (screenshot.getPicType() == null) {
+            //判断是否是游戏
+            if (isGame(new File(filePath))) {
+                screenshot.setPicType(7);
+            }
+        }
         screenshotMapper.insert(screenshot);
         return new HttpRespMsg();
     }
 
+    //判断文字内容是否是小说
+    private boolean isNovel(List<String> textContents) {
+        /**先粗糙地比较一下, 小说常规包含的词库,匹配频率高,则认为是小说。
+         * 第一步, 90%应该都是中文
+         */
+        int total = 0;
+        int chWNum = 0;
+        for (String w : textContents) {
+            char[] ch = w.toCharArray();
+            for (char c : ch) {
+                total++;
+                if (c >= 0x4E00 && c <= 0x9FBF) {
+                    chWNum++;
+                }
+            }
+        }
+        //小说一页中文字至少200个
+        if (chWNum < 200) {
+            return false;
+        }
+        int percent = chWNum*100/total;
+        log.info("中文比例:"+percent);
+        if (percent < 60) {
+            //英文太多,不是小说; 不考虑英文小说。
+            return false;
+        }
+
+
+        //第二步,匹配小说常见词汇,超过5次,认为是小说
+        try {
+            //填充小说关键字到内存,减少重复读取
+            if (nKeyWordsList.size() == 0) {
+                InputStream ins = novelWords.getInputStream();
+                BufferedReader br = new BufferedReader(new InputStreamReader(ins));
+                String line = br.readLine();
+                while (line != null) {
+                    nKeyWordsList.add(line);
+                    line = br.readLine();
+                    System.out.println(line);
+                }
+            }
+            int totalKNum = 0;
+            for (String k: textContents) {
+                int kNum = 0;
+                for (String nk : nKeyWordsList) {
+                    if (k.contains(nk)) {
+                        kNum++;
+                    }
+                }
+                totalKNum += kNum;
+                //存在第几章这样的关键字, +1分
+                if (matchCategory(k)) {
+                    totalKNum += 1;
+                }
+            }
+            log.info("文章小说匹配得分为=="+totalKNum);
+            if (totalKNum >= 5) {
+                return true;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    public static boolean matchCategory(String str) {
+        String pattern = "^第(.*)章(.*)";
+        // 创建 Pattern 对象
+        return Pattern.matches(pattern, str.trim());
+    }
+
+    public static void main(String[] args) {
+//        boolean find = matchCategory("第22 重生");
+//        System.out.println(find);
+        String str = "中文";
+        System.out.println(str.toCharArray().length);
+        isGame(new File("C://Users/seya/Desktop/1.jpg"));
+    }
+
+    public static boolean isGame(File pic) {
+        try {
+            int[] rgb = new int[3];
+            BufferedImage img = ImageIO.read(pic);
+            int width = img.getWidth();
+            int height = img.getHeight();
+            int minx = img.getMinX();
+            int miny = img.getMinY();
+            System.out.println("width=" + width + ",height=" + height + ".");
+            System.out.println("minx=" + minx + ",miniy=" + miny + ".");
+            //统计出现最多的一个色值,计算所占比重
+            int totalPixl = 0;
+            HashMap<Integer, Integer> colorCntMap = new HashMap<Integer, Integer>();
+            for (int i = minx; i < width; i++) {
+                for (int j = miny; j < height; j++) {
+                    totalPixl++;
+//                    int w=20;
+//                    int h=20;
+//                    BufferedImage rect = img.getSubimage(i, j, w, h);
+
+                    int pixel = img.getRGB(i, j); // 下面三行代码将一个数字转换为RGB数字
+                    if (colorCntMap.get(pixel) == null) {
+                        colorCntMap.put(pixel, 1);
+                    } else {
+                        colorCntMap.put(pixel, colorCntMap.get(pixel) + 1);
+                    }
+//                    rgb[0] = (pixel & 0xff0000) >> 16;
+//                    rgb[1] = (pixel & 0xff00) >> 8;
+//                    rgb[2] = (pixel & 0xff);
+//                    if (rgb[0] != 255 || rgb[1] != 255 || rgb[2] != 255) {
+//                        //红色判断
+//                        if (rgb[0]>=200 && rgb[1] <=50 && rgb[2] <= 50) {
+//                            System.out.println("红色i=" + i + ",j=" + j + ":(" + rgb[0] + ","
+//                                    + rgb[1] + "," + rgb[2] + ")");
+//                        } else if (rgb[0] <= 50 && rgb[1] >= 200 && rgb[2] <= 50) {
+//                            System.out.println("绿色i=" + i + ",j=" + j + ":(" + rgb[0] + ","
+//                                    + rgb[1] + "," + rgb[2] + ")");
+//                        } else if (rgb[0] <= 50 && rgb[1] <= 50 && rgb[2] >= 200) {
+//                            System.out.println("蓝色i=" + i + ",j=" + j + ":(" + rgb[0] + ","
+//                                    + rgb[1] + "," + rgb[2] + ")");
+//                        }
+//                    }
+                }
+            }
+
+            int maxCnt = 0;
+            int key = 0;
+            Set<Map.Entry<Integer, Integer>> entry2 = colorCntMap.entrySet();
+            for(Map.Entry<Integer, Integer> temp : entry2){
+                System.out.println("sortedMap:"+temp.getKey()+" 值"+temp.getValue());
+                if (temp.getValue() > maxCnt) {
+                    maxCnt = temp.getValue();
+                    key = temp.getKey();
+                }
+            }
+            System.out.println("最.." + maxCnt + ", key=" + key);
+            rgb[0] = (key & 0xff0000) >> 16;
+            rgb[1] = (key & 0xff00) >> 8;
+            rgb[2] = (key & 0xff);
+            System.out.println("色值为: " + rgb[0] + ", " + rgb[1]+", "+rgb[2]);
+            //计算比例, 应该不低于50%
+            int colorPercent = maxCnt * 100 / totalPixl;
+            System.out.println("底色比例=="+colorPercent);
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+
+    /**
+     * 是否全是汉字<br>
+     * 根据汉字编码范围进行判断<br>
+     * CJK统一汉字(不包含中文的,。《》()“‘'”、!¥等符号)<br>
+     *
+     * @param str
+     * @return
+     */
+    public static boolean isChineseByReg(String str) {
+        if (str == null) {
+            return false;
+        }
+        Pattern pattern = Pattern.compile("[\\u4E00-\\u9FBF]+");
+        return pattern.matcher(str).matches();
+    }
+
+
     //每次获取到截屏后计算并处理
     private void calculateTime(Screenshot screenshot) {
         try {

+ 5 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ProcessUtil.java

@@ -50,7 +50,11 @@ public class ProcessUtil {
         //从第三行开始才是系统的.exe进程
         for (int i = 3; i < list.length; i++) {
             // 必须写死,截取长度,因为是固定的
-            exeprocessList.add(list[i].substring(0, 25).trim()); // 进程名
+            if (list[i].length() > 25) {
+                exeprocessList.add(list[i].substring(0, 25).trim()); // 进程名
+            } else {
+                System.out.println("list : " + i +"=" +list[i]);
+            }
 //            System.out.println(process);
         }
         return exeprocessList;

+ 3 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml

@@ -11,7 +11,7 @@ spring:
       # Single file max size  即单个文件大小
       max-file-size: 10000MB
       max-request-size: 10000MB
-      location: D:/upload/
+      location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://118.190.47.230:3306/man_hour_manager?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
@@ -54,7 +54,7 @@ logging:
     org.springframework.web: trace
     #打印sql语句
     com.management.platform.mapper: debug
-  path: E:/
+  path: C:/
 ##########
 mybatis-plus:
 #  mapper-locations: classpath:mapper/*/*.xml
@@ -80,6 +80,6 @@ mybatis:
   mapper-locations: mappers/*Mapper.xml
 #####配置图片上传路径####
 upload:
-  path: D:/upload/
+  path: C:/upload/
 
 

+ 10 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/novel_words.data

@@ -0,0 +1,10 @@
+道:“
+道,
+道。
+我
+你
+他
+说:
+说。
+说,
+她

+ 73 - 0
fhKeeper/formulahousekeeper/mywork/.gitignore

@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+

+ 65 - 0
fhKeeper/formulahousekeeper/mywork/baseapi.cc

@@ -0,0 +1,65 @@
+#include "baseapi.h"
+
+BaseAPI::BaseAPI()
+{
+    httpRequest.setRawHeader("Accept", API_ACCEPT);
+    httpRequest.setRawHeader("User-Agent", API_USER_AGENT);
+    httpRequest.setRawHeader("X-XXX-API-Key", API_KEY);
+    httpRequest.setRawHeader("X-XXX-API-Secret", API_SECRET);
+    httpRequest.setRawHeader("Accept-Encoding", "gzip, deflate");
+    httpRequest.setRawHeader("Content-Type", "application/json");
+
+    settings = new QSettings("XXX");
+    QString id = settings->value(SETTING_ACCOUNT_ID, "seyason").toString();
+    QString token = settings->value(SETTING_ACCOUNT_TOKEN, "123456").toString();
+
+    if(!id.isEmpty()) {
+        httpRequest.setRawHeader("X-XXX-User-ID", id.toStdString().c_str());
+    }
+
+    if (!token.isEmpty()) {
+        httpRequest.setRawHeader("X-XXX-User-Token", token.toStdString().c_str());
+    }
+
+    qDebug() << "BaseAPI...id:" << id << " token:" + token;
+
+    QObject::connect(&networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));
+}
+
+BaseAPI::~BaseAPI()
+{
+    networkAccessManager.disconnect();
+    if (settings){
+        delete settings;
+        settings = nullptr;
+    }
+}
+
+void BaseAPI::get(const QString url)
+{
+    httpRequest.setUrl(QUrl(url));
+    qDebug() << "http request "<<httpRequest.url();
+    networkAccessManager.get(httpRequest);
+}
+
+void BaseAPI::post(const QString url, const QByteArray &data)
+{
+    httpRequest.setUrl(QUrl(url));
+    networkAccessManager.post(httpRequest, data);
+}
+
+void BaseAPI::serviceRequestFinished(QNetworkReply *reply)
+{
+    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+
+    qDebug() << "BaseAPI...serviceRequestFinished...statusCode:" << statusCode;
+
+    if(reply->error() == QNetworkReply::NoError) {
+        requestFinished(reply, reply->readAll(), statusCode);
+    } else {
+        requestFinished(reply, "", statusCode);
+    }
+
+    // At the end of that slot, we won't need it anymore
+    reply->deleteLater();
+}

+ 33 - 0
fhKeeper/formulahousekeeper/mywork/baseapi.h

@@ -0,0 +1,33 @@
+#ifndef BASEAPI_H
+#define BASEAPI_H
+
+#include <QSettings>
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkAccessManager>
+
+#include "constants.h"
+
+class BaseAPI : public QObject
+{
+    Q_OBJECT
+
+public:
+    BaseAPI();
+    ~BaseAPI();
+    void get(const QString url);
+    void post(const QString url, const QByteArray &data);
+
+protected:
+    virtual void requestFinished(QNetworkReply *reply, const QByteArray data, const int statusCode) = 0;
+
+public slots:
+    void serviceRequestFinished(QNetworkReply *reply);
+
+private:
+    QNetworkRequest httpRequest;
+    QNetworkAccessManager networkAccessManager;
+    QSettings *settings;
+};
+
+#endif // BASEAPI_H

+ 11 - 0
fhKeeper/formulahousekeeper/mywork/constants.h

@@ -0,0 +1,11 @@
+#ifndef CONSTANTS_H
+#define CONSTANTS_H
+
+#define API_ACCEPT "*/*"
+#define API_USER_AGENT "DesktopClient"
+#define API_KEY "key"
+#define API_SECRET "secrect"
+#define SETTING_ACCOUNT_ID "id"
+#define SETTING_ACCOUNT_TOKEN "token"
+
+#endif // CONSTANTS_H

+ 188 - 0
fhKeeper/formulahousekeeper/mywork/home.cpp

@@ -0,0 +1,188 @@
+#include "home.h"
+#include "ui_home.h"
+#include <QDateTime>
+#include <QMessageBox>
+#include <QScreen>
+#include <QTimer>
+#include <QDebug>
+#include <QNetworkRequest>
+#include <QHttpMultiPart>
+#include <QNetworkAccessManager>
+#include <QFile>
+#include <QProcess>
+#include <QVBoxLayout>
+//#include <QtWin>
+//#include <QtWinExtras/qwinfunctions.h>
+#pragma  comment(lib, "user32.lib")
+#include "httpapi.h"
+#include "qresource.h"
+
+#include <windows.h>
+#include <tlhelp32.h>
+#include <stdio.h>
+
+Home::Home(QWidget *parent) :
+    QMainWindow(parent),
+    ui(new Ui::Home)
+{
+    ui->setupUi(this);
+    myTimer = new QTimer(this);
+    //start timer for screen capture
+    connect(myTimer,&QTimer::timeout,[this](){
+            captureScreen();
+    });
+    myTimer->start(10000);
+
+    //set ui data
+    webWidget = new QWebEngineView(this);
+    QNetworkProxyFactory::setUseSystemConfiguration(false);
+
+  QVBoxLayout *mainLayout = new QVBoxLayout;
+
+  mainLayout->addWidget(webWidget);
+//  setLayout(mainLayout);
+  QWidget* widget = new QWidget(this);
+  widget->setLayout(mainLayout);
+  this->setCentralWidget(widget);
+
+  setWindowState(Qt::WindowMaximized);//最大化
+  QString str = "http://118.190.47.230:9095/#/login";
+  loadNavigate(str);
+
+
+  HANDLE hCurrentCursor = GetForegroundWindow();
+  qDebug()<<hCurrentCursor<<endl;
+//  EnumWindows(StaticEnumWindowsProc,reinterpret_cast<LPARAM>(this));
+  PROCESSENTRY32 pe32;
+  //再使用这个结构体前先定义它的大小
+  pe32.dwSize=sizeof(pe32);
+  //给系统内的所有进程拍一个快照
+  HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
+  if (hProcessSnap==INVALID_HANDLE_VALUE)
+  {
+    printf("Create ToolHelp32Snaphhot调用失败!\n");
+
+  }
+  BOOL bMore=::Process32First(hProcessSnap,&pe32);
+//  while(bMore)
+//  {
+//    qDebug()<<"进程名称="<<pe32.szExeFile<<"进程id="<<pe32.th32ProcessID;
+
+//    bMore=::Process32Next(hProcessSnap,&pe32);
+//  }
+//  qDebug()<<"不要忘记清楚掉snapshot";
+  ::CloseHandle(hProcessSnap);
+
+}
+
+BOOL Home::StaticEnumWindowsProc(HWND hwnd, LPARAM lParam)
+{
+    //窗口是否可视
+    if (!::IsWindowVisible(hwnd))
+        return TRUE;
+
+    //窗口是否可激活
+    if (!::IsWindowEnabled(hwnd))
+        return TRUE;
+
+    //确定给定窗口是否是最小化(图标化)的窗口。
+    //if(IsIconic(hwnd))
+      //  return TRUE;
+
+    //窗口是否具有父窗口?
+    HWND hParent = (HWND)GetWindowLong(hwnd, -8);
+    //父窗口是否可激活?
+    //据 Spy++ 观察,如“运行”对话框等被应列入列表的程序有一个隐藏的,具有 WS_DISABLED 的父窗口
+    if (IsWindowEnabled(hParent))
+        return TRUE;
+    //父窗口是否可视?
+    if (IsWindowVisible(hParent))
+        return TRUE;
+
+    LONG gwl_style = GetWindowLong(hwnd, GWL_STYLE);
+    if ((gwl_style & WS_POPUP) && !(gwl_style & WS_CAPTION))
+        return TRUE;
+
+    CHAR caption[256];
+    memset(caption, 0, sizeof(caption));
+    ::GetWindowTextA(hwnd, caption, 255);
+
+    if (strcmp(caption, ""))
+    {
+        if (GetClassLong(hwnd, -14))
+        {
+            HICON hIcon =(HICON)GetClassLong(hwnd, -14);
+            if(hIcon)
+            {
+//                handleIcon.push_back(hIcon);
+//                handleWindow.push_back(hwnd);
+                qDebug()<<"hIcon="<<hIcon<<", title="<<GetClassLong(hwnd, -8);
+
+            }
+        }
+    } else {
+        qDebug() <<"title=="<< caption;
+    }
+
+    return TRUE;
+}
+
+
+void Home::captureScreen() {
+    QScreen *screen = QGuiApplication::primaryScreen();
+    QString filePathName = "timeManager_screencap.jpg";
+    screen->grabWindow(0).save(filePathName, "jpg"); // 0值为整个电脑屏幕WId
+
+    //start upload file
+    QNetworkRequest request;
+    request.setUrl(QUrl(SERVER_URL + "/imageProcessing/saveAndProcessImage"));
+    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
+    QHttpPart imagePart;
+    imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));//如果是png图片填image/png
+    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"image.jpg\""));
+    // imagePart.setRawHeader("Content-ID", "my@content.id"); // 添加任何你喜欢的 headers
+    QFile *file = new QFile(filePathName);
+    file->open(QIODevice::ReadOnly);
+    imagePart.setBodyDevice(file);
+    multiPart->append(imagePart);
+
+    //text paramter
+    QHttpPart textPart;
+    textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"uid\""));
+    textPart.setBody("2");
+    multiPart->append(textPart);
+    QHttpPart textPart2;
+    textPart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"indate\""));
+    QString indate = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
+    textPart2.setBody(indate.toUtf8());
+    multiPart->append(textPart2);
+
+    QString processList = getProcessList();
+    qDebug() << processList ;
+    QHttpPart textPart3;
+    textPart3.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"processList\""));
+    textPart3.setBody(processList.toUtf8());
+    multiPart->append(textPart3);
+
+    QNetworkAccessManager *m_pNetWorkManager = new QNetworkAccessManager();
+    m_pNetWorkManager->post(request, multiPart);
+}
+
+QString Home::getProcessList() {
+    QProcess process;
+    process.start("tasklist.exe");
+    if(process.waitForFinished())
+    {
+        QByteArray result = process.readAll();
+        return result;
+    }
+    return NULL;
+}
+void Home::loadNavigate(QString sUrl)
+{
+  webWidget->load(sUrl);
+}
+Home::~Home()
+{
+    delete ui;
+}

+ 34 - 0
fhKeeper/formulahousekeeper/mywork/home.h

@@ -0,0 +1,34 @@
+#ifndef HOME_H
+#define HOME_H
+
+#include <QMainWindow>
+#include <QTimer>
+#include <QtWebEngineWidgets>
+#include "Windows.h"
+#define GWL_HWNDPARENT = -8
+#define GCL_HICON = -14
+#define GCL_MENUNAME = -8
+
+namespace Ui {
+class Home;
+}
+
+class Home : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    explicit Home(QWidget *parent = nullptr);
+    ~Home();
+public slots:
+    void captureScreen();
+    QString getProcessList();
+    void loadNavigate(QString sUrl);
+    static BOOL StaticEnumWindowsProc(HWND hwnd, LPARAM lParam);
+private:
+    Ui::Home *ui;
+    QTimer *myTimer;
+    QWebEngineView* webWidget;
+};
+
+#endif // HOME_H

+ 31 - 0
fhKeeper/formulahousekeeper/mywork/home.ui

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Home</class>
+ <widget class="QMainWindow" name="Home">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1187</width>
+    <height>797</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget"/>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1187</width>
+     <height>26</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 68 - 0
fhKeeper/formulahousekeeper/mywork/httpapi.cc

@@ -0,0 +1,68 @@
+#include "httpapi.h"
+
+#include "qdebug.h"
+
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonDocument>
+
+
+
+HttpAPI::HttpAPI()
+{
+
+}
+
+HttpAPI::~HttpAPI()
+{
+
+}
+
+void HttpAPI::requestFinished(QNetworkReply* reply, const QByteArray data, const int statusCode)
+{
+    if (statusCode == 200) {
+
+        QJsonParseError jsonError;
+        QString str = data;
+        qDebug()<<str;
+        QJsonObject json = QstringToJson(str);
+        this->checkCallback(true, json);
+        return;
+    }
+    QJsonObject games;
+    this->checkCallback(false, games);
+}
+
+void HttpAPI::getRequest(QString url, std::function<void(bool, QJsonObject)> callback)
+{
+    this->checkCallback = callback;
+
+    if (url.startsWith("http")) {
+        qDebug()<<"start request..."<<url;
+        get(url);
+    } else {
+        qDebug()<<"start request..."<<SERVER_URL + url;
+        get(SERVER_URL + url);
+    }
+
+}
+QJsonObject HttpAPI::QstringToJson(QString jsonString)
+{
+
+    QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8().data());
+    if(jsonDocument.isNull())
+    {
+        qDebug()<< "String NULL"<< jsonString.toUtf8().data();
+    } else {
+        qDebug() << "json document is not null";
+    }
+    QJsonObject jsonObject = jsonDocument.object();
+    QString code = jsonObject.value("code").toString();
+    qDebug() << code <<" == code" <<endl;
+    return jsonObject;
+}
+
+QString HttpAPI::JsonToQstring(QJsonObject jsonObject)
+{
+    return QString(QJsonDocument(jsonObject).toJson());
+}

+ 26 - 0
fhKeeper/formulahousekeeper/mywork/httpapi.h

@@ -0,0 +1,26 @@
+#ifndef HTTPAPI
+#define HTTPAPI
+
+#include <functional>
+#include <QList>
+#include <QPair>
+#include <QJsonObject>
+#include "baseapi.h"
+const QString SERVER_URL = QString("http://127.0.0.1:10010");
+class HttpAPI: public BaseAPI
+{
+public:
+    HttpAPI();
+    ~HttpAPI();
+    void getRequest(QString url, std::function<void(bool, QJsonObject)> callback);
+public slots:                   //新增
+    QJsonObject QstringToJson(QString jsonString);
+    QString JsonToQstring(QJsonObject jsonObject);
+protected:
+    void requestFinished(QNetworkReply* reply, const QByteArray data, const int statusCode);
+
+private:
+    std::function<void(bool, QJsonObject)> checkCallback;
+};
+
+#endif // HTTPAPI

+ 10 - 0
fhKeeper/formulahousekeeper/mywork/main.cpp

@@ -0,0 +1,10 @@
+#include "mainwindow.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    MainWindow w;
+    w.show();
+    return a.exec();
+}

+ 52 - 0
fhKeeper/formulahousekeeper/mywork/mainwindow.cpp

@@ -0,0 +1,52 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "home.h"
+
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkReply>
+#include <QEventLoop>
+#include <QMessageBox>
+#include "httpapi.h"
+
+MainWindow::MainWindow(QWidget *parent)
+    : QMainWindow(parent)
+    , ui(new Ui::MainWindow)
+{
+    ui->setupUi(this);
+    connect(ui->loginBtn,SIGNAL(clicked()),this,SLOT(login_in()));
+//    connect(ui->loginBtn, &QAction::triggered, this, &MainWindow::login_in);
+
+}
+void MainWindow::login_in(void){//登陆
+    //设置url
+    QString username = ui->account->text();
+    QString pwd = ui->pwd->text();
+    QString url = "/user/loginEmployee?username="+username+"&password="+pwd;//fae4b325e52c
+    HttpAPI *api = new HttpAPI();
+    static MainWindow* myWin = this;
+    api->getRequest(url, [&](bool success, QJsonObject json){
+        if (success)
+        {
+           //do something
+            qDebug()<<"request success==";
+            if (json.value("code").toString() == "ok") {
+                myWin->close();
+                //enter home page
+                home = new Home();
+                home->show();
+            } else {
+                QMessageBox msg3(QMessageBox::Information,windowTitle(),json.value("msg").toString(),QMessageBox::Ok,this);
+                msg3.exec();
+            }
+        }
+    });
+}
+void MainWindow::login_out(void){//退出
+
+}
+MainWindow::~MainWindow()
+{
+    delete ui;
+}
+

+ 26 - 0
fhKeeper/formulahousekeeper/mywork/mainwindow.h

@@ -0,0 +1,26 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+#include "home.h"
+#include <QMainWindow>
+#include <QJsonObject>
+#include <QJsonDocument>
+QT_BEGIN_NAMESPACE
+namespace Ui { class MainWindow; }
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    MainWindow(QWidget *parent = nullptr);
+    ~MainWindow();
+    Home *home;
+public slots:                   //新增
+    void login_in(void);	//新增
+    void login_out(void);	//新增
+
+private:
+    Ui::MainWindow *ui;
+};
+#endif // MAINWINDOW_H

+ 87 - 0
fhKeeper/formulahousekeeper/mywork/mainwindow.ui

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <widget class="QPushButton" name="loginBtn">
+    <property name="geometry">
+     <rect>
+      <x>340</x>
+      <y>450</y>
+      <width>93</width>
+      <height>28</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>登录</string>
+    </property>
+   </widget>
+   <widget class="QLabel" name="label">
+    <property name="geometry">
+     <rect>
+      <x>320</x>
+      <y>100</y>
+      <width>151</width>
+      <height>61</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>欢迎使用工时管家软件</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="account">
+    <property name="geometry">
+     <rect>
+      <x>290</x>
+      <y>210</y>
+      <width>201</width>
+      <height>41</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>15900000000</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="pwd">
+    <property name="geometry">
+     <rect>
+      <x>290</x>
+      <y>300</y>
+      <width>201</width>
+      <height>41</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>000000</string>
+    </property>
+    <property name="echoMode">
+     <enum>QLineEdit::Password</enum>
+    </property>
+   </widget>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>800</width>
+     <height>26</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

BIN
fhKeeper/formulahousekeeper/mywork/myicon.ico


+ 40 - 0
fhKeeper/formulahousekeeper/mywork/mywork.pro

@@ -0,0 +1,40 @@
+QT       += core gui network
+QT       += webenginewidgets
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+    baseapi.cc \
+    home.cpp \
+    httpapi.cc \
+    main.cpp \
+    mainwindow.cpp
+
+HEADERS += \
+    baseapi.h \
+    constants.h \
+    home.h \
+    httpapi.h \
+    mainwindow.h
+
+FORMS += \
+    home.ui \
+    mainwindow.ui
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+RC_ICONS = myicon.ico