From 23006c64e0d7478ff2e8c723f2bfda3781b65b09 Mon Sep 17 00:00:00 2001
From: zhang_12370 <z2864490065@outlook.com>
Date: 星期五, 18 七月 2025 11:59:20 +0800
Subject: [PATCH] 1、优化配煤计算器 2、优化正是库存数据渲染问题

---
 src/views/calculator/index.vue | 1361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 1,260 insertions(+), 101 deletions(-)

diff --git a/src/views/calculator/index.vue b/src/views/calculator/index.vue
index f2478cc..814e57f 100644
--- a/src/views/calculator/index.vue
+++ b/src/views/calculator/index.vue
@@ -6,16 +6,48 @@
         <div class="scroll">
           <div>
             <div class="title">閫氱敤璁剧疆</div>
-            <el-form :inline="true" :model="formInline" class="demo-form-inline" label-width="110" label-position="top">
-              <el-row>
-                <el-col :span="12">
+            <el-form
+              :inline="true"
+              :model="formInline"
+              class="demo-form-inline"
+              label-width="110"
+              label-position="top"
+            >
+              <el-row :gutter="16">
+                <el-col :span="8">
                   <el-form-item label="寰呴厤鐓ょ鏁伴噺">
-                    <el-input v-model="formInline.num" type="number" clearable @change="updateCoalFields" />
+                    <el-input
+                      v-model="formInline.num"
+                      type="number"
+                      style="width: 100%"
+                      @change="updateCoalFields"
+                    />
                   </el-form-item>
                 </el-col>
-                <el-col :span="12">
+                <el-col :span="8">
                   <el-form-item label="鍙備笌閰嶇叅鎬诲惃鏁�">
-                    <el-input v-model="formInline.count" type="number" clearable />
+                    <el-input
+                      v-model="formInline.totalTonnage"
+                      type="number"
+                      style="width: 100%"
+                    >
+                      <template v-slot:suffix>
+                        <i style="font-style: normal">鍚�</i>
+                      </template>
+                    </el-input>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                  <el-form-item label="姣忛摬閲嶉噺">
+                    <el-input
+                      v-model="formInline.scoopWeight"
+                      type="number"
+                      style="width: 100%"
+                    >
+                      <template v-slot:suffix>
+                        <i style="font-style: normal">鍚�</i>
+                      </template>
+                    </el-input>
                   </el-form-item>
                 </el-col>
               </el-row>
@@ -23,119 +55,892 @@
           </div>
           <div>
             <div class="title">鐓ょ灞炴��</div>
