فهرست منبع

style(pms): 优化项目配置表单及任务计划弹窗样式

- 拆分合同信息与项目配置区域,统一卡片标题和说明样式
- 调整项目配置表单布局、间距及响应式展示效果
- 统一项目配置页面操作按钮为 default 尺寸
- 重构任务计划弹窗标题区、计划工具栏及底部操作区
- 增加计划数量展示并统一新增、保存按钮样式
- 优化计划表格输入控件宽度及单元格间距
- 表格改为内容自适应高度,数据过多时限制高度并内部滚动
- 补充任务计划弹窗的小屏适配样式
Zimo 1 هفته پیش
والد
کامیت
a5b25f56d6
2فایلهای تغییر یافته به همراه343 افزوده شده و 116 حذف شده
  1. 94 48
      src/views/pms/iotprojectinfo/IotProjectInfoForm.vue
  2. 249 68
      src/views/pms/iotprojecttask/index.vue

+ 94 - 48
src/views/pms/iotprojectinfo/IotProjectInfoForm.vue

@@ -12,19 +12,30 @@
           <p class="page-header__subtitle">维护客户、合同、归属部门及项目配置信息</p>
           <p class="page-header__subtitle">维护客户、合同、归属部门及项目配置信息</p>
         </div>
         </div>
       </div>
       </div>
-      <el-button @click="close"> <Icon icon="ep:arrow-left" class="mr-5px" />返回 </el-button>
+      <el-button size="default" @click="close">
+        <Icon icon="ep:arrow-left" class="mr-5px" />返回
+      </el-button>
     </ContentWrap>
     </ContentWrap>
 
 
-    <ContentWrap v-loading="formLoading" class="project-form-content">
-      <el-form
-        ref="formRef"
-        :model="formData"
-        :rules="formRules"
-        label-width="108px"
-        size="default"
-        class="project-form">
-        <section class="form-section">
-          <div class="section-title">合同信息</div>
+    <el-form
+      ref="formRef"
+      v-loading="formLoading"
+      :model="formData"
+      :rules="formRules"
+      label-width="108px"
+      size="default"
+      class="project-form">
+      <ContentWrap class="project-form-card">
+        <div class="form-card-header">
+          <span class="form-card-icon form-card-icon--blue">
+            <Icon icon="ep:document" />
+          </span>
+          <div>
+            <h3>合同信息</h3>
+            <p>客户、合同及项目周期信息</p>
+          </div>
+        </div>
+        <div class="form-card-body">
           <el-row :gutter="24">
           <el-row :gutter="24">
             <el-col :xs="24" :md="12">
             <el-col :xs="24" :md="12">
               <el-form-item label="客户名称" prop="manufacturerId">
               <el-form-item label="客户名称" prop="manufacturerId">
@@ -76,10 +87,20 @@
               </el-form-item>
               </el-form-item>
             </el-col>
             </el-col>
           </el-row>
           </el-row>
-        </section>
+        </div>
+      </ContentWrap>
 
 
-        <section class="form-section">
-          <div class="section-title">项目配置</div>
+      <ContentWrap class="project-form-card">
+        <div class="form-card-header">
+          <span class="form-card-icon form-card-icon--green">
+            <Icon icon="ep:setting" />
+          </span>
+          <div>
+            <h3>项目配置</h3>
+            <p>归属部门、责任人与项目属性</p>
+          </div>
+        </div>
+        <div class="form-card-body">
           <el-row :gutter="24">
           <el-row :gutter="24">
             <el-col :xs="24" :md="12">
             <el-col :xs="24" :md="12">
               <el-form-item :label="t('iotDevice.company')" prop="deptId">
               <el-form-item :label="t('iotDevice.company')" prop="deptId">
@@ -119,6 +140,7 @@
                   <el-button
                   <el-button
                     type="primary"
                     type="primary"
                     plain
                     plain
+                    size="default"
                     :disabled="!formData.deptId"
                     :disabled="!formData.deptId"
                     @click="openUserDialog">
                     @click="openUserDialog">
                     <Icon icon="ep:user" class="mr-5px" />选择
                     <Icon icon="ep:user" class="mr-5px" />选择
@@ -192,9 +214,9 @@
               </el-form-item>
               </el-form-item>
             </el-col>
             </el-col>
           </el-row>
           </el-row>
-        </section>
-      </el-form>
-    </ContentWrap>
+        </div>
+      </ContentWrap>
+    </el-form>
 
 
     <CustomerList ref="customerZzFormRef" @choose="customerZzChoose" />
     <CustomerList ref="customerZzFormRef" @choose="customerZzChoose" />
 
 
@@ -233,16 +255,16 @@
         </el-transfer>
         </el-transfer>
       </div>
       </div>
       <template #footer>
       <template #footer>
