Browse Source

灰色聚类配置

Signed-off-by: codeClown <zhaomengshou@126.com>
codeClown 1 year ago
parent
commit
3e2d595d15

+ 6 - 3
QFD/dbService/EffectIndexInfoService.cpp

@@ -23,7 +23,8 @@ int EffectIndexInfoService::AddEffectIndexInfo(const EffectIndexInfo &effectInde
     return ret;
 }
 
-bool EffectIndexInfoService::QueryEffectIndexInfoByProjectId(EffectIndexInfo *effectIndexInfo, int projectId)
+bool EffectIndexInfoService::QueryEffectIndexInfoByProjectId(QList<EffectIndexInfo *> *effectIndexInfoList,
+                                                             int projectId)
 {
     QSqlDatabase db = SqlDBHelper::getDatabase();
     QSqlQuery query(db);
@@ -34,8 +35,9 @@ bool EffectIndexInfoService::QueryEffectIndexInfoByProjectId(EffectIndexInfo *ef
                     "t_effect_index_info WHERE project_id = %1")
                     .arg(projectId);
     if (query.exec(selectSql)) {
-        if (query.next()) {
+        while (query.next()) {
             if (query.isNull(0) == false) {
+                EffectIndexInfo *effectIndexInfo  = new EffectIndexInfo;
                 effectIndexInfo->id               = query.value(0).toInt();
                 effectIndexInfo->projectId        = query.value(1).toInt();
                 effectIndexInfo->effectIndexName  = query.value(2).toString();
@@ -43,9 +45,10 @@ bool EffectIndexInfoService::QueryEffectIndexInfoByProjectId(EffectIndexInfo *ef
                 effectIndexInfo->effectIndexUnit  = query.value(4).toString();
                 effectIndexInfo->extendLeft       = query.value(5).toString();
                 effectIndexInfo->extendRight      = query.value(6).toString();
+                effectIndexInfoList->append(effectIndexInfo);
             }
-            ret = true;
         }
+        ret = true;
     } else {
         qDebug() << query.lastError();
     }

+ 1 - 1
QFD/dbService/EffectIndexInfoService.h

@@ -8,7 +8,7 @@ public:
     EffectIndexInfoService(QObject *parent = nullptr);
     int AddEffectIndexInfo(const EffectIndexInfo &effectIndexInfo);
     bool UpdateEffectIndexInfo(const EffectIndexInfo &effectIndexInfo);
-    bool QueryEffectIndexInfoByProjectId(EffectIndexInfo *effectIndexInfo, int projectId);
+    bool QueryEffectIndexInfoByProjectId(QList<EffectIndexInfo *> *effectIndexInfoList, int projectId);
 };
 
 #endif  // EFFECTINDEXINFOSERVICE_H

+ 261 - 27
QFD/widgets/GreyClusteringConfigWidget.cpp

@@ -3,6 +3,7 @@
 #include "MultiLevelHeaderView.h"
 #include "ui_GreyClusteringConfigWidget.h"
 #include "dbService/GradeInfoService.h"
+#include "dbService/EffectIndexInfoService.h"
 #include "CMind.h"
 
 #include <QLineEdit>
@@ -31,6 +32,7 @@ GreyClusteringConfigWidget::GreyClusteringConfigWidget(CMind *mind, int grayNumb
     ui->stackedWidget->setCurrentIndex(0);
     ui->grayNumber->setText(QString::number(grayNumber));
     initFormLayout();
+    initClusteringItems();
     refreshTableView();
 
     resize(1200, 800);
@@ -77,7 +79,7 @@ void GreyClusteringConfigWidget::initFormLayout()
                 ginfo.projectId  = projectId;
                 ginfo.gradeName  = QString("级别 %1").arg(lvl + 1);
                 ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1);
-                ginfo.type       = 0;
+                ginfo.type       = 1;
                 if (!GradeInfoService().AddGradeInfo(ginfo)) {
                     QMessageBox::warning(this, "警告", "数据库访问失败");
                 }
@@ -106,6 +108,123 @@ void GreyClusteringConfigWidget::initFormLayout()
     connect(ui->editGrayBtn, &QToolButton::clicked, [=]() { ui->stackedWidget->setCurrentIndex(0); });
 }
 
+void GreyClusteringConfigWidget::initClusteringItems()
+{
+    // 脑图层级 < 2 时无效
+    if (m_mind->levels() < 2) {
+        return;
+    }
+    m_greyClusterings.clear();
+
+    // 使用倒数第二层节点及其子节点
+    int row = 0;
+    for (CNodeData n : m_mind->nodesInLevel(m_mind->levels() - 1)) {
+        GreyClusteringItem parentItem = { n.name, row, 0, 1, 1, nullptr };
+        QList<CNodeData> subNodes     = m_mind->subNodes(n);
+        parentItem.colSpan            = subNodes.size() == 0 ? 2 : 1;  // 没有子节点,占两列,否则占一列
+        parentItem.rowSpan = subNodes.size() == 0 ? 1 : subNodes.size();  // 没有子节点,占一行,否则占子节点数目行
+
+        if (subNodes.size() == 0) {  // 没有子节点,需要录入值
+            GreyClusteringValue *sg = new GreyClusteringValue;
+            sg->units               = "";
+            sg->weiget              = 0;
+            for (const auto &gname : m_grayNames) {
+                sg->greyRanges << GreyRange { gname, true, 0, true, 0 };
+            }
+            sg->leftExtension  = 0;
+            sg->rightExtension = 0;
+            sg->oldValue       = 0;
+            sg->newValue       = 0;
+            parentItem.value.reset(sg);
+        }
+        m_greyClusterings.append(parentItem);
+
+        int subRow = row;
+        // 子节点
+        for (const CNodeData &sub : subNodes) {
+            // 因为已有父节点,所以在第2列
+            GreyClusteringItem childItem = { sub.name, subRow, 1, 1, 1, nullptr };
+            GreyClusteringValue *sg      = new GreyClusteringValue;
+            sg->units                    = "";
+            sg->weiget                   = 0;
+            for (const auto &gname : m_grayNames) {
+                sg->greyRanges << GreyRange { gname, true, 0, true, 0 };
+            }
+            sg->leftExtension  = 0;
+            sg->rightExtension = 0;
+            sg->oldValue       = 0;
+            sg->newValue       = 0;
+            childItem.value.reset(sg);
+            m_greyClusterings.append(childItem);
+            subRow++;
+        }
+
+        row += parentItem.rowSpan;
+    }
+
+    m_rowCount = row;
+
+    // 数据库对比更新
+    QList<EffectIndexInfo *> effectIndexInfoList;
+    int projectid = m_mind->root().projectId;
+    if (!EffectIndexInfoService().QueryEffectIndexInfoByProjectId(&effectIndexInfoList, projectid)) {
+        QMessageBox::warning(this, "警告", "数据库访问失败");
+        return;
+    }
+    if (effectIndexInfoList.size() == 0) {
+        for (const auto &item : m_greyClusterings) {
+            if (item.value.isNull()) {
+                continue;
+            }
+            EffectIndexInfo effInfo;
+            effInfo.projectId       = projectid;
+            effInfo.effectIndexName = item.indexName;
+            QString effectIndexValue;
+            for (const auto &range : item.value->greyRanges) {
+                effectIndexValue += ",";
+                effectIndexValue += range.leftClose ? "[" : "(";
+                effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue);
+                effectIndexValue += range.rightClose ? "]" : ")";
+            }
+            effInfo.effectIndexValue = effectIndexValue.mid(1);
+            effInfo.effectIndexUnit  = item.value->units;
+            effInfo.extendLeft       = item.value->leftExtension;
+            effInfo.extendRight      = item.value->rightExtension;
+            if (!EffectIndexInfoService().AddEffectIndexInfo(effInfo)) {
+                QMessageBox::warning(this, "警告", "数据库访问失败");
+                break;
+            }
+        }
+    } else {
+        for (auto &item : m_greyClusterings) {
+            if (item.value.isNull()) {
+                continue;
+            }
+
+            for (const auto &effInfo : effectIndexInfoList) {
+                if (effInfo->effectIndexName == item.indexName) {
+                    item.value->units          = effInfo->effectIndexUnit;
+                    item.value->leftExtension  = effInfo->extendLeft.toDouble();
+                    item.value->rightExtension = effInfo->extendRight.toDouble();
+                    //[0:0],[0:0],[0:0]
+                    QStringList valueList = effInfo->effectIndexValue.split(",");
+                    int align             = qMin(valueList.size(), item.value->greyRanges.size());
+                    for (int str = 0; str < align; str++) {
+                        //[0:0]
+                        QStringList lr = valueList.at(str).mid(1, valueList.at(str).size() - 2).split(":");
+                        item.value->greyRanges[str].leftValue  = lr.at(0).toDouble();
+                        item.value->greyRanges[str].rightValue = lr.at(1).toDouble();
+                    }
+                }
+            }
+        }
+    }
+
+    qDeleteAll(effectIndexInfoList);
+
+    connect(ui->configSaveBtn, &QToolButton::clicked, this, &GreyClusteringConfigWidget::onConfigSaveBtnClick);
+}
+
 /**
 #if 0  // 竖直表头
     auto vHeader = new MultiLevelHeaderView(Qt::Vertical, 9, 3, t);
@@ -153,8 +272,6 @@ struct IndexItem
 
 void GreyClusteringConfigWidget::refreshTableView()
 {
-    const int nodeDepth = 3;  // 节点深度
-
     QTableView *t = ui->grayConfigTableView;
     m_model->clear();
 
@@ -185,39 +302,41 @@ void GreyClusteringConfigWidget::refreshTableView()
         t->setHorizontalHeader(hHeader);
     }
 
-    QVector<IndexItem> items;
-    items << IndexItem { "火力", 0, 0, 9, 1 };
-    items << IndexItem { "火炮口径", 0, 1, 1, 2 };
-    items << IndexItem { "初速", 1, 1, 3, 1 };
-    items << IndexItem { "穿甲弹", 1, 2, 1, 1 };
-    items << IndexItem { "破甲弹", 2, 2, 1, 1 };
-    items << IndexItem { "榴弹", 3, 2, 1, 1 };
-
-    items << IndexItem { "首发命中", 4, 1, 1, 2 };
-    items << IndexItem { "直射距离", 5, 1, 1, 2 };
-    items << IndexItem { "弹药基数", 6, 1, 1, 2 };
-    items << IndexItem { "时间", 7, 1, 2, 1 };
-    items << IndexItem { "静对静", 7, 2, 1, 1 };
-    items << IndexItem { "静对动", 8, 2, 1, 1 };
     m_model->setColumnCount(nodeDepth + 3 + m_grayNames.size());
-    m_model->setRowCount(9);  // 最大9行
+    m_model->setRowCount(m_rowCount);
 
-    for (auto &item : items) {
-        auto s = new QStandardItem(item.name);
+    // 其余的都可输入
+    for (int r = 0; r < m_model->rowCount(); ++r) {
+        for (int c = nodeDepth; c < m_model->columnCount(); ++c) {
+            auto s = new QStandardItem();
+            s->setTextAlignment(Qt::AlignCenter);
+            m_model->setItem(r, c, s);
+        }
+    }
+
+    for (auto &item : m_greyClusterings) {
+        // 指标栏
+        auto s = new QStandardItem(item.indexName);
         s->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
         s->setTextAlignment(Qt::AlignCenter);
-        s->setToolTip(item.name);
+        s->setToolTip(item.indexName);
         m_model->setItem(item.row, item.col, s);
         if (item.rowSpan > 1 || item.colSpan > 1) {
             t->setSpan(item.row, item.col, item.rowSpan, item.colSpan);
         }
-    }
 
-    for (int r = 0; r < m_model->rowCount(); ++r) {
-        for (int c = nodeDepth; c < m_model->columnCount(); ++c) {
-            auto s = new QStandardItem();
-            s->setTextAlignment(Qt::AlignCenter);
-            m_model->setItem(r, c, s);
+        if (!item.value.isNull()) {
+            m_model->item(item.row, nodeDepth)->setText(item.value->units);  // 指标
+            for (int r = 0; r < item.value->greyRanges.size(); r++) {
+                m_model->item(item.row, nodeDepth + r + 1)
+                        ->setText(QString("%1%2, %3%4")
+                                          .arg((item.value->greyRanges[r].leftClose ? "[" : "("))
+                                          .arg(item.value->greyRanges[r].leftValue)
+                                          .arg(item.value->greyRanges[r].rightValue)
+                                          .arg((item.value->greyRanges[r].rightClose ? "]" : ")")));
+            }
+            m_model->item(item.row, nodeDepth + m_grayNumber + 1)->setText(QString::number(item.value->leftExtension));
+            m_model->item(item.row, nodeDepth + m_grayNumber + 2)->setText(QString::number(item.value->rightExtension));
         }
     }
 
@@ -277,3 +396,118 @@ void GreyClusteringConfigWidget::onConfirmClick()
     refreshTableView();
     ui->stackedWidget->setCurrentIndex(1);
 }
+
+static bool isNeedUpdate(const EffectIndexInfo &effInfo, const GreyClusteringItem &item)
+{
+    if (effInfo.effectIndexUnit != item.value->units) {
+        return true;
+    }
+
+    QString effectIndexValue;
+    for (const auto &range : item.value->greyRanges) {
+        effectIndexValue += ",";
+        effectIndexValue += range.leftClose ? "[" : "(";
+        effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue);
+        effectIndexValue += range.rightClose ? "]" : ")";
+    }
+
+    if (effInfo.effectIndexValue != effectIndexValue.mid(1)) {
+        return true;
+    }
+
+    if (effInfo.extendLeft.toDouble() != item.value->leftExtension) {
+        return true;
+    }
+
+    if (effInfo.extendRight.toDouble() != item.value->rightExtension) {
+        return true;
+    }
+
+    return false;
+}
+
+void GreyClusteringConfigWidget::onConfigSaveBtnClick()
+{
+    for (auto &item : m_greyClusterings) {
+        if (item.value.isNull()) {
+            continue;
+        }
+
+        item.value->units = m_model->item(item.row, nodeDepth)->text();  // 指标
+        for (int r = 0; r < item.value->greyRanges.size(); r++) {
+            QString str                          = m_model->item(item.row, nodeDepth + r + 1)->text();
+            item.value->greyRanges[r].leftClose  = str[0] == "[";
+            item.value->greyRanges[r].rightClose = str.right(1) == "]";
+            QStringList list                     = str.mid(1, str.size() - 2).replace(" ", "").split(",");
+            item.value->greyRanges[r].leftValue  = list.at(0).toDouble();
+            item.value->greyRanges[r].rightValue = list.at(1).toDouble();
+        }
+        item.value->leftExtension  = m_model->item(item.row, nodeDepth + m_grayNumber + 1)->text().toDouble();
+        item.value->rightExtension = m_model->item(item.row, nodeDepth + m_grayNumber + 2)->text().toDouble();
+    }
+
+    // 更新数据库
+    QList<EffectIndexInfo *> effectIndexInfoList;
+    int projectid = m_mind->root().projectId;
+    if (!EffectIndexInfoService().QueryEffectIndexInfoByProjectId(&effectIndexInfoList, projectid)) {
+        QMessageBox::warning(this, "警告", "数据库访问失败");
+        return;
+    }
+
+    for (auto &item : m_greyClusterings) {
+        if (item.value.isNull()) {
+            continue;
+        }
+
+        bool found = false;
+        for (auto &effInfo : effectIndexInfoList) {
+            if (effInfo->effectIndexName == item.indexName) {
+                found = true;
+
+                if (isNeedUpdate(*effInfo, item)) {
+                    QString effectIndexValue;
+                    for (const auto &range : item.value->greyRanges) {
+                        effectIndexValue += ",";
+                        effectIndexValue += range.leftClose ? "[" : "(";
+                        effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue);
+                        effectIndexValue += range.rightClose ? "]" : ")";
+                    }
+                    effInfo->effectIndexValue = effectIndexValue.mid(1);
+                    effInfo->effectIndexUnit  = item.value->units;
+                    effInfo->extendLeft       = QString::number(item.value->leftExtension);
+                    effInfo->extendRight      = QString::number(item.value->rightExtension);
+                    if (!EffectIndexInfoService().UpdateEffectIndexInfo(*effInfo)) {
+                        QMessageBox::warning(this, "警告", "数据库访问失败");
+                        qDeleteAll(effectIndexInfoList);
+                        return;
+                    }
+                }
+
+                break;
+            }
+        }
+
+        if (!found) {  // 新增
+            EffectIndexInfo effInfo;
+            effInfo.projectId       = projectid;
+            effInfo.effectIndexName = item.indexName;
+            QString effectIndexValue;
+            for (const auto &range : item.value->greyRanges) {
+                effectIndexValue += ",";
+                effectIndexValue += range.leftClose ? "[" : "(";
+                effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue);
+                effectIndexValue += range.rightClose ? "]" : ")";
+            }
+            effInfo.effectIndexValue = effectIndexValue.mid(1);
+            effInfo.effectIndexUnit  = item.value->units;
+            effInfo.extendLeft       = QString::number(item.value->leftExtension);
+            effInfo.extendRight      = QString::number(item.value->rightExtension);
+            if (!EffectIndexInfoService().AddEffectIndexInfo(effInfo)) {
+                QMessageBox::warning(this, "警告", "数据库访问失败");
+                break;
+            }
+        }
+    }
+
+    qDeleteAll(effectIndexInfoList);
+}

+ 8 - 0
QFD/widgets/GreyClusteringConfigWidget.h

@@ -1,6 +1,7 @@
 #ifndef GREYCLUSTERINGCONFIGWIDGET_H
 #define GREYCLUSTERINGCONFIGWIDGET_H
 
+#include "GreyClusteringSampleTable.h"
 #include <QStandardItemModel>
 #include <QWidget>
 
@@ -19,18 +20,25 @@ public:
 
 private:
     void initFormLayout();
+    void initClusteringItems();
     void refreshTableView();
 
 private slots:
     void onConfirmClick();
+    void onConfigSaveBtnClick();
 
 private:
     Ui::GreyClusteringConfigWidget *ui;
 
+    const int nodeDepth = 2;  // 节点深度
+
     CMind *m_mind;
     int m_grayNumber;
     QStringList m_grayNames;
     QStandardItemModel *m_model;
+    int m_rowCount;
+
+    QVector<GreyClusteringItem> m_greyClusterings;
 };
 
 #endif  // GREYCLUSTERINGCONFIGWIDGET_H

+ 6 - 20
QFD/widgets/GreyClusteringConfigWidget.ui

@@ -161,14 +161,14 @@
      </widget>
      <widget class="QWidget" name="configPage">
       <layout class="QGridLayout" name="gridLayout_3">
-       <item row="1" column="2">
-        <widget class="QToolButton" name="clearBtn">
+       <item row="1" column="1">
+        <widget class="QToolButton" name="editGrayBtn">
          <property name="text">
-          <string>清除</string>
+          <string>灰类编辑</string>
          </property>
          <property name="icon">
           <iconset resource="../../QFluentWidgets/qfluentwidgets.qrc">
-           <normaloff>:/qfluentwidgets/images/color_dialog/Clear_black.svg</normaloff>:/qfluentwidgets/images/color_dialog/Clear_black.svg</iconset>
+           <normaloff>:/qfluentwidgets/images/icons/Edit_black.svg</normaloff>:/qfluentwidgets/images/icons/Edit_black.svg</iconset>
          </property>
          <property name="toolButtonStyle">
           <enum>Qt::ToolButtonTextBesideIcon</enum>
@@ -188,10 +188,10 @@
          </property>
         </spacer>
        </item>
-       <item row="0" column="0" colspan="4">
+       <item row="0" column="0" colspan="3">
         <widget class="QTableView" name="grayConfigTableView"/>
        </item>
-       <item row="1" column="3">
+       <item row="1" column="2">
         <widget class="QToolButton" name="configSaveBtn">
          <property name="text">
           <string>保存</string>
@@ -205,20 +205,6 @@
          </property>
         </widget>
        </item>
-       <item row="1" column="1">
-        <widget class="QToolButton" name="editGrayBtn">
-         <property name="text">
-          <string>灰类编辑</string>
-         </property>
-         <property name="icon">
-          <iconset resource="../../QFluentWidgets/qfluentwidgets.qrc">
-           <normaloff>:/qfluentwidgets/images/icons/Edit_black.svg</normaloff>:/qfluentwidgets/images/icons/Edit_black.svg</iconset>
-         </property>
-         <property name="toolButtonStyle">
-          <enum>Qt::ToolButtonTextBesideIcon</enum>
-         </property>
-        </widget>
-       </item>
       </layout>
      </widget>
     </widget>