-            <el-form :model="coalForms" :inline="true" label-width="110" label-position="top">
-              <div v-for="(item, index) in coalForms" :key="index" style="margin-bottom: 15px;">
-                <el-row>
-                  <el-col :span="6">
-                    <el-form-item label="鐓ょ绫诲瀷">
-                      <el-select v-model="item.type" placeholder="璇烽�夋嫨" clearable style="width: 200px">
-                        <el-option label="宸叉湁鐓�" value="宸叉湁鐓�" />
-                        <el-option label="鏈煡鐓�" value="鏈煡鐓�" />
-                      </el-select>
-                    </el-form-item>
-                  </el-col>
-                  <el-col :span="6">
-                    <el-form-item :label="'鐓ょ' + (index + 1)">
-                      <el-input v-model="item.name" clearable v-if="item.type !== '宸叉湁鐓�'" placeholder=" 璇疯緭鍏�"/>
-                      <el-select v-model="item.name" placeholder="璇烽�夋嫨" clearable v-else style="width: 200px">
-                        <el-option label="宸叉湁鐓�" value="宸叉湁鐓�" />
-                        <el-option label="鏈煡鐓�" value="鏈煡鐓�" />
-                      </el-select>
-                    </el-form-item>
-                  </el-col>
-                  <el-col :span="6">
-                    <el-form-item label="鍙戠儹閲�(CV)">
-                      <el-input v-model="item.ratio" type="number" clearable />
-                    </el-form-item>
-                  </el-col>
-                  <el-col :span="6">
-                    <el-form-item label="浠锋牸(鍏�/鍚�)">
-                      <el-input v-model="item.weight" type="number" clearable />
-                    </el-form-item>
-                  </el-col>
-                </el-row>
-                <el-row>
-                  <el-col :span="6">
-                    <el-form-item label="纭垎(%)">
-                      <el-input v-model="item.weight1" type="number" clearable placeholder="鍙��" />
-                    </el-form-item>
-                  </el-col>
-                  <el-col :span="6">
-                    <el-form-item label="鐏板垎(%)">
-                      <el-input v-model="item.weight2" type="number" clearable placeholder="鍙��" />
-                    </el-form-item>
-                  </el-col>
-                  <el-col :span="6">
-                    <el-form-item label="姘村垎(%)">
-                      <el-input v-model="item.weight3" type="number" clearable placeholder="鍙��" />
-                    </el-form-item>
-                  </el-col>
-                  <el-col :span="6">
-                    <el-form-item label="姣忛摬閲嶉噺(鍚�/閾�)">
-                      <el-input v-model="formInline.count1" type="number" clearable />
-                    </el-form-item>
-                  </el-col>
-                </el-row>
-                <el-divider />
-              </div>
-            </el-form>
+            <div class="coal-forms-container">
+              <el-form
+                :model="coalForms"
+                :inline="true"
+                label-width="110"
+                label-position="top"
+              >
+                <div
+                  v-for="(item, index) in coalForms"
+                  :key="index"
+                  style="margin-bottom: 15px"
+                >
+                  <el-row :gutter="16">
+                    <el-col :span="6">
+                      <el-form-item label="鐓ょ绫诲瀷">
+                        <el-select
+                          v-model="item.type"
+                          placeholder="璇烽�夋嫨"
+                          style="width: 100%"
+                          @change="handleCoalTypeChange(index)"
+                        >
+                          <el-option label="宸叉湁鐓�" value="宸叉湁鐓�" />
+                          <el-option label="鏈煡鐓�" value="鏈煡鐓�" />
+                        </el-select>
+                      </el-form-item>
+                    </el-col>
+                    <el-col :span="6">
+                      <el-form-item :label="'鐓ょ' + (index + 1)">
+                        <div class="input-wrapper">
+                          <el-input
+                            v-model="item.coalId"
+                            v-show="item.type !== '宸叉湁鐓�'"
+                            placeholder="璇疯緭鍏�"
+                            style="width: 100%"
+                          />
+
+                          <el-select
+                            v-model="item.coalId"
+                            v-show="item.type === '宸叉湁鐓�'"
+                            placeholder="璇烽�夋嫨"
+                            style="width: 100%"
+                            @change="handleCoalSelectChange(index, item.coalId)"
+                          >
+                            <el-option
+                              v-for="ele in infoCoals"
+                              :key="ele.key"
+                              :label="ele.value"
+                              :value="ele.key"
+                              >{{ ele.value }}
+                            </el-option>
+                          </el-select>
+                        </div>
+                      </el-form-item>
+                    </el-col>
+                    <el-col :span="6">
+                      <el-form-item label="鍙戠儹閲�">
+                        <el-input
+                          v-if="item.type !== '鏈煡鐓�'"
+                          :value="
+                            infoCoals.find((coal) => coal.key === item.coalId)
+                              ?.item.coalValues.find((value) => value.fieldName === '鍙戠儹閲�')?.coalValue || '0'
+                          "
+                          type="number"
+                          style="width: 100%"
+                          :disabled="true"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">kcal</i>
+                          </template>
+                        </el-input>
+                        <el-input
+                          v-else
+                          v-model="item.cv"
+                          type="number"
+                          placeholder="璇疯緭鍏ュ彂鐑噺"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">kcal</i>
+                          </template>
+                        </el-input>
+                      </el-form-item>
+                    </el-col>
+                    <el-col :span="6">
+                      <el-form-item label="浠锋牸">
+                        <el-input
+                        v-if="item.type !== '鏈煡鐓�'"
+                        
+                          :value="
+                            infoCoals.find((coal) => coal.key === item.coalId)
+                              ?.item.priceExcludingTax || 0
+                          "
+                          type="number"
+                          style="width: 100%"
+                          :disabled="item.type === '宸叉湁鐓�'"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">鍏�/鍚�</i>
+                          </template>
+                        </el-input>
+                        <el-input
+                        v-else
+                          v-model="item.price"
+                          placeholder="璇疯緭鍏ヤ环鏍�"
+                          type="number"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">鍏�/鍚�</i>
+                          </template>
+                        </el-input>
+                      </el-form-item>
+                    </el-col>
+                  </el-row>
+                  <el-row :gutter="16">
+                    <el-col :span="6">
+                      <el-form-item label="纭垎">
+                        <el-input
+                          v-if="item.type !== '鏈煡鐓�'"
+                          :disabled="item.type === '宸叉湁鐓�'"
+                          v-model="item.sulfur"
+                          :value="
+                            infoCoals.find((coal) => coal.key === item.coalId)
+                              ?.item.coalValues.find((value) => value.fieldName === '纭垎')?.coalValue || '0'
+                          "
+                          type="number"
+                          placeholder="鍙��"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">%</i>
+                          </template>
+                        </el-input>
+                        <el-input
+                          v-else
+                          v-model="item.sulfur"
+                          type="number"
+                          placeholder="鍙��"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">%</i>
+                          </template>
+                        </el-input>
+                      </el-form-item>
+                    </el-col>
+                    <el-col :span="6">
+                      <el-form-item label="鐏板垎">
+                        <el-input
+                          v-if="item.type !== '鏈煡鐓�'"
+                          :disabled="item.type === '宸叉湁鐓�'"
+                          v-model="item.ash"
+                          :value="
+                            infoCoals.find((coal) => coal.key === item.coalId)
+                              ?.item.coalValues.find((value) => value.fieldName === '鐏板垎')?.coalValue || '0'
+                          "
+                          type="number"
+                          placeholder="鍙��"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">%</i>
+                          </template>
+                        </el-input>
+                        <el-input
+                          v-else
+                          v-model="item.ash"
+                          type="number"
+                          placeholder="鍙��"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">%</i>
+                          </template>
+                        </el-input>
+                      </el-form-item>
+                    </el-col>
+                    <el-col :span="6">
+                      <el-form-item label="姘村垎">
+                        <el-input
+                        v-if="item.type !== '鏈煡鐓�'"
+                        :disabled="item.type === '宸叉湁鐓�'"
+                        v-model="item.moisture"
+                        :value="
+                            infoCoals.find((coal) => coal.key === item.coalId)
+                              ?.item.coalValues.find((value) => value.fieldName === '姘村垎')?.coalValue || '0'
+                          "
+                          type="number"
+                          placeholder="鍙��"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">%</i>
+                          </template>
+                        </el-input>
+                        <el-input
+                        v-else
+                          v-model="item.moisture"
+                          type="number"
+                          placeholder="鍙��"
+                          style="width: 100%"
+                        >
+                          <template v-slot:suffix>
+                            <i style="font-style: normal">%</i>
+                          </template>
+                        </el-input>
+                      </el-form-item>
+                    </el-col>
+                  </el-row>
+                  <el-divider />
+                </div>
+              </el-form>
+            </div>
           </div>
           <div>
             <div class="title">閰嶇叅绾︽潫鏉′欢</div>
-            <el-form :inline="true" :model="formInline" class="demo-form-inline" label-width="110" label-position="top">
-              <el-row>
+            <el-form
+              :inline="true"
+              :model="constraints"
+              class="demo-form-inline"
+              label-width="110"
+              label-position="top"
+            >
+              <el-row :gutter="16">
                 <el-col :span="6">
                   <el-form-item label="娣峰悎鐓ゆ渶浣庡彂鐑噺(CV)">