-        <el-button @click="handleUserDialogClose">取消</el-button>
-        <el-button type="primary" @click="confirmUserSelection">确定</el-button>
+        <el-button size="default" @click="handleUserDialogClose">取消</el-button>
+        <el-button size="default" type="primary" @click="confirmUserSelection">确定</el-button>
       </template>
       </template>
     </el-dialog>
     </el-dialog>
 
 
     <div class="form-actions">
     <div class="form-actions">
-      <el-button type="primary" :loading="formLoading" @click="submitForm">
+      <el-button size="default" type="primary" :loading="formLoading" @click="submitForm">
         <Icon icon="ep:check" class="mr-5px" />保存
         <Icon icon="ep:check" class="mr-5px" />保存
       </el-button>
       </el-button>
-      <el-button @click="close">取消</el-button>
+      <el-button size="default" @click="close">取消</el-button>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>
@@ -979,46 +1001,69 @@ const handleSelect = (item: any) => {
   color: var(--el-text-color-secondary);
   color: var(--el-text-color-secondary);
 }
 }
 
 
-.project-form-content {
+.project-form {
+  display: flex;
+  flex-direction: column;
   flex: 1;
   flex: 1;
+  gap: 12px;
+}
+
+.project-form-card {
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
 
 
-.project-form-content :deep(.el-card__body) {
+.project-form-card :deep(.el-card__body) {
   padding: 0;
   padding: 0;
 }
 }
 
 
-.project-form {
-  padding: 0 20px;
+.form-card-header {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  min-height: 64px;
+  padding: 14px 18px;
+  background: linear-gradient(90deg, #f7faff 0%, var(--el-bg-color) 78%);
+  border-bottom: 1px solid var(--el-border-color-lighter);
 }
 }
 
 
-.form-section {
-  padding: 16px 0 4px;
+.form-card-header h3 {
+  margin: 0;
+  font-size: 15px;
+  font-weight: 700;
+  line-height: 22px;
+  color: var(--el-text-color-primary);
 }
 }
 
 
-.form-section + .form-section {
-  border-top: 1px solid var(--el-border-color-lighter);
+.form-card-header p {
+  margin: 2px 0 0;
+  font-size: 12px;
+  line-height: 18px;
+  color: var(--el-text-color-secondary);
 }
 }
 
 
-.section-title {
-  position: relative;
-  padding-left: 12px;
-  margin-bottom: 18px;
-  font-size: 15px;
-  font-weight: 600;
-  line-height: 22px;
-  color: var(--el-text-color-primary);
+.form-card-icon {
+  display: inline-flex;
+  flex: 0 0 auto;
+  align-items: center;
+  justify-content: center;
+  width: 36px;
+  height: 36px;
+  font-size: 18px;
+  border-radius: 9px;
+}
+
+.form-card-icon--blue {
+  color: #3478f6;
+  background: #eaf2ff;
+}
+
+.form-card-icon--green {
+  color: #20a36a;
+  background: #e7f8f0;
 }
 }
 
 
-.section-title::before {
-  position: absolute;
-  top: 3px;
-  bottom: 3px;
-  left: 0;
-  width: 3px;
-  background: var(--el-color-primary);
-  border-radius: 2px;
-  content: '';
+.form-card-body {
+  padding: 18px 20px 0;
 }
 }
 
 
 .project-form :deep(.el-select),
 .project-form :deep(.el-select),
@@ -1167,8 +1212,9 @@ const handleSelect = (item: any) => {
     display: none;
     display: none;
   }
   }
 
 
-  .project-form {
-    padding: 0 12px;
+  .form-card-body {
+    padding-right: 12px;
+    padding-left: 12px;
   }
   }
 
 
   .user-select-dialog :deep(.el-dialog) {
   .user-select-dialog :deep(.el-dialog) {

+ 249 - 68
src/views/pms/iotprojecttask/index.vue

@@ -531,21 +531,45 @@ onMounted(async () => {
 
 
   <el-dialog
   <el-dialog
     v-model="planDialogVisible"
     v-model="planDialogVisible"
-    :title="`${currentRow?.contractName || ''} - ${currentRow?.wellName || ''} - 任务计划`"
-    width="80%">
-    <div class="mb-15px">
-      <el-button type="primary" @click="addNewRow">
-        <Icon icon="ep:plus" class="mr-5px" />新增行
-      </el-button>
-    </div>
+    width="min(1440px, calc(100vw - 40px))"
+    class="plan-dialog">
+    <template #header>
+      <div class="plan-dialog-title">
+        <span class="plan-dialog-title__icon">
+          <Icon icon="ep:calendar" />
+        </span>
+        <div class="plan-dialog-title__content">
+          <h3>任务计划</h3>
+          <p>
+            {{ currentRow?.contractName || '未关联合同' }}
+            <span class="plan-dialog-title__separator">·</span>
+            {{ currentRow?.wellName || '未填写井号' }}
+          </p>
+        </div>
+      </div>
+    </template>
 
 
-    <el-table :data="planList" border stripe>
-      <el-table-column label="序号" width="60" align="center">
-        <template #default="scope">
-          {{ scope.$index + 1 }}
-        </template>
-      </el-table-column>
-      <!-- <el-table-column label="施工状态" min-width="200">
+    <div class="plan-dialog-content">
+      <div class="plan-toolbar">
+        <div>
+          <div class="plan-toolbar__title">计划明细</div>
+          <div class="plan-toolbar__subtitle">维护任务开始时间、结束时间及工作量</div>
+        </div>
+        <div class="plan-toolbar__actions">
+          <span class="plan-count">共 {{ planList.length }} 条</span>
+          <el-button size="default" type="primary" @click="addNewRow">
+            <Icon icon="ep:plus" class="mr-5px" />新增计划
+          </el-button>
+        </div>
+      </div>
+
+      <el-table :data="planList" border stripe max-height="50vh" class="plan-table">
+        <el-table-column label="序号" width="60" align="center">
+          <template #default="scope">
+            {{ scope.$index + 1 }}
+          </template>
+        </el-table-column>
+        <!-- <el-table-column label="施工状态" min-width="200">
         <template #default="scope">
         <template #default="scope">
           <el-select
           <el-select
             v-model="scope.row.status"
             v-model="scope.row.status"
@@ -561,63 +585,70 @@ onMounted(async () => {
           </el-select>
           </el-select>
         </template>
         </template>
       </el-table-column> -->
       </el-table-column> -->
-      <el-table-column label="开始时间" min-width="200">
-        <template #default="scope">
-          <el-date-picker
-            v-model="scope.row.startTime"
-            type="datetime"
-            placeholder="选择开始时间"
-            value-format="YYYY-MM-DD HH:mm"
-            format="YYYY-MM-DD HH:mm"
-            class="w-full" />
-        </template>
-      </el-table-column>
-      <el-table-column label="结束时间" min-width="200">
-        <template #default="scope">
-          <el-date-picker
-            v-if="rowShowEndTime(scope.row)"
-            v-model="scope.row.endTime"
-            type="datetime"
-            placeholder="选择结束时间"
-            value-format="YYYY-MM-DD HH:mm"
-            format="YYYY-MM-DD HH:mm"
-            class="w-full" />
-        </template>
-      </el-table-column>
-
-      <el-table-column
-        min-width="100"
-        v-for="item in currentTableColumns"
-        :key="item.identifier"
-        :prop="item.identifier">
-        <template #header>
-          <span>
-            <span v-if="isRequiredColumn(item)" class="required-mark">*</span>
-            {{ item.unit ? `${item.name}(${item.unit})` : item.name }}
-          </span>
-        </template>
-        <template #default="scope">
-          <!-- <el-input type="number" v-model="scope.row[item.identifier]" placeholder="请输入" /> -->
-          <el-input-number
-            style="width: 150px"
-            v-model="scope.row[item.identifier]"
-            :min="0"
-            placeholder="请输入" />
-        </template>
-      </el-table-column>
+        <el-table-column label="开始时间" min-width="200">
+          <template #default="scope">
+            <el-date-picker
+              v-model="scope.row.startTime"
+              type="datetime"
+              placeholder="选择开始时间"
+              value-format="YYYY-MM-DD HH:mm"
+              format="YYYY-MM-DD HH:mm"
+              class="w-full" />
+          </template>
+        </el-table-column>
+        <el-table-column label="结束时间" min-width="200">
+          <template #default="scope">
+            <el-date-picker
+              v-if="rowShowEndTime(scope.row)"
+              v-model="scope.row.endTime"
+              type="datetime"
+              placeholder="选择结束时间"
+              value-format="YYYY-MM-DD HH:mm"
+              format="YYYY-MM-DD HH:mm"
+              class="w-full" />
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          min-width="100"
+          v-for="item in currentTableColumns"
+          :key="item.identifier"
+          :prop="item.identifier">
+          <template #header>
+            <span>
+              <span v-if="isRequiredColumn(item)" class="required-mark">*</span>
+              {{ item.unit ? `${item.name}(${item.unit})` : item.name }}
+            </span>
+          </template>
+          <template #default="scope">
+            <!-- <el-input type="number" v-model="scope.row[item.identifier]" placeholder="请输入" /> -->
+            <el-input-number
+              v-model="scope.row[item.identifier]"
+              size="default"
+              :min="0"
+              class="plan-number-input"
+              placeholder="请输入" />
+          </template>
+        </el-table-column>
 
 
-      <el-table-column label="操作" width="100" align="center">
-        <template #default="scope">
-          <el-button link type="danger" @click="removeRow(scope.$index)">删除</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
+        <el-table-column label="操作" width="100" align="center">
+          <template #default="scope">
+            <el-button link type="danger" @click="removeRow(scope.$index)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
 
 
     <template #footer>
     <template #footer>
-      <span class="dialog-footer">
-        <el-button @click="planDialogVisible = false">取消</el-button>
-        <el-button type="primary" :loading="saveLoading" @click="savePlan">保存</el-button>
-      </span>
+      <div class="plan-dialog-footer">
+        <span>请确认各计划时间和工作量填写完整</span>
+        <div>
+          <el-button size="default" @click="planDialogVisible = false">取消</el-button>
+          <el-button size="default" type="primary" :loading="saveLoading" @click="savePlan">
+            <Icon icon="ep:check" class="mr-5px" />保存
+          </el-button>
+        </div>
+      </div>
     </template>
     </template>
   </el-dialog>
   </el-dialog>
 
 
@@ -709,6 +740,138 @@ onMounted(async () => {
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
 
 
+.plan-dialog-title {
+  display: flex;
+  align-items: center;
+  min-width: 0;
+  padding-right: 40px;
+}
+
+.plan-dialog-title__icon {
+  display: inline-flex;
+  flex: 0 0 auto;
+  align-items: center;
+  justify-content: center;
+  width: 40px;
+  height: 40px;
+  margin-right: 12px;
+  color: #3478f6;
+  background: #eaf2ff;
+  border-radius: 8px;
+}
+
+.plan-dialog-title__content {
+  min-width: 0;
+}
+
+.plan-dialog-title h3 {
+  margin: 0;
+  font-size: 16px;
+  font-weight: 600;
+  line-height: 24px;
+  color: var(--el-text-color-primary);
+}
+
+.plan-dialog-title p {
+  margin: 2px 0 0;
+  overflow: hidden;
+  font-size: 12px;
+  line-height: 18px;
+  color: var(--el-text-color-secondary);
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.plan-dialog-title__separator {
+  margin: 0 6px;
+  color: var(--el-text-color-placeholder);
+}
+
+.plan-dialog :deep(.el-dialog__header) {
+  padding: 16px 20px;
+  margin-right: 0;
+  border-bottom: 1px solid var(--el-border-color-lighter);
+}
+
+.plan-dialog :deep(.el-dialog__body) {
+  padding: 16px 20px;
+}
+
+.plan-dialog :deep(.el-dialog__footer) {
+  padding: 12px 20px;
+  border-top: 1px solid var(--el-border-color-lighter);
+}
+
+.plan-dialog-content {
+  overflow: hidden;
+  border: 1px solid var(--el-border-color-lighter);
+  border-radius: 6px;
+}
+
+.plan-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  min-height: 60px;
+  padding: 10px 14px;
+  background: var(--el-fill-color-extra-light);
+  border-bottom: 1px solid var(--el-border-color-lighter);
+}
+
+.plan-toolbar__title {
+  font-size: 14px;
+  font-weight: 600;
+  line-height: 22px;
+  color: var(--el-text-color-primary);
+}
+
+.plan-toolbar__subtitle {
+  margin-top: 1px;
+  font-size: 12px;
+  line-height: 18px;
+  color: var(--el-text-color-secondary);
+}
+
+.plan-toolbar__actions {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+.plan-count {
+  font-size: 12px;
+  color: var(--el-text-color-secondary);
+  white-space: nowrap;
+}
+
+.plan-table {
+  width: 100%;
+}
+
+.plan-table :deep(.el-table__cell) {
+  padding: 8px 0;
+}
+
+.plan-number-input {
+  width: 100%;
+}
+
+.plan-dialog-footer {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 16px;
+}
+
+.plan-dialog-footer > span {
+  font-size: 12px;
+  color: var(--el-text-color-secondary);
+}
+
+.plan-dialog-footer :deep(.el-button) {
+  margin-left: 8px;
+}
+
 .required-mark {
 .required-mark {
   margin-right: 2px;
   margin-right: 2px;
   color: var(--el-color-danger);
   color: var(--el-color-danger);
@@ -779,6 +942,24 @@ onMounted(async () => {
     width: 100%;
     width: 100%;
   }
   }
 
 
+  .plan-dialog .plan-dialog-title p,
+  .plan-dialog .plan-toolbar__subtitle,
+  .plan-dialog .plan-dialog-footer > span {
+    display: none;
+  }
+
+  .plan-dialog .plan-toolbar {
+    align-items: flex-start;
+  }
+
+  .plan-dialog .plan-toolbar__actions {
+    gap: 8px;
+  }
+
+  .plan-dialog .plan-dialog-footer {
+    justify-content: flex-end;
+  }
+
   .query-row {
   .query-row {
     grid-template-columns: minmax(0, 1fr);
     grid-template-columns: minmax(0, 1fr);
   }
   }