yusheng hai 3 meses
pai
achega
7d6737bd19

+ 2 - 2
src/api/meterModel/index.js

@@ -25,8 +25,8 @@ export async function getById(id) {
   return Promise.reject(new Error(res.data.message));
 }
 // 删除
-export async function del(data) {
-  const res = await request.delete(`/main/meterModel/del`, { data });
+export async function del(id) {
+  const res = await request.delete(`/main/meterModel/del/${id}`);
   if (res.data.code == 0) {
     return res.data.data;
   }

+ 136 - 0
src/api/sealManagement/index.js

@@ -0,0 +1,136 @@
+import request from '@/utils/request';
+
+/**
+ * 新增印章
+ * @param {Object} data 印章数据
+ * @returns {Promise}
+ */
+export async function addSeal(data) {
+  const res = await request.post('/seal/management/add', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 变更印章
+ * @param {Object} data 印章数据
+ * @returns {Promise}
+ */
+export async function changeSeal(data) {
+  const res = await request.post('/seal/management/change', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 删除印章
+ * @param {string|number} id 印章ID
+ * @returns {Promise}
+ */
+export async function deleteSeal(id) {
+  const res = await request.get(`/seal/management/delete/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 停用印章
+ * @param {string|number} id 印章ID
+ * @returns {Promise}
+ */
+export async function disableSeal(id) {
+  const res = await request.put(`/seal/management/disable/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 启用印章
+ * @param {string|number} id 印章ID
+ * @returns {Promise}
+ */
+export async function enableSeal(id) {
+  const res = await request.put(`/seal/management/enable/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 根据ID查询印章详情
+ * @param {string|number} id 印章ID
+ * @returns {Promise}
+ */
+export async function getSealById(id) {
+  const res = await request.get(`/seal/management/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 查询印章历史版本
+ * @param {string|number} sealId 印章ID
+ * @returns {Promise}
+ */
+export async function getSealHistoryList(sealId) {
+  const res = await request.get(`/seal/management/getHistoryList/${sealId}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 分页查询印章列表
+ * @param {Object} params 查询参数
+ * @returns {Promise}
+ */
+export async function getSealPage(data) {
+  const res = await request.post(`/seal/management/page`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新印章
+ * @param {Object} data 印章数据
+ * @returns {Promise}
+ */
+export async function updateSeal(data) {
+  const res = await request.post('/seal/management/update', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 根据印章ID查询使用记录列表
+ * @param {string|number} id 印章ID
+ * @param {Object} params 查询参数
+ * @returns {Promise}
+ */
+export async function getSealUsageRecordList(id, params) {
+  let par = new URLSearchParams(params);
+  const res = await request.get(
+    `/seal/management/usageRecord/listBySealId/${id}?` + par,
+    {}
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 127 - 0
src/components/upload/WithViewNew.vue

@@ -0,0 +1,127 @@
+<template>
+  <div>
+    <div class="img-view" v-if="dialogImageUrl">
+      <img :src="dialogImageUrl" alt="" srcset="" />
+    </div>
+    <div class="placeholder-box" v-else>
+      <img src="~@/assets/upload-placeholder.svg" alt="" />
+    </div>
+    <div class="btn-box">
+      <el-upload
+        class="avatar-div"
+        action="#"
+        accept="image/png,image/jpeg"
+        :show-file-list="false"
+        ref="uploadRef"
+        :on-exceed="handleExceed"
+        :limit="1"
+        :http-request="handlSuccess"
+        :multiple="false"
+      >
+        <el-button type="text" v-if="disabled"
+          >上传{{ assetName }}图片</el-button
+        >
+      </el-upload>
+      <el-button type="text" v-if="disabled" @click="clearImg"
+        >清除图片</el-button
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+  import { uploadFile, removeFile } from '@/api/system/file/index.js';
+  import { getImageUrl } from '@/utils/file';
+  export default {
+    props: {
+      assetName: {
+        type: String,
+        default: ' '
+      },
+      value: {
+        type: String,
+        default: ''
+      },
+      disabled: {
+        type: Boolean,
+        default: false
+      },
+      // 所属模块
+      module: {
+        type: String,
+        default: 'main'
+      }
+    },
+    data() {
+      return {};
+    },
+    computed: {
+      dialogImageUrl() {
+        return this.value;
+      }
+    },
+    methods: {
+      // 清空已上传的文件列表
+      clearUploadFiles() {},
+      //图片添加
+      async handlSuccess(params) {
+        let res = await uploadFile({
+          multiPartFile: params.file,
+          module: this.module
+        });
+        if (res?.data) {
+          this.$emit('input', res.data.url);
+        }
+      },
+      async clearImg() {
+        // await removeFile({ fileId: this.value.id });
+        this.$emit('input', '');
+        this.$refs.uploadRef.clearFiles();
+      },
+      // 限制上传的数量
+      handleExceed(files, fileList) {
+        this.$message.warning(`最多允许上传一张图片!`);
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .img-view {
+    width: 280px;
+    height: 342px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    border-width: 1px;
+    border-style: solid;
+    border-color: rgba(215, 215, 215, 1);
+
+    img {
+      max-width: 100%;
+      max-height: 100%;
+    }
+  }
+
+  .placeholder-box {
+    width: 250px;
+    height: 200px;
+    text-align: center;
+
+    background-color: rgba(242, 242, 242, 1);
+    box-sizing: border-box;
+    border-width: 1px;
+    border-style: solid;
+    border-color: rgba(215, 215, 215, 1);
+    padding-top: 60px;
+
+    img {
+      width: 100px;
+      height: 100px;
+    }
+  }
+
+  .btn-box {
+    display: flex;
+    justify-content: space-around;
+  }
+</style>

+ 11 - 1
src/views/meterModel/energyDialog.vue

@@ -72,6 +72,12 @@
             </el-col>
             <el-col :span="12">
               <el-form-item label="表计图片" prop="modelImg">
+                <el-input
+                  clearable
+                  v-model="form.modelImg"
+                  placeholder="请选择"
+                  v-show="false"
+                />
                 <fileMain
                   v-model="form.modelImg"
                   :type="title == '详情' ? 'view' : 'add'"
@@ -358,7 +364,11 @@
             }
           ],
 
-          modelImg: [{ required: true, message: '请选择', trigger: 'change' }]
+          modelImg: [
+            { required: true, message: '请选择', trigger: 'change' },
+            { required: true, message: '请输入', trigger: 'blur' },
+            { required: true, message: '请输入', trigger: 'input' }
+          ]
         }
       };
     },

+ 11 - 6
src/views/meterModel/index.vue

@@ -46,7 +46,10 @@
           </template>
 
           <template v-slot:action="{ row }">
-            <el-link type="primary" :underline="false" @click="handleEdit(row,'edit')"
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="handleEdit(row, 'edit')"
               >编辑</el-link
             >
             <el-link
@@ -73,7 +76,7 @@
 
 <script>
   import EnergyDialog from './energyDialog.vue';
-  import { getPage } from '@/api/meterModel/index.js';
+  import { getPage, del } from '@/api/meterModel/index.js';
   import tabMixins from '@/mixins/tableColumnsMixin';
   import dictMixins from '@/mixins/dictMixins';
 
@@ -98,7 +101,7 @@
           },
           {
             prop: 'code',
-            slot:'code',
+            slot: 'code',
             label: '表计模版编码',
             align: 'center',
             minWidth: 120,
@@ -211,8 +214,8 @@
         this.$refs.energyDialogRef.open();
       },
       // 编辑
-      handleEdit(row,type) {
-        this.$refs.energyDialogRef.open(row,type);
+      handleEdit(row, type) {
+        this.$refs.energyDialogRef.open(row, type);
       },
       // 删除
       handleDelete(row) {
@@ -222,7 +225,9 @@
           type: 'warning'
         })
           .then(() => {
-            this.$message.success('删除成功');
+            del(row.id).then(res=>{
+              this.handleSearch()
+            })
           })
           .catch(() => {});
       },

+ 437 - 0
src/views/sealManagement/index.vue

@@ -0,0 +1,437 @@
+<template>
+  <div class="seal-management">
+    <el-card shadow="never" class="config-card">
+      <!-- 搜索区域 -->
+      <div class="search-area">
+        <seek-page
+          :seekList="seekList"
+          @search="handleSearch"
+          @reset="handleReset"
+          :formLength="3"
+        />
+      </div>
+
+      <!-- 列表视图 -->
+      <div class="list-view">
+        <ele-pro-table
+          ref="table"
+          row-key="id"
+          :columns="columns"
+          :datasource="datasource"
+          :cache-key="cacheKeyUrl"
+          height="calc(100vh - 350px)"
+        >
+          <template v-slot:toolbar>
+            <el-button
+              type="primary"
+              size="small"
+              icon="el-icon-plus"
+              @click="handleAdd"
+              >新增</el-button
+            >
+            <el-button
+              type="danger"
+              size="small"
+              icon="el-icon-delete"
+              @click="handleBatchDelete"
+              >删除</el-button
+            >
+          </template>
+          <template v-slot:imgUrl="{ row }">
+            <el-image
+              style="width: 60px; height: 60px"
+              :src="row.imgUrl"
+              :preview-src-list="[row.imgUrl]"
+            >
+            </el-image>
+          </template>
+          <template v-slot:code="{ row }">
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="handleEdit(row, 'view')"
+              >{{ row.code }}</el-link
+            >
+          </template>
+          <template v-slot:action="{ row }" >
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="handleEdit(row)"
+              v-if="[0, 3].includes(row.approvalStatus)&&row.isLatest==1"
+              >修改</el-link
+            >
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="handleSubmit(row)"
+              style="margin-left: 8px"
+              v-if="[0, 3].includes(row.approvalStatus)&&row.isLatest==1"
+              >提交</el-link
+            >
+            <el-link
+              type="danger"
+              :underline="false"
+              @click="handleDelete(row)"
+              style="margin-left: 8px"
+              v-if="[0, 3].includes(row.approvalStatus)&&row.isLatest==1"
+              >删除</el-link
+            >
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="handleModify(row)"
+              v-if="[2].includes(row.approvalStatus)&&row.isLatest==1"
+              >变更</el-link
+            >
+            <el-link
+              type="danger"
+              :underline="false"
+              @click="handleStop(row)"
+              v-if="[2].includes(row.approvalStatus) && row.status == 1&&row.isLatest==1"
+              style="margin-left: 8px"
+              >停用</el-link
+            >
+          </template>
+        </ele-pro-table>
+      </div>
+
+      <!-- 新增/编辑弹窗 -->
+      <seal-dialog ref="sealDialogRef" @reload="$refs.table.reload()" />
+    </el-card>
+    <process-submit-dialog
+      :isNotNeedProcess="false"
+      :processSubmitDialogFlag.sync="processSubmitDialogFlag"
+      v-if="processSubmitDialogFlag"
+      ref="processSubmitDialogRef"
+      @reload="handleSearch"
+    ></process-submit-dialog>
+  </div>
+</template>
+
+<script>
+  import SealDialog from './sealDialog.vue';
+  import {
+    getSealPage,
+    deleteSeal,
+    disableSeal,
+    enableSeal
+  } from '@/api/sealManagement';
+  import { reviewStatus } from '@/enum/dict';
+  import processSubmitDialog from '@/components/processSubmitDialog/processSubmitDialog.vue';
+
+  export default {
+    components: {
+      SealDialog,
+      processSubmitDialog
+    },
+    data() {
+      return {
+        processSubmitDialogFlag: false,
+        // 表格列配置
+        columns: [
+          {
+            columnKey: 'selection',
+            type: 'selection',
+            width: 55,
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            prop: 'code',
+            label: '印章编码',
+            align: 'center',
+            slot: 'code',
+            minWidth: 150,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'name',
+            label: '印章名称',
+            align: 'center',
+            minWidth: 130,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'sealNumber',
+            label: '印章编号',
+            align: 'center',
+            minWidth: 150,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'type',
+            label: '类型',
+            align: 'center',
+            minWidth: 110,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'version',
+            label: '版本',
+            align: 'center',
+            minWidth: 80,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'holder',
+            label: '印章持有人',
+            align: 'center',
+            minWidth: 100,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'imgUrl',
+            label: '印章图片',
+            align: 'center',
+            slot: 'imgUrl',
+            minWidth: 80
+          },
+          {
+            prop: 'validEndDate',
+            label: '有效期起止时间',
+            align: 'center',
+            minWidth: 250,
+            formatter: (row) => {
+              if (row.isLongTerm != 1) {
+                return row.validStartDate + '至' + row.validEndDate;
+              }
+            },
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'approveStatus',
+            label: '审批状态',
+            align: 'center',
+            minWidth: 120,
+            formatter: (_row, _column, cellValue) => {
+              return reviewStatus[_row.approvalStatus];
+            },
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'publishStatus',
+            label: '发布状态',
+            align: 'center',
+            minWidth: 120,
+            formatter: (_row, _column, cellValue) => {
+              return _row.publishStatus == 1
+                ? '已发布'
+                : _row.publishStatus == 2
+                ? '已撤销'
+                : '未发布';
+            }
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            align: 'center',
+            minWidth: 120,
+            formatter: (_row, _column, cellValue) => {
+              return _row.status == 1 ? '启用' : '停用';
+            }
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 200,
+            align: 'center',
+            slot: 'action'
+          }
+        ],
+        cacheKeyUrl: 'seal-management-list'
+      };
+    },
+    computed: {
+      seekList() {
+        return [
+          {
+            label: '印章编码',
+            value: 'sealCode',
+            type: 'input',
+            width: 160,
+            placeholder: '请输入'
+          },
+          {
+            label: '印章名称',
+            value: 'sealName',
+            type: 'input',
+            width: 160,
+            placeholder: '请输入'
+          },
+          {
+            label: '印章类型',
+            value: 'type',
+            type: 'select',
+            width: 120,
+            placeholder: '请选择',
+            planList: [
+              { value: '', label: '全部' },
+              { label: '法律效力章', value: '法律效力章' },
+              { label: '财务专用章', value: '财务专用章' },
+              { label: '业务专用章', value: '业务专用章' },
+              { label: '内部管理章', value: '内部管理章' }
+            ]
+          },
+          {
+            label: '印章持有人',
+            value: 'holder',
+            type: 'input',
+            width: 160,
+            placeholder: '请输入'
+          }
+        ];
+      }
+    },
+    methods: {
+      // 新增
+      handleAdd() {
+        this.$refs.sealDialogRef.open();
+      },
+      // 编辑
+      handleEdit(row, type = 'edit') {
+        this.$refs.sealDialogRef.open(row, type);
+      },
+      // 提交
+      handleSubmit(res) {
+        this.processSubmitDialogFlag = true;
+        this.$nextTick(() => {
+          let params = {
+            businessId: res.id,
+            businessKey: 'main_seal_management_approval',
+            formCreateUserId: res.createUserId,
+            variables: {
+              businessCode: res.code,
+              businessName: res.name,
+              businessType: '印章审核'
+            }
+          };
+
+          this.$refs.processSubmitDialogRef.init(params);
+        });
+      },
+      // 删除
+      handleDelete(row) {
+        this.$confirm('确认删除该印章吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+          .then(async () => {
+            try {
+              await deleteSeal(row.id);
+              this.$message.success('删除成功');
+              this.$refs.table.reload();
+            } catch (error) {
+              this.$message.error(error.message || '删除失败');
+            }
+          })
+          .catch(() => {});
+      },
+      // 批量删除
+      handleBatchDelete() {
+        const selected = this.$refs.table.getSelectionRows();
+        if (!selected || selected.length === 0) {
+          this.$message.warning('请选择要删除的数据');
+          return;
+        }
+        this.$confirm(
+          `确认删除选中的 ${selected.length} 条印章记录吗?`,
+          '提示',
+          {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }
+        )
+          .then(async () => {
+            try {
+              const promises = selected.map((item) => deleteSeal(item.id));
+              await Promise.all(promises);
+              this.$message.success('删除成功');
+              this.$refs.table.reload();
+            } catch (error) {
+              this.$message.error(error.message || '删除失败');
+            }
+          })
+          .catch(() => {});
+      },
+      // 变更
+      handleModify(row) {
+        this.$refs.sealDialogRef.open(row, 'modify');
+      },
+      // 停用
+      handleStop(row) {
+        this.$confirm('确认停用该印章吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+          .then(async () => {
+            try {
+              await disableSeal(row.id);
+              this.$message.success('停用成功');
+              this.$refs.table.reload();
+            } catch (error) {
+              this.$message.error(error.message || '停用失败');
+            }
+          })
+          .catch(() => {});
+      },
+
+      // 搜索
+      handleSearch(where) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+      // 重置
+      handleReset() {
+        this.$refs.table.reload({ page: 1 });
+      },
+      // 表格数据源
+      async datasource({ page, limit, where }) {
+        return await getSealPage({ page, limit, ...where });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .seal-management {
+    .config-card {
+      height: calc(100vh - 100px);
+
+      ::v-deep .el-card__body {
+        height: 100%;
+        padding: 15px;
+        display: flex;
+        flex-direction: column;
+      }
+    }
+
+    // 搜索区域
+    .search-area {
+      margin-bottom: 15px;
+      padding-bottom: 15px;
+      border-bottom: 1px solid #ebeef5;
+    }
+
+    // 列表视图
+    .list-view {
+      flex: 1;
+      overflow: hidden;
+
+      ::v-deep .ele-pro-table {
+        .el-table {
+          border: 1px solid #ebeef5;
+          border-radius: 4px;
+        }
+      }
+    }
+  }
+</style>

+ 502 - 0
src/views/sealManagement/sealDialog.vue

@@ -0,0 +1,502 @@
+<template>
+  <ele-modal
+    :visible="visible"
+    :title="title"
+    width="1200px"
+    :destroy-on-close="true"
+    @update:visible="updateVisible"
+    :maxable="true"
+    append-to-body
+  >
+    <div class="switch" v-if="title == '详情'">
+      <div class="switch_left">
+        <ul>
+          <li
+            v-for="item in tabOptions"
+            :key="item.key"
+            :class="{ active: activeComp == item.key }"
+            @click="activeComp = item.key"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+      </div>
+    </div>
+    <el-form
+      ref="formRef"
+      :model="form"
+      :rules="rules"
+      label-width="120px"
+      size="small"
+      v-show="activeComp == 'main'"
+      style="margin-top: 15px"
+    >
+      <!-- 第一行:印章编码 + 印章名称 -->
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="印章编码" prop="code">
+            <el-input
+              v-model="form.code"
+              placeholder="系统自动生成,唯一码"
+              disabled
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="印章名称" prop="name" required>
+            <el-input
+              v-model="form.name"
+              placeholder="请输入"
+              :disabled="title == '详情' || title == '变更'"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 第二行:印章类型 + 印章编号 -->
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="印章类型" prop="sealType" required>
+            <el-select
+              v-model="form.sealType"
+              placeholder="请选择"
+              clearable
+              style="width: 100%"
+              :disabled="title == '详情' || title == '变更'"
+            >
+              <el-option
+                v-for="item in sealTypeList"
+                :label="item.label"
+                :key="item.value"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="印章编号" prop="sealNumber">
+            <el-input
+              v-model="form.sealNumber"
+              placeholder="请输入"
+              :disabled="title == '详情' || title == '变更'"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 第三行:印章持有人 + 版本 -->
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="印章持有人" prop="sealHolderName">
+            <el-input
+              :maxlength="20"
+              v-model="form.sealHolderName"
+              @click.native="setUsers"
+              placeholder="选择人员"
+              :disabled="title == '详情'"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="版本" prop="version" required>
+            <el-input
+              v-model="form.version"
+              placeholder="请输入"
+              :disabled="title == '详情'"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 第四行:是否长期有效 + 状态 -->
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="是否长期有效" prop="isLongTerm" required>
+            <el-radio-group
+              v-model="form.isLongTerm"
+              :disabled="title == '详情'"
+            >
+              <el-radio :label="1">长期</el-radio>
+              <el-radio :label="0">非长期</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="状态" prop="status" required>
+            <el-switch
+              v-model="form.status"
+              :disabled="title == '详情'"
+              :active-value="1"
+              :inactive-value="0"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 非长期时显示有效期 -->
+      <el-row :gutter="20" v-if="form.isLongTerm == '0'">
+        <el-col :span="12">
+          <el-form-item label="有效期开始日期" prop="validStartDate">
+            <el-date-picker
+              v-model="form.validStartDate"
+              :disabled="title == '详情'"
+              type="date"
+              value-format="yyyy-MM-dd"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="有效期结束日期" prop="validEndDate">
+            <el-date-picker
+              v-model="form.validEndDate"
+              type="date"
+              value-format="yyyy-MM-dd"
+              :disabled="title == '详情'"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 印章图片上传 -->
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="印章图片" prop="imgUrl" required>
+            <div class="upload-container">
+              <WithView
+                :assetName="''"
+                :disabled="title == '详情'"
+                v-model="form.imgUrl"
+                style="max-height: 370px"
+              ></WithView>
+              <div class="upload-tips">
+                <p>上传要求:</p>
+                <p>1、图像样式必须与实物印章的印模规制保持一致。</p>
+                <p>2、印模必须清晰、完整、无断裂、无拖影</p>
+              </div>
+            </div>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <template slot="footer">
+      <el-button
+        type="primary"
+        size="small"
+        @click="handleSave"
+        v-if="title != '详情'"
+        >保存</el-button
+      >
+      <el-button
+        type="primary"
+        size="small"
+        @click="handleSaveAndSubmit"
+        v-if="title != '详情'"
+        >保存并提交</el-button
+      >
+      <el-button size="small" @click="handleCancel">取消</el-button>
+    </template>
+    <addUser ref="addREf" @success="userBk"></addUser>
+    <bpmDetail
+      v-if="activeComp == 'bpm' && form.processInstanceId"
+      :id="form.processInstanceId"
+    ></bpmDetail>
+  </ele-modal>
+</template>
+
+<script>
+  import {
+    addSeal,
+    changeSeal,
+    updateSeal,
+    getSealById
+  } from '@/api/sealManagement';
+  import addUser from '@/views/system/user/components/add.vue';
+  import WithView from '@/components/upload/WithViewNew.vue';
+  import bpmDetail from '@/views/bpm/processInstance/businessDetail.vue';
+
+  const defaultForm = {
+    code: '',
+    imgUrl: '',
+    isLongTerm: 1,
+    name: '',
+    remark: '',
+    sealHolderId: '',
+    sealHolderName: '',
+    sealNumber: '',
+    sealType: '',
+    sealTypeName: '',
+    status: 1,
+    processInstanceId: '',
+    validEndDate: '',
+    validStartDate: '',
+    version: ''
+  };
+
+  export default {
+    components: { addUser, WithView, bpmDetail },
+    name: 'SealDialog',
+    data() {
+      return {
+        activeComp: 'main',
+        tabOptions: [
+          { key: 'main', name: '详情' },
+          { key: 'bpm', name: '流程详情' }
+        ],
+        visible: false,
+        title: '新增',
+        sealTypeList: [
+          {
+            label: '法律效力章',
+            value: '1'
+          },
+          {
+            label: '财务专用章',
+            value: '2'
+          },
+          {
+            label: '业务专用章',
+            value: '3'
+          },
+          {
+            label: '内部管理章',
+            value: '4'
+          }
+        ],
+        form: {
+          ...defaultForm
+        },
+        rules: {
+          name: [
+            { required: true, message: '请输入印章名称', trigger: 'blur' }
+          ],
+          sealType: [
+            { required: true, message: '请选择印章类型', trigger: 'change' }
+          ],
+          version: [{ required: true, message: '请输入版本', trigger: 'blur' }],
+          isLongTerm: [
+            { required: true, message: '请选择是否长期有效', trigger: 'change' }
+          ],
+          status: [
+            { required: true, message: '请选择状态', trigger: 'change' }
+          ],
+          imgUrl: [
+            { required: true, message: '请上传印章图片', trigger: 'change' }
+          ],
+          validStartDate: [
+            { required: true, message: '请选择', trigger: 'change' }
+          ],
+          validEndDate: [
+            { required: true, message: '请选择', trigger: 'change' }
+          ]
+        }
+      };
+    },
+    methods: {
+      open(row, type = 'add') {
+        this.activeComp = 'main';
+        console.log(type, 'type');
+
+        if (row && (type == 'edit' || type == 'modify' || type == 'view')) {
+          getSealById(row.id).then((res) => {
+            this.form = res;
+            if (type == 'modify') {
+              this.form.parentId = row.id;
+            }
+          });
+          this.title =
+            type == 'edit' ? '修改' : type == 'modify' ? '变更' : '详情';
+        } else {
+          this.title = '新增';
+          this.resetForm();
+        }
+        this.visible = true;
+      },
+      setUsers() {
+        this.$refs.addREf.open();
+      },
+      updateVisible(val) {
+        this.visible = val;
+        if (!val) {
+          this.resetForm();
+        }
+      },
+      userBk(data) {
+        this.form.sealHolderId = data.id;
+        this.form.sealHolderName = data.name;
+      },
+      resetForm() {
+        this.form = {
+          ...defaultForm
+        };
+        this.$nextTick(() => {
+          this.$refs.formRef && this.$refs.formRef.clearValidate();
+        });
+      },
+      // 图片上传
+      handleImageChange(file) {
+        const isJPG = file.raw.type === 'image/jpeg';
+        const isPNG = file.raw.type === 'image/png';
+        const isBMP = file.raw.type === 'image/bmp';
+        const isLt10M = file.raw.size / 1024 / 1024 < 10;
+
+        if (!isJPG && !isPNG && !isBMP) {
+          this.$message.error('上传图片只能是 JPG、PNG、BMP 格式!');
+          return false;
+        }
+        if (!isLt10M) {
+          this.$message.error('上传图片大小不能超过 10MB!');
+          return false;
+        }
+
+        this.form.sealImage = file.raw;
+        this.form.sealImageUrl = URL.createObjectURL(file.raw);
+      },
+      // 删除图片
+      handleRemoveImage() {
+        this.form.sealImage = '';
+        this.form.sealImageUrl = '';
+      },
+      // 构建提交数据
+      buildSubmitData() {
+        const data = { ...this.form };
+        // 处理有效期
+        if (data.isLongTerm === '1') {
+          data.validityPeriod = '长期';
+        } else if (
+          data.validityDateRange &&
+          data.validityDateRange.length === 2
+        ) {
+          data.validityPeriod = `${data.validityDateRange[0]}至${data.validityDateRange[1]}`;
+        }
+        // 删除临时字段
+        delete data.validityDateRange;
+        delete data.sealImageUrl;
+        return data;
+      },
+      // 保存
+      async handleSave() {
+        this.$refs.formRef.validate(async (valid) => {
+          if (valid) {
+            try {
+              const data = this.buildSubmitData();
+              if (this.title === '新增') {
+                await addSeal(data);
+              } else if (this.title === '变更') {
+                await changeSeal(data);
+              } else {
+                await updateSeal(data);
+              }
+              this.$message.success('保存成功');
+              this.$emit('reload');
+              this.visible = false;
+            } catch (error) {
+              this.$message.error(error.message || '保存失败');
+            }
+          }
+        });
+      },
+      // 保存并提交
+      async handleSaveAndSubmit() {
+        this.$refs.formRef.validate(async (valid) => {
+          if (valid) {
+            try {
+              const data = this.buildSubmitData();
+              data.submitFlag = true; // 标记为提交
+              if (this.title === '新增') {
+                await addSeal(data);
+              } else if (this.title === '变更') {
+                await changeSeal(data);
+              } else {
+                await updateSeal(data);
+              }
+              this.$message.success('保存并提交成功');
+              this.$emit('reload');
+              this.visible = false;
+            } catch (error) {
+              this.$message.error(error.message || '保存并提交失败');
+            }
+          }
+        });
+      },
+      // 取消
+      handleCancel() {
+        this.visible = false;
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  .upload-container {
+    display: flex;
+    align-items: flex-start;
+    gap: 20px;
+  }
+
+  .seal-uploader {
+    width: 200px;
+    height: 200px;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+    background-color: #f5f7fa;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .seal-uploader:hover {
+    border-color: #409eff;
+  }
+
+  .uploader-placeholder {
+    text-align: center;
+    color: #8c939d;
+  }
+
+  .uploader-placeholder .el-icon-picture-outline {
+    font-size: 48px;
+    margin-bottom: 10px;
+  }
+
+  .upload-text {
+    display: flex;
+    gap: 10px;
+    justify-content: center;
+  }
+
+  .delete-btn {
+    color: #f56c6c;
+  }
+
+  .seal-image {
+    width: 100%;
+    height: 100%;
+    object-fit: contain;
+  }
+
+  .upload-tips {
+    flex: 1;
+    font-size: 12px;
+    color: #606266;
+    line-height: 1.8;
+  }
+
+  .upload-tips p {
+    margin: 0;
+    padding: 0;
+  }
+
+  .upload-tips p:first-child {
+    font-weight: bold;
+    margin-bottom: 5px;
+  }
+</style>

+ 1 - 1
vue.config.js

@@ -39,7 +39,7 @@ module.exports = {
         // target: 'http://192.168.1.251:18186',
         // target: 'http://192.168.1.251:18086',
         // target: 'http://192.168.1.251:18186',
-        target: 'http://192.168.1.125:18086',
+        target: 'http://192.168.1.3:18086',
         // target: 'http://192.168.1.251:18186', // 测试环境
         // target: 'http://192.168.1.251:18087',
         // target: 'http://192.168.1.116:18086',