Parcourir la source

Update project_quota添加note字段

yue il y a 1 mois
Parent
commit
1b03c5f661

+ 1 - 0
SourceCode/IntelligentRailwayCosting/.script/init_mysql.sql

@@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS project_quota (
     ex_row VARCHAR(4000) COMMENT '该行内容',
     ex_unit VARCHAR(50) COMMENT 'excel中给出的单位',
     ex_amount FLOAT COMMENT 'excel中给出的数量',
+    note VARCHAR(4000) COMMENT '说明',
     is_change INT NOT NULL DEFAULT 1 COMMENT '是否变更(0:未变更,1:已变更)',
     send_status INT NOT NULL DEFAULT 0 COMMENT '推送状态(0:未推送,1:推送中 ,2:已推送, 3:推送失败, 4:已修改)',
     send_time DATETIME COMMENT '推送时间',

+ 1 - 0
SourceCode/IntelligentRailwayCosting/.script/init_sqlserver.sql

@@ -85,6 +85,7 @@ CREATE TABLE [dbo].[project_quota] (
     [ex_row] NVARCHAR(4000) NULL,
     [ex_unit] NVARCHAR(50) NULL,
     [ex_amount] FLOAT NULL,
+    [note] NVARCHAR(4000) NULL,
     [is_change] INT NOT NULL DEFAULT 1,
     [send_status] INT NOT NULL DEFAULT 0,
     [send_time] DATETIME NULL,

+ 38 - 33
SourceCode/IntelligentRailwayCosting/app/core/dtos/excel_parse.py

@@ -52,18 +52,18 @@ class ExcelParseFileDto:
 
 class ExcelParseDto:
     def __init__(
-        self,
-        task_id: int,
-        version: str,
-        project_id: str,
-        project_name: str,
-        project_stage: str,
-        selected_zgs_id: int,
-        zgs_list: list[ExcelParseZgsDto],
-        selected_chapter: ExcelParseItemDto,
-        # hierarchy: list[ExcelParseItemDto],
-        # components: list[ExcelParseItemDto],
-        files: list[ExcelParseFileDto],
+            self,
+            task_id: int,
+            version: str,
+            project_id: str,
+            project_name: str,
+            project_stage: str,
+            selected_zgs_id: int,
+            zgs_list: list[ExcelParseZgsDto],
+            selected_chapter: ExcelParseItemDto,
+            # hierarchy: list[ExcelParseItemDto],
+            # components: list[ExcelParseItemDto],
+            files: list[ExcelParseFileDto],
     ):
         self.task_id = task_id
         self.version = version
@@ -110,24 +110,26 @@ class ExcelParseResultDataDto:
     #     "ex_row": 该⾏内容,由逗号连接多个单元格得到,
     #     "ex_unit": excel中给出的单位,
     #     "ex_amount": excel中给出的数量, // number
+    #     "note": 说明,例如"需根据标号和运距调整"
     # }
     def __init__(
-        self,
-        zgs_id: int,  # 总概算id
-        zgs_code: str,  # 总概算编号
-        item_id: int,  # 条⽬序号
-        item_code: str,  # 条⽬编码
-        entry_name: str,  # ⼯程或费⽤项⽬名称,来⾃于定额表,
-        dinge_code: str,  # 定额编号,
-        dinge_adjust: str,  # 定额调整,
-        units: str,  # 单位,
-        amount: float,  # 数量,
-        target_id: int,  # ⽤户数据库中条⽬的id,-1表示没有,
-        ex_file_id: str,  # excel⽂件id,
-        ex_cell: str,  # 数量单元格位置,例如 "C17",
-        ex_row: str,  # 该⾏内容,由逗号连接多个单元格得到,
-        ex_unit: str,  # excel中给出的单位,
-        ex_amount: float,  # excel中给出的数量,
+            self,
+            zgs_id: int,  # 总概算id
+            zgs_code: str,  # 总概算编号
+            item_id: int,  # 条⽬序号
+            item_code: str,  # 条⽬编码
+            entry_name: str,  # ⼯程或费⽤项⽬名称,来⾃于定额表,
+            dinge_code: str,  # 定额编号,
+            dinge_adjust: str,  # 定额调整,
+            units: str,  # 单位,
+            amount: float,  # 数量,
+            target_id: int,  # ⽤户数据库中条⽬的id,-1表示没有,
+            ex_file_id: str,  # excel⽂件id,
+            ex_cell: str,  # 数量单元格位置,例如 "C17",
+            ex_row: str,  # 该⾏内容,由逗号连接多个单元格得到,
+            ex_unit: str,  # excel中给出的单位,
+            ex_amount: float,  # excel中给出的数量,
+            note: str,  # 说明,
     ):
         self.zgs_id = zgs_id
         self.zgs_code = zgs_code
@@ -145,6 +147,7 @@ class ExcelParseResultDataDto:
         self.ex_row = ex_row
         self.ex_unit = ex_unit
         self.ex_amount = ex_amount
+        self.note = note
 
     @classmethod
     def from_dict(cls, data: dict):
@@ -168,6 +171,7 @@ class ExcelParseResultDataDto:
             ex_row=data.get("ex_row", ""),
             ex_unit=data.get("ex_unit", ""),
             ex_amount=data.get("ex_amount", 0.0),
+            note=data.get("note", ""),
         )
 
     def to_dict(self):
@@ -189,16 +193,17 @@ class ExcelParseResultDataDto:
             "ex_row": self.ex_row,
             "ex_unit": self.ex_unit,
             "ex_amount": self.ex_amount,
+            "note": self.note,
         }
 
 
 class ExcelParseResultDto:
     def __init__(
-        self,
-        task_id: int,
-        result: int = -1,
-        reason: str = "",
-        data: list[ExcelParseResultDataDto] = None,
+            self,
+            task_id: int,
+            result: int = -1,
+            reason: str = "",
+            data: list[ExcelParseResultDataDto] = None,
     ):
         self.task_id = task_id
         self.result = result  # -1-失败;0-运行中;1-成功