-                    <el-input v-model="formInline.num" type="number" clearable @change="updateCoalFields" />
+                    <el-input
+                      v-model="constraints.minCalorific"
+                      type="number"
+                      style="width: 100%"
+                    >
+                      <template v-slot:suffix>
+                        <i style="font-style: normal">kcal</i>
+                      </template>
+                    </el-input>
                   </el-form-item>
                 </el-col>
                 <el-col :span="6">
-                  <el-form-item label="娣峰悎鐓ゆ渶楂樼~鍒�(%)">
-                    <el-input v-model="formInline.count" type="number" clearable placeholder="鍙��"/>
+                  <el-form-item label="娣峰悎鐓ゆ渶楂樼~鍒�">
+                    <el-input
+                      v-model="constraints.maxSulfur"
+                      type="number"
+                      placeholder="鍙��"
+                      style="width: 100%"
+                    >
+                      <template v-slot:suffix>
+                        <i style="font-style: normal">%</i>
+                      </template>
+                    </el-input>
                   </el-form-item>
                 </el-col>
                 <el-col :span="6">
-                  <el-form-item label="娣峰悎鐓ゆ渶楂樼伆鍒�(%)">
-                    <el-input v-model="formInline.count1" type="number" clearable placeholder="鍙��"/>
+                  <el-form-item label="娣峰悎鐓ゆ渶楂樼伆鍒�">
+                    <el-input
+                      v-model="constraints.maxAsh"
+                      type="number"
+                      placeholder="鍙��"
+                      style="width: 100%"
+                    >
+                      <template v-slot:suffix>
+                        <i style="font-style: normal">%</i>
+                      </template>
+                    </el-input>
                   </el-form-item>
                 </el-col>
                 <el-col :span="6">
-                  <el-form-item label="娣峰悎鐓ゆ渶楂樻按鍒�(%)">
-                    <el-input v-model="formInline.count1" type="number" clearable placeholder="鍙��"/>
+                  <el-form-item label="娣峰悎鐓ゆ渶楂樻按鍒�">
+                    <el-input
+                      v-model="constraints.maxMoisture"
+                      type="number"
+                      placeholder="鍙��"
+                      style="width: 100%"
+                    >
+                      <template v-slot:suffix>
+                        <i style="font-style: normal">%</i>
+                      </template>
+                    </el-input>
                   </el-form-item>
                 </el-col>
               </el-row>
             </el-form>
           </div>
         </div>
-        
         <div class="footer">
           <el-button @click="cancel">閲嶇疆</el-button>
-          <el-button type="primary" @click="submitForm" plain>鏌ョ湅璁$畻缁撴灉</el-button>
-          <el-button type="primary" @click="submitForm">璁$畻鍏ュ簱</el-button>
+          <el-button type="primary" @click="addWarehoused" plain>
+            娣诲姞鑷冲緟鍏ュ簱
+          </el-button>
+          <el-button type="primary" @click="submitForm">璁$畻鏈�浼橀厤姣�</el-button>
         </div>
       </div>
       <div class="right-card">