+ 2 - 0
SourceCode/IntelligentRailwayCosting/app/core/dtos/project_quota.py

@@ -26,6 +26,7 @@ class ProjectQuotaDto(BaseModel):
     ex_row: Optional[str] = None
     ex_unit: Optional[str] = None
     ex_amount: Optional[float] = None
+    note: Optional[str] = None
     is_change: int = 1
     send_status: int = 0
     send_time: Optional[datetime] = None
@@ -57,6 +58,7 @@ class ProjectQuotaDto(BaseModel):
             ex_row=model.ex_row,
             ex_unit=model.ex_unit,
             ex_amount=model.ex_amount,
+            note=model.note,
             is_change=model.is_change,
             send_status=model.send_status,
             send_time=model.send_time,

+ 3 - 2
SourceCode/IntelligentRailwayCosting/app/core/models/project_quota.py

@@ -20,11 +20,12 @@ class ProjectQuotaModel(Base):
     entry_name = Column(String(255), comment="工程或费用项目名称")
     units = Column(String(20), comment="单位")
     amount = Column(Float, comment="数量")
-    ex_file = Column(String(5000), comment="excel⽂件")
+    ex_file = Column(String(4000), comment="excel⽂件")
     ex_cell = Column(String(50), comment='数量单元格位置,例如"C17"')
-    ex_row = Column(String(5000), comment="该⾏内容,由逗号连接多个单元格得到")
+    ex_row = Column(String(4000), comment="该⾏内容,由逗号连接多个单元格得到")
     ex_unit = Column(String(50), comment="excel中给出的单位")
     ex_amount = Column(Float, comment="excel中给出的数量")
+    note = Column(String(4000), comment="说明")
     is_change = Column(
         Integer,
         nullable=False,

+ 14 - 12
SourceCode/IntelligentRailwayCosting/app/executor/task_processor.py

@@ -176,14 +176,14 @@ class TaskProcessor:
             return None, msg
 
     def _build_api_body(
-        self,
-        task: ProjectTaskDto,
-        project: ProjectDto,
-        budgets: list[TotalBudgetInfoDto],
-        chapter: ChapterDto,
-        # parents: list[ChapterDto],
-        # children: list[ChapterDto],
-        files: list[ExcelParseFileDto],
+            self,
+            task: ProjectTaskDto,
+            project: ProjectDto,
+            budgets: list[TotalBudgetInfoDto],
+            chapter: ChapterDto,
+            # parents: list[ChapterDto],
+            # children: list[ChapterDto],
+            files: list[ExcelParseFileDto],
     ):
         try:
             budgets_data = [ExcelParseZgsDto.from_dto(budget) for budget in budgets]
@@ -233,10 +233,10 @@ class TaskProcessor:
             raise Exception(msg)
 
     def _insert_data(
-        self,
-        task: ProjectTaskDto,
-        project: ProjectDto,
-        data: list[ExcelParseResultDataDto],
+            self,
+            task: ProjectTaskDto,
+            project: ProjectDto,
+            data: list[ExcelParseResultDataDto],
     ):
         try:
             self._logger.debug(f"开始插入数据:{task.task_name}")
@@ -266,6 +266,7 @@ class TaskProcessor:
                     quota_dto.ex_row = item.ex_row
                     quota_dto.ex_unit = item.ex_unit
                     quota_dto.ex_amount = item.ex_amount
+                    quota_dto.note = item.note
                     quota_dto.send_error = None
                     self._quota_store.update_quota(quota_dto)
                 else:
@@ -290,6 +291,7 @@ class TaskProcessor:
                         ex_row=item.ex_row,
                         ex_unit=item.ex_unit,
                         ex_amount=item.ex_amount,
+                        note=item.note,
                         created_by=task.created_by,
                     )
                     self._quota_store.create_quota(quota_dto)

+ 1 - 0
SourceCode/IntelligentRailwayCosting/app/services/project_quota.py

@@ -184,6 +184,7 @@ class ProjectQuotaService:
                 quota_dto.ex_cell = quota.ex_cell
                 quota_dto.ex_unit = quota.ex_unit
                 quota_dto.ex_amount = quota.ex_amount
+                quota_dto.note = quota.note
 
             # self.update_process_status(quota_dto.id,4)
             LogRecordHelper.log_success(

+ 2 - 0
SourceCode/IntelligentRailwayCosting/app/stores/railway_costing_mysql/project_quota.py

@@ -220,6 +220,7 @@ class ProjectQuotaStore:
                 ex_row=quota_dto.ex_row,
                 ex_unit=quota_dto.ex_unit,
                 ex_amount=quota_dto.ex_amount,
+                note=quota_dto.note,
                 is_change=quota_dto.is_change,
                 send_status=SendStatusEnum.NEW.value,
                 send_time=quota_dto.send_time,
@@ -257,6 +258,7 @@ class ProjectQuotaStore:
             quota.ex_row = quota_dto.ex_row
             quota.ex_unit = quota_dto.ex_unit
             quota.ex_amount = quota_dto.ex_amount
+            quota.note = quota_dto.note
             quota.is_change = quota_dto.is_change
             quota.send_status = quota_dto.send_status
             quota.send_error = None

+ 2 - 0
SourceCode/IntelligentRailwayCosting/app/stores/railway_costing_sqlserver/project_quota.py

@@ -220,6 +220,7 @@ class ProjectQuotaStore:
                 ex_row=quota_dto.ex_row,
                 ex_unit=quota_dto.ex_unit,
                 ex_amount=quota_dto.ex_amount,
+                note=quota_dto.note,
                 send_status=SendStatusEnum.NEW.value,
                 is_change=quota_dto.is_change,
                 send_time=quota_dto.send_time,
@@ -257,6 +258,7 @@ class ProjectQuotaStore:
             quota.ex_row = quota_dto.ex_row
             quota.ex_unit = quota_dto.ex_unit
             quota.ex_amount = quota_dto.ex_amount
+            quota.note = quota_dto.note
             quota.is_change = 1
             quota.send_status = SendStatusEnum.CHANGE.value
             quota.send_error = None

+ 22 - 8
SourceCode/IntelligentRailwayCosting/app/views/static/base/css/styles.css

@@ -35,8 +35,8 @@
     color: var(--bs-primary);
 }
 