-        <div class="count-region">缁撴灉鍖�</div>
+        <div class="count-region">閰嶇叅浼樺寲缁撴灉</div>
+        <div class="result-scroll">
+          <!-- 閿欒淇℃伅 -->
+          <div v-if="result.show && result.error" class="error-box">
+            <el-alert
+              :title="result.error"
+              type="error"
+              :closable="false"
+              show-icon
+            />
+          </div>
+
+          <!-- 鏈�浼橀厤姣旂粨鏋� -->
+          <div
+            v-if="result.show && result.optimal && !result.error"
+            class="result-section"
+          >
+            <div class="result-title">馃幆 鏈�浼橀厤姣旂粨鏋�</div>
+            <!-- 閰嶆瘮琛� -->
+            <div class="table-container">
+              <el-table
+                :data="result.optimal.instructions"
+                border
+                size="small"
+                class="result-table"
+                style="width: 100%"
+              >
+                <el-table-column prop="coalId" label="鐓ょ" min-width="80">
+                  <template #default="scope">
+                    {{
+                      infoCoals.find((coal) => coal.key === scope.row.coalId)
+                        ?.value ||
+                      "" ||
+                      matchCoalName(scope.row.coalId)
+                    }}
+                  </template>
+                </el-table-column>
+                <el-table-column prop="ratio" label="閰嶆瘮" min-width="80">
+                  <template #default="scope"> {{ scope.row.ratio }}% </template>
+                </el-table-column>
+                <el-table-column prop="quantity" label="鍚ㄦ暟" min-width="80">
+                  <template #default="scope">
+                    {{ scope.row.quantity }}鍚�
+                  </template>
+                </el-table-column>
+                <el-table-column prop="scoops" label="閾叉暟" min-width="80">
+                  <template #default="scope">
+                    {{ scope.row.scoops }}閾�
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+
+            <!-- 娣峰悎鐓ゅ睘鎬� -->
+            <div class="props-section">
+              <div class="props-title">馃搳 娣峰悎鐓ゅ睘鎬�</div>
+              <div class="props-grid">
+                <div class="prop-item">
+                  <span class="prop-label">鍙戠儹閲�:</span>
+                  <span class="prop-value"
+                    >{{ result.optimal.props.cv.toFixed(2) }} kcal</span
+                  >
+                </div>
+                <div class="prop-item">
+                  <span class="prop-label">纭垎:</span>
+                  <span class="prop-value"
+                    >{{ result.optimal.props.sulfur.toFixed(2) }}%</span
+                  >
+                </div>
+                <div class="prop-item">
+                  <span class="prop-label">鐏板垎:</span>
+                  <span class="prop-value"
+                    >{{ result.optimal.props.ash.toFixed(2) }}%</span
+                  >
+                </div>
+                <div class="prop-item">
+                  <span class="prop-label">姘村垎:</span>
+                  <span class="prop-value"
+                    >{{ result.optimal.props.moisture.toFixed(2) }}%</span
+                  >
+                </div>
+                <div class="prop-item">
+                  <span class="prop-label">鎴愭湰:</span>
+                  <span class="prop-value cost"
+                    >{{ result.optimal.props.cost.toFixed(2) }} 鍏�/鍚�</span
+                  >
+                </div>
+                <div class="prop-item">
+                  <span class="prop-label">鐢熸垚:</span>
+                  <el-autocomplete
+                    v-model="result.optimal.props.createCoal"
+                    :fetch-suggestions="querySearch"
+                    clearable
+                    size="small"
+                    class="inline-input red-border"
+                    style="width: 180px; min-height: 24px !important"
+                    placeholder="璇疯緭鍏ョ敓鎴愮叅绉�"
+                    @blur="handleSelect($event)"
+                    @select="handleSelect($event)"
+                  />
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <!-- 澶囬�夋柟妗� -->
+          <div
+            v-if="result.show && result.alternatives.length > 0"
+            class="alternatives-section"
+          >
+            <div class="result-title">馃攧 澶囬�夋柟妗�</div>
+            <div
+              v-for="(alt, index) in result.alternatives"
+              :key="index"
+              class="alt-item"
+            >
+              <div class="alt-title">{{ alt.desc }}</div>
+              <div class="table-container">
+                <el-table
+                  :data="alt.instructions"
+                  border
+                  size="small"
+                  class="alt-table"
+                  style="width: 100%"
+                >
+                  <el-table-column prop="coalId" label="鐓ょ" min-width="80">
+                    <template #default="scope">
+                      {{
+                        infoCoals.find((coal) => coal.key === scope.row.coalId)
+                          ?.value ||
+                        "" ||
+                        matchCoalName(scope.row.coalId)
+                      }}
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="ratio" label="閰嶆瘮" min-width="80">
+                    <template #default="scope">
+                      {{ scope.row.ratio }}%
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="quantity" label="鍚ㄦ暟" min-width="80">
+                    <template #default="scope">
+                      {{ scope.row.quantity }}鍚�
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="scoops" label="閾叉暟" min-width="80">
+                    <template #default="scope">
+                      {{ scope.row.scoops }}閾�
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </div>
+
+              <div class="alt-props">
+                <span>鍙戠儹閲�: {{ alt.props.cv.toFixed(2) }} kcal锛�</span>
+                <span>纭垎: {{ alt.props.sulfur.toFixed(2) }}%锛�</span>
+                <span>鐏板垎: {{ alt.props.ash.toFixed(2) }}%锛�</span>
+                <span>姘村垎: {{ alt.props.moisture.toFixed(2) }}%锛�</span>
+                <span class="cost"
+                  >鎴愭湰: {{ alt.props.cost.toFixed(2) }} 鍏�/鍚�</span
+                >
+              </div>
+            </div>
+          </div>
+          <!-- 绌虹姸鎬� -->
+          <div v-if="!result.show" class="empty-state">
+            <el-empty description="鐐瑰嚮宸︿晶璁$畻鏈�浼橀厤姣旀寜閽煡鐪嬬粨鏋�" />
+          </div>
+        </div>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
+import { reactive, toRefs, nextTick, onMounted, ref } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { getCoalInfoList } from "@/api/procureMent"; // 鍋囪鏈変竴涓狝PI鑾峰彇鐓ょ淇℃伅
+import { getCoalBlendingList,addPendingInventory } from "@/api/calculator/index.js";
+
 const data = reactive({
   formInline: {
-    num: 1
+    num: 3, // 榛樿3涓叅绉�
+    totalTonnage: 1000, // 鍙備笌閰嶇叅鎬诲惃鏁�
+    scoopWeight: 50, // 姣忛摬閲嶉噺
+  },
+  // 绾︽潫鏉′欢
+  constraints: {
+    minCalorific: 5600, // 娣峰悎鐓ゆ渶浣庡彂鐑噺
+    maxSulfur: 1.2, // 娣峰悎鐓ゆ渶楂樼~鍒�
+    maxAsh: 15.0, // 娣峰悎鐓ゆ渶楂樼伆鍒�
+    maxMoisture: "", // 娣峰悎鐓ゆ渶楂樻按鍒�
   },
   coalForms: [
     {
-      name: '',
-      ratio: 0,
-      weight: 0
-    }
+      type: "鏈煡鐓�",
+      coalId: "鐓",
+      cv: 6200, // 鍙戠儹閲�
+      price: 450, // 浠锋牸
+      sulfur: 0.6, // 纭垎
+      ash: 12.0, // 鐏板垎
+      moisture: 8.0, // 姘村垎
+    },
+    {
+      type: "鏈煡鐓�",
+      coalId: "鐓",
+      cv: 5800,
+      price: 380,
+      sulfur: 1.0,
+      ash: 14.0,
+      moisture: 10.0,
+    },
+    {
+      type: "鏈煡鐓�",
+      coalId: "鐓",
+      cv: 5400,
+      price: 320,
+      sulfur: 1.4,
+      ash: 16.0,
+      moisture: 12.0,
+    },
   ],
-})
-const { formInline, coalForms } = toRefs(data)
+  // 璁$畻缁撴灉
+  result: {
+    show: false,
+    optimal: null,
+    alternatives: [],
+    error: null,
+    createCoal: null,
+  },
+});
+const handleCoalSelectChange = (index, coalId) => {
+  const selectedCoal = infoCoals.value.find(item => item.key === coalId);
+  
+  if (!selectedCoal?.item?.coalValues) {
+    console.warn('鏈壘鍒伴�変腑鐨勭叅绉嶆暟鎹垨鏁版嵁鏍煎紡涓嶆纭�');
+    return;
+  }
+  
+  // 鑾峰彇鐓よ川鍙傛暟鐨勯�氱敤鍑芥暟
+  const getCoalValue = (fieldName) => {
+    return selectedCoal.item.coalValues.find(
+      value => value.fieldName === fieldName
+    )?.coalValue || 0;
+  };
+
+  // 鎵归噺鏇存柊琛ㄥ崟鏁版嵁
+  Object.assign(data.coalForms[index], {
+    price: selectedCoal.item.priceExcludingTax || 0,
+    cv: getCoalValue("鍙戠儹閲�"),
+    sulfur: getCoalValue("纭垎"),
+    ash: getCoalValue("鐏板垎"),
+    moisture: getCoalValue("姘村垎")
+  });
+};
+const coalInfoList = ref([]);
+// 鑾峰彇鐓ょ淇℃伅
+const getCoalInfo = async () => {
+  try {
+    const result = await getCoalInfoList();
+    if (result.code === 200) {
+      coalInfoList.value = result.data.map(item => ({
+        value: item.coal,
+        key: item.id,
+      }));
+    } else {
+      ElMessage.error("鑾峰彇鐓ょ淇℃伅澶辫触锛岃绋嶅悗閲嶈瘯");
+    }
+  } catch (error) {
+    ElMessage.error("鑾峰彇鐓ょ淇℃伅澶辫触锛岃绋嶅悗閲嶈瘯");
+  }
+};
+// 琛ㄦ牸灞曠ず鐢細鍖归厤鐓ょ鍚嶇О
+const matchCoalName = (name) => {
+  if (!name || !coalInfoList.value?.length) return name;
+  
+  // 浼樺厛鎸� key 鍖归厤锛屽啀鎸� value 鍖归厤
+  const foundCoal = coalInfoList.value.find(item => 
+    String(item.key) === String(name) || item.value === name
+  );
+  
+  return foundCoal?.value || name;
+};
+// 鑷姩琛ュ叏鎼滅储
+const querySearch = (q, cb) => {
+  const results = q 
+    ? coalInfoList.value.filter(c => c.value.includes(q))
+    : coalInfoList.value;
+  cb(results);
+};
+
+// 閫夋嫨/澶辩劍澶勭悊
+const handleSelect = (item) => {
+  const val = item.value || item.target?.value || "";
+  const found = coalInfoList.value.find(c => c.value === val || c.key === val);
+  
+  result.value.optimal.props.createCoal = found ? found.key : val;
+  result.value.optimal.props.coalId = found?.key || null;
+  
+  // 鏇存柊鏄剧ず鍚嶇О
+  const matchedName = matchCoalName(result.value.optimal.props.createCoal);
+  if (matchedName !== result.value.optimal.props.createCoal) {
+    result.value.optimal.props.createCoal = matchedName;
+  }
+};
+onMounted(async () => {
+  getCoalInfo();
+  geInfoCoals();
+});
+const infoCoals = ref([]);
+// 鍒濆鍖栫叅绉嶅瓧娈�
+const geInfoCoals = async () => {
+  try {
+    const res = await getCoalBlendingList();
+    if (res.code === 200) {
+      console.log("鑾峰彇鐓ょ淇℃伅鎴愬姛", res.data);
+      infoCoals.value = res.data.map(item => ({
+        value: item.supplierCoal,
+        key: item.coalId,
+        item,
+      }));
+    } else {
+      ElMessage.error("鑾峰彇鐓ょ淇℃伅澶辫触锛岃绋嶅悗閲嶈瘯");
+    }
+  } catch (error) {
+    ElMessage.error("鑾峰彇鐓ょ淇℃伅澶辫触锛岃绋嶅悗閲嶈瘯");
+  }
+};
+// 绾挎�ц鍒掓眰瑙e嚱鏁�
+const solveBlend = (coals, constraints) => {
+  // 鏁版嵁楠岃瘉
+  const validateConstraint = (constraintValue, fieldName, coalField) => {
+    if (constraintValue && coals.some(coal => !coal[coalField] && coal[coalField] !== 0)) {
+      throw new Error(`濡傛灉璁剧疆浜�${fieldName}绾︽潫锛屽垯鎵�鏈夌叅绉嶉兘蹇呴』鎻愪緵${fieldName}鏁版嵁銆俙);
+    }
+  };
+
+  validateConstraint(constraints.maxSulfur, '鏈�澶х~鍒�', 'sulfur');
+  validateConstraint(constraints.maxAsh, '鏈�澶х伆鍒�', 'ash');
+  validateConstraint(constraints.maxMoisture, '鏈�澶ф按鍒�', 'moisture');
+
+  try {
+    // 绠�鍗曠殑绛夋潈閲嶅垎閰嶄綔涓哄垵濮嬭В
+    let ratios = new Array(coals.length).fill(1 / coals.length);
+
+    // 楠岃瘉绾︽潫鏉′欢骞惰皟鏁撮厤姣�
+    let blendProps = calcBlendProps(coals, ratios);
+
+    if (constraints.minCalorific && blendProps.cv < constraints.minCalorific) {
+      // 浼樺厛浣跨敤楂樺彂鐑噺鐓ょ
+      const sortedCoals = coals
+        .map((coal, i) => ({ index: i, cv: coal.cv }))
+        .sort((a, b) => b.cv - a.cv);
+
+      ratios = new Array(coals.length).fill(0);
+      ratios[sortedCoals[0].index] = 0.6;
+      if (sortedCoals[1]) ratios[sortedCoals[1].index] = 0.4;
+    }
+
+    return ratios;
+  } catch (error) {
+    throw error;
+  }
+};
+
+// 璁$畻娣峰悎灞炴��
+const calcBlendProps = (coals, ratios) => {
+  let cv = 0,
+    sulfur = 0,
+    ash = 0,
+    moisture = 0,
+    cost = 0;
+  for (let i = 0; i < coals.length; i++) {
+    cv += ratios[i] * Number(coals[i].cv || 0);
+    sulfur += ratios[i] * Number(coals[i].sulfur || 0);
+    ash += ratios[i] * Number(coals[i].ash || 0);
+    moisture += ratios[i] * Number(coals[i].moisture || 0);
+    cost += ratios[i] * Number(coals[i].price || 0);
+  }
+  return { cv, sulfur, ash, moisture, cost };
+};
+
+// 鐢熸垚鎿嶄綔鎸囦护
+const genInstructions = (coals, ratios, total, scoop) => {
+  return coals
+    .map((coal, i) => {
+      if (ratios[i] < 1e-6) return null;
+      let quantity = ratios[i] * total;
+      let scoops = quantity / scoop;
+      return {
+        coalId: coal.coalId,
+        ratio: (ratios[i] * 100).toFixed(2),
+        quantity: quantity.toFixed(1),
+        scoops: scoops.toFixed(1),
+      };
+    })
+    .filter(Boolean);
+};
+
+const cancel = () => {
+  // 閲嶇疆琛ㄥ崟閫昏緫
+  data.formInline = {
+    num: 3,
+    totalTonnage: 1000,
+    scoopWeight: 50,
+  };
+  data.constraints = {
+    minCalorific: 5600,
+    maxSulfur: 1.2,
+    maxAsh: 15.0,
+    maxMoisture: "",
+  };
+  data.coalForms = [
+    {
+      type: "鏈煡鐓�",
+      coalId: "鐓",
+      cv: 6200,
+      price: 450,
+      sulfur: 0.6,
+      ash: 12.0,
+      moisture: 8.0,
+    },
+    {
+      type: "鏈煡鐓�",
+      coalId: "鐓",
+      cv: 5800,
+      price: 380,
+      sulfur: 1.0,
+      ash: 14.0,
+      moisture: 10.0,
+    },
+    {
+      type: "鏈煡鐓�",
+      coalId: "鐓",
+      cv: 5400,
+      price: 320,
+      sulfur: 1.4,
+      ash: 16.0,
+      moisture: 12.0,
+    },
+  ];
+  data.result = {
+    show: false,
+    optimal: null,
+    alternatives: [],
+    error: null,
+  };
+  ElMessage.success("琛ㄥ崟宸查噸缃�");
+};
+const addWarehoused = () => {
+  // 楠岃瘉鍓嶇疆鏉′欢
+  const validationChecks = [
+    { condition: !result.value, message: "璇峰厛璁$畻鏈�浼橀厤姣斿悗鍐嶆坊鍔犺嚦寰呭叆搴�" },
+    { condition: !result.value.optimal, message: "璇峰厛璁$畻鏈�浼橀厤姣�" },
+    { condition: !result.value.optimal.props.createCoal, message: "璇峰厛閫夋嫨鐢熸垚鐓ょ" }
+  ];
+
+  for (const check of validationChecks) {
+    if (check.condition) {
+      ElMessage.error(check.message);
+      return;
+    }
+  }
+
+  // 楠岃瘉閰嶆瘮涓殑鐓ょ
+  const coals = result.value.optimal.instructions.map(item => item.coalId);
+  const allCoalsFound = coals.every(coalId => 
+    coalInfoList.value.some(item => item.key === coalId)
+  );
+
+  if (!allCoalsFound) {
+    ElMessage.error("閰嶆瘮涓寘鍚湭鐭ョ叅绉嶏紝璇峰厛娣诲姞鑷崇叅绉嶅垪琛�");
+    return;
+  }
+
+  // 楠岃瘉鐢熸垚鐓ょ
+  const createCoalExists = coalInfoList.value.some(
+    item => item.key === result.value.optimal.props.coalId
+  );
+
+  if (!createCoalExists) {
+    ElMessage.warning("鐢熸垚鐓ょ鏄湭鐭ョ叅绉嶏紝鏃犳硶娣诲姞鑷冲緟鍏ュ簱");
+    return;
+  }
+
+  // 鍑嗗鏁版嵁
+  const optimalData = result.value.optimal;
+  optimalData.props.totalTonnage = formInline.value.totalTonnage;
+  optimalData.props.cost = parseFloat(optimalData.props.cost.toFixed(2));
+  
+  // 娣诲姞瀹樻柟ID
+  optimalData.instructions.forEach(item => {
+    item.officialId = item.coalId;
+  });
+
+  const params = {
+    fieldsResultList: optimalData.props,
+    coalResultList: optimalData.instructions,
+  };
+
+  addPendingInventory(params).then(res => {
+    if (res.code === 200 && res.data === true) {
+      ElMessage.success("娣诲姞鑷冲緟鍏ュ簱鎴愬姛");
+    }
+  });
+};
+const submitForm = () => {
+  // 鏁版嵁楠岃瘉
+  const validCoals = coalForms.value.filter(
+    coal => coal.coalId && coal.cv && coal.price
+  );
+
+  if (validCoals.length < 2) {
+    ElMessage.error("鑷冲皯闇�瑕�2涓湁鏁堢殑鐓ょ鏁版嵁锛堝悕绉般�佸彂鐑噺銆佷环鏍间负蹇呭~锛�");
+    return;
+  }
+
+  try {
+    // 姹傝В鏈�浼橀厤姣�
+    const ratios = solveBlend(validCoals, constraints.value);
+    if (!ratios) {
+      data.result.error = "鏃犲彲琛岃В锛岃妫�鏌ョ害鏉熸潯浠舵垨鐓ょ鏁版嵁";
+      data.result.show = true;
+      return;
+    }
+
+    // 璁$畻缁撴灉
+    const props = calcBlendProps(validCoals, ratios);
+    const instructions = genInstructions(
+      validCoals,
+      ratios,
+      formInline.value.totalTonnage,
+      formInline.value.scoopWeight
+    );
+
+    data.result = {
+      show: true,
+      optimal: { ratios, props, instructions },
+      alternatives: [],
+      error: null,
+    };
+
+    // 鐢熸垚澶囬�夋柟妗�
+    generateAlternatives(validCoals);
+
+    ElMessage.success("閰嶇叅浼樺寲璁$畻瀹屾垚");
+  } catch (error) {
+    data.result.error = error.message || "璁$畻杩囩▼涓彂鐢熼敊璇�";
+    data.result.show = true;
+    ElMessage.error(data.result.error);
+  }
+};
+
+const generateAlternatives = (coals) => {
+  const altList = [
+    { desc: "鍙戠儹閲忛檷1%", mod: { minCalorific: constraints.value.minCalorific * 0.99 } },
+    { desc: "鍙戠儹閲忛檷2%", mod: { minCalorific: constraints.value.minCalorific * 0.98 } },
+    { desc: "纭垎鍗�1%", mod: { maxSulfur: constraints.value.maxSulfur * 1.01 } },
+    { desc: "纭垎鍗�2%", mod: { maxSulfur: constraints.value.maxSulfur * 1.02 } },
+    { 
+      desc: "鍙戠儹閲忛檷0.5%涓旂~鍒嗗崌0.5%", 
+      mod: {
+        minCalorific: constraints.value.minCalorific * 0.995,
+        maxSulfur: constraints.value.maxSulfur * 1.005,
+      }
+    },
+  ];
+
+  data.result.alternatives = altList.reduce((alternatives, alt) => {
+    try {
+      const altConstraints = { ...constraints.value, ...alt.mod };
+      const altRatios = solveBlend(coals, altConstraints);
+      
+      if (altRatios) {
+        const altProps = calcBlendProps(coals, altRatios);
+        const altInstructions = genInstructions(
+          coals, altRatios, formInline.value.totalTonnage, formInline.value.scoopWeight
+        );
+
+        alternatives.push({
+          desc: alt.desc,
+          ratios: altRatios,
+          props: altProps,
+          instructions: altInstructions,
+        });
+      }
+    } catch (error) {
+      console.warn(`澶囬�夋柟妗� ${alt.desc} 璁$畻澶辫触:`, error);
+    }
+    return alternatives;
+  }, []);
+};
+
+const { formInline, constraints, coalForms, result } = toRefs(data);
 
 const updateCoalFields = () => {
   const num = parseInt(formInline.value.num);
@@ -143,34 +948,67 @@
     coalForms.value = [];
     return;
   }
-  
-  // 濡傛灉褰撳墠鏁扮粍闀垮害澶т簬鎵�闇�鏁伴噺锛屾埅鏂�
+
+  // 鎴柇澶氫綑鐨勬垨濉厖涓嶈冻鐨勭叅绉�
   if (coalForms.value.length > num) {
     coalForms.value = coalForms.value.slice(0, num);
-    return;
+  } else {
+    while (coalForms.value.length < num) {
+      coalForms.value.push({
+        type: "鏈煡鐓�",
+        coalId: `鐓�${String.fromCharCode(65 + coalForms.value.length)}`,
+        cv: 0,
+        price: 0,
+        sulfur: "",
+        ash: "",
+        moisture: "",
+      });
+    }
   }
-  
-  // 鍚﹀垯锛屽~鍏呮柊鐨勭┖瀵硅薄
-  while (coalForms.value.length < num) {
-    coalForms.value.push({
-      name: '',
-      ratio: 0,
-      weight: 0
-    });
-  }
-}
+};
+
+// 澶勭悊鐓ょ绫诲瀷鍙樺寲
+const handleCoalTypeChange = (index) => {
+  coalForms.value[index].coalId = "";
+};
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .view {
   display: flex;
+  gap: 10px;
 }
 .left-card {
   background: #fff;
-  width: calc(100% - 600px);
+  flex: 1;
+  min-width: 0;
   padding: 16px;
-  margin-right: 10px;
+  border-radius: 6px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
+.coal-forms-container {
+  overflow-x: auto;
+  padding-bottom: 8px;
+}
+
+.coal-forms-container::-webkit-scrollbar {
+  height: 6px;
+}
+
+.coal-forms-container::-webkit-scrollbar-track {
+  background: #f1f1f1;
+  border-radius: 3px;
+}
+
+.coal-forms-container::-webkit-scrollbar-thumb {
+  background: #c1c1c1;
+  border-radius: 3px;
+}
+
+.coal-forms-container::-webkit-scrollbar-thumb:hover {
+  background: #a8a8a8;
+}
+
 .count-region {
   font-size: 18px;
   color: #000000;
@@ -179,10 +1017,30 @@
 .scroll {
   height: calc(100vh - 14em);
   overflow-y: auto;
+  overflow-x: hidden;
+  padding-right: 8px;
+}
+
+.scroll::-webkit-scrollbar {
+  width: 6px;
+}
+
+.scroll::-webkit-scrollbar-track {
+  background: #f1f1f1;
+  border-radius: 3px;
+}
+
+.scroll::-webkit-scrollbar-thumb {
+  background: #c1c1c1;
+  border-radius: 3px;
+}
+
+.scroll::-webkit-scrollbar-thumb:hover {
+  background: #a8a8a8;
 }
 .title {
   font-size: 14px;
-  color: #165DFF;
+  color: #165dff;
   line-height: 20px;
   font-weight: 600;
   padding-left: 10px;
@@ -196,7 +1054,7 @@
   top: 3px; /* 璋冩暣鍨傜洿浣嶇疆 */
   width: 4px; /* 灏忔暟鏉″搴� */
   height: 14px; /* 灏忔暟鏉¢珮搴� */
-  background-color: #165DFF; /* 钃濊壊 */
+  background-color: #165dff; /* 钃濊壊 */
 }
 .el-divider--horizontal {
   margin: 12px 0;
@@ -208,7 +1066,308 @@
 .right-card {
   background: #fff;
   width: 600px;
+  min-width: 400px;
   height: auto;
   padding: 16px;
+  border-radius: 6px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
-</style>
\ No newline at end of file
+
+.result-scroll {
+  height: calc(100vh - 14em);
+  overflow-y: auto;
+  overflow-x: hidden;
+  padding-right: 8px;
+}
+
+.result-scroll::-webkit-scrollbar {
+  width: 6px;
+}
+
+.result-scroll::-webkit-scrollbar-track {
+  background: #f1f1f1;
+  border-radius: 3px;
+}
+
+.result-scroll::-webkit-scrollbar-thumb {
+  background: #c1c1c1;
+  border-radius: 3px;
+}
+
+.result-scroll::-webkit-scrollbar-thumb:hover {
+  background: #a8a8a8;
+}
+
+.error-box {
+  margin-bottom: 20px;
+}
+
+.result-section,
+.alternatives-section {
+  margin-bottom: 20px;
+}
+
+.result-title {
+  font-size: 16px;
+  color: #165dff;
+  font-weight: 600;
+  margin-bottom: 15px;
+  padding-left: 10px;
+  position: relative;
+}
+
+.result-title::before {
+  content: "";
+  position: absolute;
+  left: 0;
+  top: 3px;
+  width: 4px;
+  height: 16px;
+  background-color: #165dff;
+}
+
+.result-table,
+.alt-table {
+  margin-bottom: 15px;
+}
+
+.table-container {
+  overflow-x: auto;
+  margin-bottom: 15px;
+  border-radius: 4px;
+}
+
+.table-container::-webkit-scrollbar {
+  height: 6px;
+}
+
+.table-container::-webkit-scrollbar-track {
+  background: #f1f1f1;
+  border-radius: 3px;
+}
+
+.table-container::-webkit-scrollbar-thumb {
+  background: #c1c1c1;
+  border-radius: 3px;
+}
+
+.table-container::-webkit-scrollbar-thumb:hover {
+  background: #a8a8a8;
+}
+
+.input-wrapper {
+  position: relative;
+  min-height: 32px;
+  width: 100%;
+}
+
+.input-wrapper .el-input,
+.input-wrapper .el-select {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100% !important;
+  transition: opacity 0.2s ease-in-out;
+}
+
+/* 纭繚input-wrapper鍐呯殑缁勪欢瀹藉害 */
+.input-wrapper :deep(.el-input),
+.input-wrapper :deep(.el-select) {
+  width: 100% !important;
+}
+
+.input-wrapper :deep(.el-input__wrapper),
+.input-wrapper :deep(.el-select .el-input__wrapper) {
+  width: 100% !important;
+}
+
+.props-section {
+  margin-top: 15px;
+}
+
+.props-title {
+  font-size: 14px;
+  color: #333;
+  font-weight: 600;
+  margin-bottom: 10px;
+}
+
+.props-grid {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 8px;
+}
+
+.prop-item {
+  display: flex;
+  justify-content: space-between;
+  padding: 8px 12px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  font-size: 13px;
+  align-items: center;
+}
+
+.prop-label {
+  color: #606266;
+}
+
+.prop-value {
+  font-weight: 600;
+  color: #303133;
+}
+
+.prop-value.cost {
+  color: #e6a23c;
+  font-weight: bold;
+}
+
+.alt-item {
+  margin-bottom: 20px;
+  padding: 15px;
+  border: 1px solid #ebeef5;
+  border-radius: 6px;
+  background: #fafafa;
+}
+
+.alt-title {
+  font-size: 14px;
+  color: #409eff;
+  font-weight: 600;
+  margin-bottom: 10px;
+}
+
+.alt-props {
+  font-size: 12px;
+  color: #606266;
+  margin-top: 10px;
+  line-height: 1.6;
+}
+
+.alt-props .cost {
+  color: #e6a23c;
+  font-weight: 600;
+}
+
+.empty-state {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 300px;
+}
+
+/* 闃叉椤甸潰鎶栧姩鐨勬牱寮� */
+:deep(.el-input) {
+  width: 100% !important;
+  min-width: 100% !important;
+}
+
+:deep(.el-select) {
+  width: 100% !important;
+  min-width: 100% !important;
+}
+
+:deep(.el-form-item) {
+  margin-bottom: 18px;
+  width: 100%;
+}
+
+:deep(.el-form-item__label) {
+  padding-bottom: 6px;
+  font-size: 14px;
+  line-height: 1.5;
+  height: auto;
+}
+
+:deep(.el-form-item__content) {
+  min-height: 32px;
+  line-height: 32px;
+  width: 100%;
+}
+
+:deep(.el-col) {
+  padding-right: 8px;
+  box-sizing: border-box;
+}
+
+:deep(.el-col:last-child) {
+  padding-right: 0;
+}
+
+/* 纭繚杈撳叆妗嗗鍣ㄦ湁鍥哄畾楂樺害鍜屽搴� */
+:deep(.el-input__wrapper) {
+  min-height: 32px;
+  box-sizing: border-box;
+  width: 100% !important;
+  min-width: 100% !important;
+}
+
+:deep(.el-select .el-input__wrapper) {
+  min-height: 32px;
+  box-sizing: border-box;
+  width: 100% !important;
+  min-width: 100% !important;
+}
+
+/* 闃叉tooltip寮曡捣鐨勬姈鍔� */
+:deep(.el-tooltip) {
+  display: block;
+  width: 100%;
+}
+
+/* 缁熶竴琛岄珮鍜岄棿璺� */
+:deep(.el-row) {
+  margin-bottom: 0;
+}
+
+/* 闃叉鍐呭鍙樺寲寮曡捣鐨勫竷灞�璺冲姩 */
+:deep(.el-input__inner),
+:deep(.el-select__input) {
+  min-height: 30px;
+  line-height: 30px;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1200px) {
+  .view {
+    flex-direction: column;
+  }
+
+  .left-card {
+    width: 100%;
+  }
+
+  .right-card {
+    width: 100%;
+    min-width: auto;
+  }
+
+  .scroll {
+    height: calc(100vh - 20em);
+  }
+
+  .result-scroll {
+    height: calc(100vh - 20em);
+  }
+}
+
+@media (max-width: 768px) {
+  .props-grid {
+    grid-template-columns: 1fr;
+  }
+
+  .table-container {
+    font-size: 12px;
+  }
+
+  :deep(.el-table .cell) {
+    padding: 4px 8px;
+  }
+}
+:deep(.el-input__wrapper) {
+  min-height: 24px !important;
+}
+:deep(.el-input__inner) {
+  min-height: 24px !important;
+}
+</style>

--
Gitblit v1.9.3