-body>.container,
-body>.container-fluid {
+body > .container,
+body > .container-fluid {
     padding: 0;
     margin: 0;
 }
@@ -68,26 +68,26 @@ body>.container-fluid {
     height: 45px;
 }
 
-.table-box td>.link:hover {
+.table-box td > .link:hover {
     border-bottom: 2px solid;
 }
 
-.table-box td>span {
+.table-box td > span {
     font-size: 13px;
 }
 
-.table-box td>.btn {
+.table-box td > .btn {
     padding: calc(.2rem + 1px) calc(.4rem + 1px) !important;
     margin: 0 5px;
     --bs-btn-border-radius: .3rem;
 }
 
-.table-box td>.btn-icon {
+.table-box td > .btn-icon {
     width: 25px !important;
     height: 25px !important;
 }
 
-.table-box td>.link:hover {
+.table-box td > .link:hover {
     border-bottom: 2px solid;
 }
 
@@ -109,6 +109,16 @@ body>.container-fluid {
     color: #666;
 }
 
+.table-box tr.tr-waring td {
+    background: #FFFACD;
+    box-shadow: none;
+}
+
+.table-box tr.tr-waring:hover td {
+    --bs-table-bg-state: #FFE4B5;
+    background: #FFE4B5;
+}
+
 .table-box td .one-line {
     white-space: nowrap;
     overflow: hidden;
@@ -121,6 +131,10 @@ body>.container-fluid {
     display: inline-flex
 }
 
+.edit-td .edit-label {
+    cursor: pointer;
+}
+
 .edit-td .edit-label.hide {
     display: none;
 }
@@ -150,7 +164,7 @@ body>.container-fluid {
 }
 
 .form-check-input:disabled,
-.form-check-input:disabled+.form-check-label {
+.form-check-input:disabled + .form-check-label {
     cursor: not-allowed;
 }
 

+ 28 - 25
SourceCode/IntelligentRailwayCosting/app/views/static/base/js/utils.js

@@ -17,7 +17,7 @@ function IwbAjax(opt) {
     if (opt.data === undefined) {
         opt.data = {}
     }
-    opt = $.extend({}, { isAlert: true, }, opt)
+    opt = $.extend({}, {isAlert: true,}, opt)
     fetch(opt.url, {
         method: opt.method,
         headers: opt.headers || {
@@ -74,6 +74,7 @@ function IwbTable(table, opts, isReload) {
         rows: new Set(),
         checkBoxWidth: 40,
         checkBoxDisable: undefined,
+        canEdit: undefined,
         pageSize: 15,
         pageNum: 1,
         search: {
@@ -92,7 +93,7 @@ function IwbTable(table, opts, isReload) {
         }
         $table.data('options', opt)
         loading()
-        const data = $.extend({}, opt.search, { pageNum: opt.pageNum, pageSize: opt.pageSize })
+        const data = $.extend({}, opt.search, {pageNum: opt.pageNum, pageSize: opt.pageSize})
         fetch(opt.url, {
             method: 'POST',
             headers: {
@@ -153,42 +154,44 @@ function IwbTable(table, opts, isReload) {
         }
         if (rows && rows.length) {
             for (let i = 0; i < rows.length; i++) {
-                const row = rows[i]
-                body_str += `<tr data-id="${row[opt.idFiled]}">`
+                const row = rows[i], canEdit = opt.canEdit && opt.canEdit(row)
+                let trStr = "", trClassStr = ""
                 if (opt.checkBox) {
                     const disabled_checkbox = opt.checkBoxDisable && opt.checkBoxDisable(row) ? 'disabled' : ''
                     if (opt.selected_ids.size && opt.selected_ids.has(row[opt.idFiled] + "")) {
                         if (disabled_checkbox === '') {
-                            body_str += `<td style="${opt.checkBoxWidth ? `width: ${opt.checkBoxWidth}px;` : ``}">${checkBoxDiv.format(row[opt.idFiled], `${opt.tableCheckboxName}`, `checked`)}</td>`
+                            trStr += `<td style="${opt.checkBoxWidth ? `width: ${opt.checkBoxWidth}px;` : ``}">${checkBoxDiv.format(row[opt.idFiled], `${opt.tableCheckboxName}`, `checked`)}</td>`
                         } else {
-                            body_str += `<td style="${opt.checkBoxWidth ? `width: ${opt.checkBoxWidth}px;` : ``}">${checkBoxDiv.format(row[opt.idFiled], `${opt.tableCheckboxName}`, `${disabled_checkbox}`)}</td>`
+                            trStr += `<td style="${opt.checkBoxWidth ? `width: ${opt.checkBoxWidth}px;` : ``}">${checkBoxDiv.format(row[opt.idFiled], `${opt.tableCheckboxName}`, `${disabled_checkbox}`)}</td>`
                         }
                     } else {
                         check_all = false
-                        body_str += `<td style="${opt.checkBoxWidth ? `width: ${opt.checkBoxWidth}px;` : ``}">${checkBoxDiv.format(row[opt.idFiled], `${opt.tableCheckboxName}`, `${disabled_checkbox}`)}</td>`
+                        trStr += `<td style="${opt.checkBoxWidth ? `width: ${opt.checkBoxWidth}px;` : ``}">${checkBoxDiv.format(row[opt.idFiled], `${opt.tableCheckboxName}`, `${disabled_checkbox}`)}</td>`
                     }
                 }
                 for (let j = 0; j < opt.columns.length; j++) {
                     const col = opt.columns[j],
+                        isEdit = col.isEdit && canEdit,
                         style = `${col.tdStyle ? `${col.tdStyle};` : ``}`,
-                        classStr = `${col.isEdit ? 'edit-td' : ''}`,
+                        classStr = `${isEdit ? 'edit-td' : ''}`,
                         col_data = row[col.data] === undefined || row[col.data] === null ? '-' : row[col.data]
-                    body_str += `<td class="${classStr}" style="${style}" data-key="${col.data}" data-val="${col_data}">`
-                    let str = ''
+                    trStr += `<td class="${classStr}" style="${style}" data-key="${col.data}" data-val="${col_data}" >`
+                    let tdStr = ''
                     if (col.render) {
-                        str += col.render(row, rows)
+                        tdStr += col.render(row, rows)
                     } else {
-                        str += col_data
+                        tdStr += col_data
                     }
-                    if (col.isEdit) {
-                        body_str += col.render ? str : `<span class="edit-label"><span class="edit-text">${str}</span></span>`
-                        body_str += `<div class="edit-td-input"><input class="form-control form-control-sm" data-col="" value="${col_data}"/></div>`
+                    if (isEdit) {
+                        trStr += col.render ? tdStr : `<span class="edit-label"><span class="edit-text">${tdStr}</span></span>`
+                        trStr += `<div class="edit-td-input"><input class="form-control form-control-sm" data-col="" value="${col_data}"/></div>`
                     } else {
-                        body_str += str
+                        trStr += tdStr
                     }
-                    body_str += `</td>`
+                    trStr += `</td>`
                 }
-                body_str += '</tr>'
+                trClassStr = opt.trClass && typeof opt.trClass === 'function' ? opt.trClass(row) : typeof opt.trClass === 'string' ? opt.trClass : opt.trClass || ""
+                body_str += `<tr class="${trClassStr}" data-id="${row[opt.idFiled]}">${trStr}</tr>`
             }
         } else {
             body_str += '<tr><td colspan="' + opt.columns.length + '" class="text-center">暂无数据</td></tr>'
@@ -314,9 +317,9 @@ function IwbTable(table, opts, isReload) {
 
         str += `<div class="dt-info"><strong> 共 ${total} 条</strong>,当前第 ${pageNum}/${totalPages} 页,每页</div>`
         str += `<div><select class="form-select form-select-solid form-select-sm" onchange="IwbTableChangePageSize(this)">`
-            ;[15, 25, 50, 100].forEach((size) => {
-                str += `<option value="${size}" ${pageSize === size ? ' selected' : ''}>${size}</option>`
-            })
+        ;[15, 25, 50, 100].forEach((size) => {
+            str += `<option value="${size}" ${pageSize === size ? ' selected' : ''}>${size}</option>`
+        })
         str += '</select>条</div>'
         str += '</div>'
 
@@ -376,7 +379,7 @@ function IwbTable(table, opts, isReload) {
         const $table = $(table), opt = $table.data('options'), tableEl = $table[0], rows = tableEl.rows,
             header = rows[0],
             col_length = header.cells.length, col_start = opt.checkBox ? 1 : 0;
-        let self = { mouseDown: false }, tableX = header.clientWidth;
+        let self = {mouseDown: false}, tableX = header.clientWidth;
 
         for (let i = 0; i < rows.length; i++) {
             for (let j = col_start; j < col_length; j++) {
@@ -446,7 +449,7 @@ function IwbTableSearch(that) {
             delete search[$(el).attr('name')]
         }
     })
-    IwbTable($table, { search: search, pageNum: 1, selected_ids: new Set(), selected_rows: new Set() })
+    IwbTable($table, {search: search, pageNum: 1, selected_ids: new Set(), selected_rows: new Set()})
 }
 
 function IwbTableResetSearch(that) {
@@ -457,13 +460,13 @@ function IwbTableResetSearch(that) {
 
 function IwbTableJumpPage(that, pageNum) {
     const $table = $(that).closest('.table-box').find('.table')
-    IwbTable($table, { pageNum: pageNum })
+    IwbTable($table, {pageNum: pageNum})
 }
 
 function IwbTableChangePageSize(that) {
     const $table = $(that).closest('.table-box').find('.table')
     const pageSize = parseInt($(that).val())
-    IwbTable($table, { pageSize: pageSize })
+    IwbTable($table, {pageSize: pageSize})
 }
 
 function IwbTableGetSelectedIds(table) {

+ 11 - 2
SourceCode/IntelligentRailwayCosting/app/views/static/project/quota_info.js

@@ -381,6 +381,12 @@ function LoadQuotaTable(table) {
         checkBoxDisable: (row) => {
             return row.send_status === 200
         },
+        canEdit: (row) => {
+            return row.send_status !== 200
+        },
+        trClass: (row) => {
+            return row.note || !row.quota_code ? 'tr-waring' : ''
+        },
         columns: [
             // {
             //     title: '序号',
@@ -423,10 +429,13 @@ function LoadQuotaTable(table) {
                 width: '100px',
                 isEdit: true,
                 render: (row) => {
+                    if (!row.quota_code) {
+                        return `<span class="badge badge-light-danger edit-label" data-bs-toggle="tooltip" data-bs-placement="top" title="${row.note ? `说明:${row.note}` : '未查询到'}" ><span class="edit-text">未查询到</span></span>`
+                    }
                     if (row.quota_id) {
-                        return `<span class="badge badge-light-danger edit-label" data-bs-toggle="tooltip" data-bs-placement="top" title="可覆盖系统数据:${row.quota_id}" ><span class="edit-text">${row.quota_code}</span></span>`
+                        return `<span class="badge badge-light-info edit-label" data-bs-toggle="tooltip" data-bs-placement="top" title="可覆盖系统数据:${row.quota_id} | ${row.note ? `说明:${row.note}` : ''}" ><span class="edit-text">${row.quota_code}</span></span>`
                     } else {
-                        return `<span class="badge badge-light-primary edit-label" data-bs-toggle="tooltip" data-bs-placement="top" title="未关联系统数据" ><span class="edit-text">${row.quota_code}</span></span>`
+                        return `<span class="badge badge-light-primary edit-label" data-bs-toggle="tooltip" data-bs-placement="top" title="未关联系统数据 | ${row.note ? `说明:${row.note}` : ''}" ><span class="edit-text">${row.quota_code}</span></span>`
                     }
                 }
             },