zhouwx
2025-03-14 3533b11c19b628e45f26d25bedd7c82e0aa2037a
接口对接
已修改12个文件
已添加4个文件
964 ■■■■■ 文件已修改
.env.development 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/menu.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/signAgreement/signProject.js 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/signAgreement/signType.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/signAgreement/template.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/signProject/components/circulation.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/signProject/components/record.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/signProject/components/viewPdf.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/signProject/index.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/signTypeManage/components/addDialog.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/signTypeManage/index.vue 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/templateManage/components/createSign.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/templateManage/components/templateDialog.vue 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/templateManage/index.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -7,7 +7,7 @@
# 纳米所安全责任书签署/开发环境
#小董
VITE_APP_BASE_API = 'http://192.168.2.21:8085/signature'
VITE_APP_BASE_API = 'http://192.168.2.30:8085/signature'
#线上
#VITE_APP_BASE_API = 'http://8.137.115.153:85/api'
package.json
@@ -23,6 +23,7 @@
    "@wangeditor/editor-for-vue": "^5.1.12",
    "@wangeditor/plugin-upload-attachment": "^1.1.0",
    "axios": "0.27.2",
    "crypto-browserify": "^3.12.1",
    "docxtemplater": "^3.54.0",
    "echarts": "5.4.0",
    "element-plus": "2.2.27",
@@ -36,13 +37,17 @@
    "jszip-utils": "^0.1.0",
    "moment": "^2.30.1",
    "nprogress": "0.2.0",
    "path-browserify": "^1.0.1",
    "pdfjs-dist": "^4.10.38",
    "pinia": "2.0.22",
    "pizzip": "^3.1.7",
    "quill": "^2.0.0-dev.3",
    "stream-browserify": "^3.0.0",
    "tinymce": "^5.10.2",
    "vue": "3.2.45",
    "vue-baidu-map-3x": "^1.0.35",
    "vue-cropper": "1.0.3",
    "vue-pdf": "^4.3.0",
    "vue-quill-editor": "^3.0.6",
    "vue-router": "4.1.4",
    "vue3-json-excel": "^1.0.10-alpha",
@@ -58,6 +63,7 @@
    "unplugin-vue-setup-extend-plus": "0.4.9",
    "vite": "3.2.3",
    "vite-plugin-compression": "0.5.1",
    "vite-plugin-require": "^1.2.14",
    "vite-plugin-svg-icons": "2.0.1"
  }
}
src/api/menu.js
@@ -6,4 +6,4 @@
    url: '/getRouters',
    method: 'get'
  })
}
}
src/api/signAgreement/signProject.js
对比新文件
@@ -0,0 +1,51 @@
import request from '@/utils/request'
export function getSignProject(params) {
    return request({
        url: '/item/list',
        method: 'get',
        params: params
    })
}
export function addSignProject(data) {
    return request({
        url: '/item/insert',
        method: 'post',
        data: data
    })
}
export function editSignProject(params) {
    return request({
        url: `/item/update`,
        method: 'post',
        data: params
    })
}
export function delSignProject(data) {
    return request({
        url: `/item/delete/` + data,
        method: 'post',
    })
}
export function signFlow(data) {
    return request({
        url: `/flow/insert`,
        method: 'post',
        data: data
    })
}
export function signArchive(data) {
    return request({
        url: `/flow/returnFile`,
        method: 'post',
        data: data
    })
}
src/api/signAgreement/signType.js
对比新文件
@@ -0,0 +1,34 @@
import request from '@/utils/request'
export function getSignType(params) {
    return request({
        url: '/type/list',
        method: 'get',
        params: params
    })
}
export function addType(data) {
    return request({
        url: '/type/insert',
        method: 'post',
        data: data
    })
}
export function editType(params) {
    return request({
        url: `/type/update`,
        method: 'post',
        data: params
    })
}
export function delType(data) {
    return request({
        url: `/type/delete/` + data,
        method: 'post',
    })
}
src/api/signAgreement/template.js
对比新文件
@@ -0,0 +1,35 @@
import request from '@/utils/request'
export function getTemplate(params) {
    return request({
        url: '/template/list',
        method: 'get',
        params: params
    })
}
export function addTemplate(data) {
    return request({
        url: '/template/insert',
        method: 'post',
        data: data
    })
}
export function editTemplate(params) {
    return request({
        url: `/template/update`,
        method: 'post',
        data: params
    })
}
export function delTemplate(data) {
    return request({
        url: `/template/delete/` + data,
        method: 'post',
        data: data
    })
}
src/store/modules/user.js
@@ -48,6 +48,7 @@
            this.name = user.userName
            this.avatar = avatar
            Cookies.set('userInfo',JSON.stringify(user))
            Cookies.set('userRole',JSON.stringify(this.roles))
            resolve(res)
          }).catch(error => {
            reject(error)
src/views/signProject/components/circulation.vue
@@ -9,27 +9,25 @@
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
        <el-form-item label="部门:" prop="deptId" >
        <el-form-item label="部门:" prop="signDeptId" >
          <el-cascader
              style="width: 100%"
              clearable
              v-model="state.form.deptId"
              v-model="state.form.signDeptId"
              :options="state.options"
              @change="selectValue"
              :props="{ expandTrigger: 'hover', value: 'deptId',label: 'deptName',emitPath: false}"></el-cascader>
        </el-form-item>
        <el-form-item label="签署人:" prop="people" >
        <el-form-item label="签署人:" prop="signUserId" >
          <el-select
              clearable
              v-model="state.form.people"
              v-model="state.form.signUserId"
              filterable
              multiple
              remote
              reserve-keyword
              placeholder="请输入签署人名称(可多选)"
              remote-show-suffix
              :remote-method="(val)=>getUserList(val,state.form.deptId)"
              :remote-method="(val)=>getUserList(val,state.form.signDeptId)"
              style="width: 100%"
          >
            <el-option
@@ -55,6 +53,8 @@
import {ElMessage} from "element-plus";
import {listDept} from "@/api/system/dept";
import {listUser} from "@/api/system/user";
import {signFlow} from "@/api/signAgreement/signProject";
import {getInfo} from "@/api/login";
const { proxy } = getCurrentInstance();
const dialogVisible = ref(false);
@@ -65,26 +65,29 @@
const state = reactive({
  form: {
    id: '',
    deptId: '',
    people: []
    itemId: null,
    signUserId: null,
    signDeptId: null
  },
  user: {},
  options: [],
  userList: [],
  formRules:{
    deptId: [{ required: true, trigger: "blur", message:'请选择部门' }],
    people: [{ required: true, trigger: "blur", message:'请选择签署人' }],
    signDeptId: [{ required: true, trigger: "blur", message:'请选择部门' }],
    signUserId: [{ required: true, trigger: "blur", message:'请选择签署人' }],
  },
})
const openDialog = async (value) => {
  await getDept()
  await getUserInfo()
  state.form.itemId = value.id
  dialogVisible.value = true;
}
const selectValue = (val) => {
  state.userList = []
  state.form.people = []
  state.form.signUserId = []
  getUserList("",val)
}
@@ -96,25 +99,37 @@
  });
}
const getUserInfo = async () => {
  const res = await getInfo()
  if(res.code == 200){
    state.user = res.user
  }else{
    ElMessage.warning(res.message)
  }
}
const onSubmit = async () => {
  const valid = await busRef.value.validate();
  if(valid){
      const {id, ...data} = JSON.parse(JSON.stringify(state.form))
      // const res = await addWarehouse(data)
      // if(res.code === 200){
      //   ElMessage({
      //     type: 'success',
      //     message: '新增成功'
      //   });
      // }else{
      //   ElMessage.warning(res.message)
      // }
      data.userId = state.user.userId
      data.userName = state.user.userName
      data.deptId = state.user.deptId
      data.deptName = state.user.dept.deptName
      const res = await signFlow(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '流转成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
  }
}
@@ -126,9 +141,9 @@
}
const reset = () => {
  state.form = {
    id: '',
    name: '',
    remark: '',
    itemId: null,
    signUserId: null,
    signDeptId: null
  }
}
const getUserList = async (val,deptId)=>{
src/views/signProject/components/record.vue
@@ -9,22 +9,32 @@
        :close-on-click-modal="false"
    >
      <el-timeline style="max-width: 600px">
        <el-timeline-item size="large" color="#0bbd87" style="font-size: 16px">
          <div>创建人:{{state.creatContent}}</div>
        </el-timeline-item>
        <el-timeline-item style="font-size: 16px" :color="state.firstPeopleState == 1 ? '#0bbd87' : '#B4B4B4' " size="large">
          <div>
            最初签署人:{{state.firstPeopleContent}}
            <span v-if="state.firstPeopleState == 1" style="color: #1ab394;font-size: 14px;">[已签]</span>
            <span v-else style="color: #6d737b;font-size: 14px;">[未签]</span>
          </div>
        </el-timeline-item>
        <el-timeline-item
            v-for="(activity, index) in state.activities"
            :key="index"
            :icon="activity.icon"
            :type="activity.type"
            :color="activity.state == 1 ? '#0bbd87' : '#B4B4B4' "
            :size="activity.size"
            size="large"
            style="font-size: 16px"
            :color="activity.signStatus == 1 || activity.signStatus == 3 ? '#0bbd87' : '#B4B4B4' "
        >
          <div style="display: flex;font-size: 16px">
            <div style="display: flex;flex-direction: column">
              <span v-if="activity.title" style="font-size: 14px;margin-bottom: 5px;color: #6d737b">{{activity.title}}</span>
              <span  style="font-size: 14px;margin-bottom: 5px;color: #6d737b">由 {{activity.deptName}} {{activity.userName}} 流转</span>
              <div>
                <span style="font-size: 16px">{{activity.content}}</span>
                <span v-if="activity.state == 1 && index != 3" style="color: #1ab394;font-size: 14px;margin-left: 5px">[已签]</span>
                <span v-if="activity.state == 0 && index != 3" style="color: #6d737b;font-size: 14px;margin-left: 5px">[未签]</span>
                <span v-if="activity.state == 1 && index == 3" style="color: #1ab394;font-size: 14px;margin-left: 5px">[已归档]</span>
                <span style="font-size: 16px" >{{activity.signUserName}}({{activity.signDeptName}})</span>
                <span v-if="activity.signStatus == 1" style="color: #1ab394;font-size: 14px;margin-left: 5px">[已签]</span>
                <span v-else-if="activity.signStatus == 0 || activity.signStatus == null " style="color: #6d737b;font-size: 14px;margin-left: 5px">[未签]</span>
                <span v-else-if="activity.signStatus == 3 && state.form.itemStatus == 2 " style="color: #1ab394;font-size: 14px;margin-left: 5px">[已归档]</span>
              </div>
            </div>
          </div>
@@ -52,6 +62,9 @@
    id: '',
  },
  activities: [],
  creatContent: '',
  firstPeopleContent: '',
  firstPeopleState: null,
  formRules:{
    name: [{ required: true, trigger: "blur", message:'' }],
  },
@@ -59,40 +72,52 @@
const openDialog = async (value) => {
  state.activities = [
    {
      content: '创建人:张三(综合办)',
      timestamp: '2018-04-03 20:46',
      size: 'large',
      state: 1,
    },
    {
      content: '最初签署人:李四',
      timestamp: '2018-04-03 20:46',
      size: 'large',
      state: 1,
    },
    {
      title: '由  XXX 部门 XX 流转',
      content: 'XXXX',
      timestamp: '2018-04-03 20:46',
      size: 'large',
      state: 1,
    },
    {
      title: '由  XXX 部门 XX 流转',
      content: 'XXXX',
      timestamp: '2018-04-03 20:46',
      size: 'large',
      state: 1,
    },
  console.log('va',value)
  state.form = JSON.parse(JSON.stringify(value))
  state.activities = JSON.parse(JSON.stringify(value)).signatureFlows
  const newArr = []
  state.activities.forEach(item => {
    if(item.sort == 1){
      state.creatContent = item.userName + '('+ item.deptName + ')'
      state.firstPeopleContent =  item.signUserName + '('+ item.signDeptName + ')'
      state.firstPeopleState = item.signStatus
    }else {
      newArr.push(item)
    }
  })
  newArr.sort((a,b) => a.sort - b.sort)
  state.activities = newArr
  ]
  // state.activities = [
    // {
    //   content: '创建人:张三(综合办)',
    //   timestamp: '2018-04-03 20:46',
    //   size: 'large',
    //   state: 1,
    // },
    // {
    //   content: '最初签署人:李四',
    //   timestamp: '2018-04-03 20:46',
    //   size: 'large',
    //   state: 1,
    // },
    // {
    //   title: '由  XXX 部门 XX 流转',
    //   content: 'XXXX',
    //   timestamp: '2018-04-03 20:46',
    //   size: 'large',
    //   state: 1,
    // },
    // {
    //   title: '由  XXX 部门 XX 流转',
    //   content: 'XXXX',
    //   timestamp: '2018-04-03 20:46',
    //   size: 'large',
    //   state: 1,
    // },
  // ]
  dialogVisible.value = true;
}
const handleClose = () => {
  reset();
src/views/signProject/components/viewPdf.vue
对比新文件
@@ -0,0 +1,66 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        title="流转记录"
        width="500px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <iframe :src="state.pdfUrl" width="100%" height="600px" sandbox="allow-scripts"></iframe>
    </el-dialog>
  </div>
</template>
<script setup>
import {reactive, ref, toRefs} from 'vue'
const dialogVisible = ref(false);
const title = ref("");
const emit = defineEmits(["getList"]);
const state = reactive({
  pdfUrl: ''
})
const openDialog = async (value) => {
  state.pdfUrl =  import.meta.env.VITE_APP_BASE_API  +value.itemFile
  console.log('11',state.pdfUrl)
  dialogVisible.value = true;
}
const handleClose = () => {
  reset();
  dialogVisible.value = false;
  emit("getList")
}
const reset = () => {
state.pdfUrl = ''
}
defineExpose({
  openDialog
});
</script>
<style scoped lang="scss">
.notice{
  /* 针对 iframe 的滚动条 */
  iframe::-webkit-scrollbar {
    width: 12px; /* 滚动条宽度 */
  }
  iframe::-webkit-scrollbar-track {
    background: #f1f1f1; /* 滚动条轨道背景 */
    border-radius: 10px;
  }
  iframe::-webkit-scrollbar-thumb {
    background: #888; /* 滚动条滑块颜色 */
    border-radius: 10px;
  }
  iframe::-webkit-scrollbar-thumb:hover {
    background: #555; /* 鼠标悬停时滑块颜色 */
  }
}
</style>
src/views/signProject/index.vue
@@ -2,9 +2,9 @@
  <div class="app-container">
    <div style="display: flex;justify-content: space-between;margin-bottom: 20px">
      <el-form :inline="true" style="display: flex;align-items: center;flex-wrap: wrap;" >
        <el-radio-group v-model="queryParams.type">
        <el-radio-group v-model="queryParams.status" @change="getList">
          <el-radio-button label="" >全部</el-radio-button>
          <el-radio-button label="1">签署中</el-radio-button>
          <el-radio-button label="0">签署中</el-radio-button>
          <el-radio-button label="2" >已归档</el-radio-button>
        </el-radio-group>
<!--        <el-form-item label="仓库名称:" >-->
@@ -26,22 +26,26 @@
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true">
      <el-table-column label="序号" type="index" align="center" width="80" />
      <el-table-column label="项目名称" prop="name" align="center"  />
      <el-table-column label="模板ID" prop="remark" align="center" />
      <el-table-column label="发起部门" prop="remark" align="center" />
      <el-table-column label="发起时间" prop="remark" align="center" />
      <el-table-column label="最初签署人" prop="remark" align="center" />
      <el-table-column label="项目名称" prop="itemName" align="center"  />
      <el-table-column label="模板ID" prop="templateId" align="center" />
      <el-table-column label="发起部门" prop="deptName" align="center" />
      <el-table-column label="发起时间" prop="originateTime" align="center" />
      <el-table-column label="最初签署人" prop="initiaiUserName" align="center" />
      <el-table-column label="流转记录" prop="count" align="center" >
        <template #default="scope">
          <span style="color: #1890ff;cursor: pointer" @click="record(scope.row)">{{scope.row.count}}</span>
          <span style="color: #1890ff;cursor: pointer" @click="record(scope.row)">{{scope.row.flowCount}}</span>
        </template>
      </el-table-column>
      <el-table-column label="签署状态" prop="remark" align="center" />
      <el-table-column label="签署状态" prop="itemStatus" align="center" >
        <template #default="scope">
          <span>{{scope.row.itemStatus == 0 ? '签署中' : scope.row.itemStatus == 1 ? '已签署' :scope.row.itemStatus == 2 ? '已归档' : ''  }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="250" >
        <template #default="scope">
          <el-button link type="primary" >预览</el-button>
          <el-button link type="primary" @click="circulationBtn(scope.row)" >流转</el-button>
          <el-button link type="primary" >确认归档</el-button>
          <el-button link type="primary" @click="view(scope.row)">预览</el-button>
          <el-button link type="primary" v-if="scope.row.itemStatus !=2 && (data.userRole.includes('admin') || data.userRole.includes('suprice') ) " @click="circulationBtn(scope.row)" >流转</el-button>
          <el-button link type="primary" v-if="scope.row.itemStatus !=2 &&(data.userRole.includes('admin') || data.userRole.includes('suprice')) && scope.row.isAbleArchive " @click="archiveBtn(scope.row)">确认归档</el-button>
          <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
@@ -55,6 +59,7 @@
    />
    <circulation ref="circulationRef" @getList="getList"></circulation>
    <timeRecord ref="timeRecordRef" @getList="getList"></timeRecord>
<!--    <view-p ref="viewPRef" @getList="getList"></view-p>-->
  </div>
</template>
@@ -63,18 +68,23 @@
import {ElMessage, ElMessageBox} from "element-plus";
import circulation from './components/circulation'
import timeRecord from './components/record.vue'
import viewP from './components/viewPdf.vue'
import {delSignProject, getSignProject, signArchive} from "@/api/signAgreement/signProject";
import Cookies from "js-cookie";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const dialogRef = ref();
const circulationRef = ref();
const cupDialogRef = ref();
const viewPRef = ref();
const timeRecordRef = ref()
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    type: ''
    status: ''
  },
  userRole:[],
  user: {},
  total: 0,
  dataList: []
});
@@ -83,6 +93,8 @@
const classHourRef = ref();
onMounted(()=>{
  getList()
  data.userRole = JSON.parse(Cookies.get('userRole'))
  data.user = JSON.parse(Cookies.get('userInfo'))
})
onUnmounted(()=>{
@@ -91,20 +103,28 @@
const getList = async () => {
  loading.value = true
  // const res = await getWarehouse(data.queryParams)
  // if(res.code == 200){
  //   data.dataList = res.data.list
  //   data.total = res.data.total
  // }else{
  //   ElMessage.warning(res.message)
  // }
  data.dataList = [
    {
      id: 1,
      name: 'xxx',
      count: 2
    }
  ]
  const res = await getSignProject(data.queryParams)
  if(res.code == 200){
    data.dataList = res.rows.map(item => {
      return {
        ...item,
        flowCount: item.signatureFlows && item.signatureFlows.length >0 ? item.signatureFlows.length : 0
      }
    })
    data.dataList.forEach(item => {
      let isAble = true
      item.signatureFlows.forEach(i => {
        if(i.signStatus !=1){
          isAble = false
        }
      })
      item.isAbleArchive = isAble
    })
    console.log('1',data.dataList)
    data.total = res.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false
}
@@ -112,18 +132,53 @@
  dialogRef.value.openDialog(type, value);
}
const record = (val) => {
  timeRecordRef.value.openDialog(val)
  if(val.flowCount > 0){
    timeRecordRef.value.openDialog(val)
  }else {
    ElMessage.warning('暂无流转记录')
  }
}
const circulationBtn = (value) => {
  circulationRef.value.openDialog(value)
}
const view = (val) => {
  const url =import.meta.env.VITE_APP_BASE_API  +val.itemFile
  window.open(url)
}
const archiveBtn = (val) => {
  ElMessageBox.confirm(
      '确定项目归档?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        console.log('1111',val)
        const param = {
          itemId: val.id,
          filePath: val.itemFile,
          userId: data.user.userId
        }
        const res = await signArchive(param)
        if(res.code == 200){
          ElMessage.success('项目归档成功')
          await getList()
        }else{
          ElMessage.warning(res.message)
        }
      })
}
/** 重置新增的表单以及其他数据  */
function reset() {
  data.queryParams = {
    pageNum: 1,
    pageSize: 10,
    name: ''
    status: ''
  }
  getList()
}
@@ -137,7 +192,7 @@
        type: 'warning',
      })
      .then( async() => {
        const res = await delWarehouse(val.id)
        const res = await delSignProject(val.id)
        if(res.code == 200){
          ElMessage.success('数据删除成功')
          await getList()
@@ -145,31 +200,7 @@
          ElMessage.warning(res.message)
        }
      })
}
const delCup = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delCupboard(val.id)
        if(res.code == 200){
          ElMessage.success('数据删除成功')
          await getList()
        }else{
          ElMessage.warning(res.message)
        }
      })
}
const addCupboard = (type,value) => {
  cupDialogRef.value.openDialog(type, value);
}
const getRowKeys = (row) => {
  return row.name
}
</script>
src/views/signTypeManage/components/addDialog.vue
@@ -9,8 +9,8 @@
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
        <el-form-item label="类别名称:" prop="name" >
          <el-input v-model.trim="state.form.name" placeholder="请输入类别名称"></el-input>
        <el-form-item label="类别名称:" prop="typeName" >
          <el-input v-model.trim="state.form.typeName" placeholder="请输入类别名称"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
@@ -25,6 +25,7 @@
<script setup>
import {reactive, ref, toRefs} from 'vue'
import {ElMessage} from "element-plus";
import {addType, editType} from "@/api/signAgreement/signType";
const dialogVisible = ref(false);
const title = ref("");
const busRef = ref();
@@ -35,12 +36,10 @@
const state = reactive({
  form: {
    id: '',
    name: '',
    remark: ''
    typeName: '',
  },
  formRules:{
    name: [{ required: true, trigger: "blur", message: '请输入类别名称' }],
    typeName: [{ required: true, trigger: "blur", message: '请输入类别名称' }],
  },
})
@@ -59,7 +58,7 @@
  if(valid){
    if(title.value === '新增'){
      const {id, ...data} = JSON.parse(JSON.stringify(state.form))
      const res = await addWarehouse(data)
      const res = await addType(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
@@ -74,7 +73,7 @@
      dialogVisible.value = false;
    }else if(title.value === '编辑'){
      const {...data} = JSON.parse(JSON.stringify(state.form))
      const res = await editWarehouse(data)
      const res = await editType(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
@@ -100,8 +99,7 @@
const reset = () => {
  state.form = {
    id: '',
    name: '',
    remark: '',
    typeName: '',
  }
}
defineExpose({
src/views/signTypeManage/index.vue
@@ -10,26 +10,26 @@
              @click="openDialog('add',{})"
          >新增</el-button>
        </el-form-item>
<!--        <el-form-item label="仓库名称:" >-->
<!--          <el-input v-model="data.queryParams.name" placeholder="请输仓库名称"></el-input>-->
<!--        </el-form-item>-->
<!--        <el-form-item >-->
<!--          <el-button-->
<!--              type="primary"-->
<!--              @click="getList"-->
<!--          >查询</el-button>-->
<!--          <el-button-->
<!--              type="primary"-->
<!--              plain-->
<!--              @click="reset"-->
<!--          >重置</el-button>-->
<!--        </el-form-item>-->
        <el-form-item label="名称:" >
          <el-input v-model="data.queryParams.typeName" placeholder="请输入类别名称"></el-input>
        </el-form-item>
        <el-form-item >
          <el-button
              type="primary"
              @click="getList"
          >查询</el-button>
          <el-button
              type="primary"
              plain
              @click="reset"
          >重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true">
      <el-table-column label="序号" type="index" align="center" width="80" />
      <el-table-column label="类别名称" prop="name" align="center"  />
      <el-table-column label="类别名称" prop="typeName" align="center"  />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200" >
        <template #default="scope">
          <el-button link type="primary" @click="openDialog('edit',scope.row)">编辑</el-button>
@@ -38,13 +38,13 @@
      </el-table-column>
    </el-table>
    <pagination
        v-show="total > 0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
    />
<!--    <pagination-->
<!--        v-show="total > 0"-->
<!--        :total="total"-->
<!--        v-model:page="queryParams.pageNum"-->
<!--        v-model:limit="queryParams.pageSize"-->
<!--        @pagination="getList"-->
<!--    />-->
    <add-dialog ref="dialogRef" @getList="getList"></add-dialog>
  </div>
@@ -54,15 +54,14 @@
import {getCurrentInstance, onMounted, onUnmounted, reactive, ref, toRefs} from "vue";
import {ElMessage, ElMessageBox} from "element-plus";
import addDialog from './components/addDialog.vue'
import {delType, getSignType} from "@/api/signAgreement/signType";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const dialogRef = ref();
const cupDialogRef = ref();
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    name: ''
    typeName: ''
  },
  total: 0,
  dataList: []
@@ -79,15 +78,15 @@
})
const getList = async () => {
  // loading.value = true
  // const res = await getWarehouse(data.queryParams)
  // if(res.code == 200){
  //   data.dataList = res.data.list
  //   data.total = res.data.total
  // }else{
  //   ElMessage.warning(res.message)
  // }
  // loading.value = false
  loading.value = true
  const res = await getSignType(data.queryParams)
  if(res.code == 200){
    data.dataList = res.data
    // data.total = res.data.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false
}
const openDialog = (type, value) => {
@@ -97,9 +96,7 @@
/** 重置新增的表单以及其他数据  */
function reset() {
  data.queryParams = {
    pageNum: 1,
    pageSize: 10,
    name: ''
    typeName: ''
  }
  getList()
}
@@ -113,7 +110,7 @@
        type: 'warning',
      })
      .then( async() => {
        const res = await delWarehouse(val.id)
        const res = await delType(val.id)
        if(res.code == 200){
          ElMessage.success('数据删除成功')
          await getList()
src/views/templateManage/components/createSign.vue
@@ -3,19 +3,22 @@
    <el-dialog
        v-model="dialogVisible"
        title="创建签署项目"
        width="50%"
        width="550px"
        :before-close="handleClose"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
    >
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
        <el-form-item label="项目名称:" prop="name" >
          <el-input v-model="state.form.name" placeholder="请输入项目名称"></el-input>
        <el-form-item label="项目名称:" prop="itemName" >
          <el-input v-model="state.form.itemName" placeholder="请输入项目名称"></el-input>
        </el-form-item>
        <div style="display: flex;align-items: center;">
        <el-form-item label="最初签署人:" prop="deptId" >
          <div style="display: flex;">
            <el-cascader
                style="width: 50%"
                :show-all-levels="false"
                style="width: 170px"
                clearable
                placeholder="请选择部门"
                v-model="state.form.deptId"
@@ -23,18 +26,16 @@
                @change="selectValue"
                :props="{ expandTrigger: 'hover', value: 'deptId',label: 'deptName',emitPath: false}">
            </el-cascader>
            <el-select
                clearable
                v-model="state.form.people"
                v-model="state.form.initiaiUserId"
                filterable
                multiple
                remote
                reserve-keyword
                placeholder="请输入签署人名称(可多选)"
                placeholder="请输入签署人名称"
                remote-show-suffix
                :remote-method="(val)=>getUserList(val,state.form.deptId)"
                style="width: 50%;margin-left: 10px"
                style=" width:170px;margin-left:20px"
            >
              <el-option
                  v-for="item in state.userList"
@@ -43,9 +44,8 @@
                  :value="item.userId"
              />
            </el-select>
          </div>
        </el-form-item>
        </div>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
@@ -61,6 +61,7 @@
import {ElMessage} from "element-plus";
import {listDept} from "@/api/system/dept";
import {listUser} from "@/api/system/user";
import {addSignProject} from "@/api/signAgreement/signProject";
const { proxy } = getCurrentInstance();
const dialogVisible = ref(false);
@@ -72,25 +73,28 @@
const state = reactive({
  form: {
    id: '',
    deptId: '',
    people: []
    itemName: '',
    deptId: null,
    initiaiUserId: null,
    templateId: null
  },
  options: [],
  userList: [],
  formRules:{
    deptId: [{ required: true, trigger: "blur", message:'请选择部门' }],
    people: [{ required: true, trigger: "blur", message:'请选择签署人' }],
    itemName: [{ required: true, trigger: "blur", message:'请输入项目名称' }],
  },
})
const openDialog = async (value) => {
  await getDept()
  state.form.templateId = value.id
  dialogVisible.value = true;
}
const selectValue = (val) => {
  state.userList = []
  state.form.people = []
  state.form.initiaiUserId = null
  getUserList("",val)
}
@@ -107,15 +111,19 @@
  const valid = await busRef.value.validate();
  if(valid){
    const {id, ...data} = JSON.parse(JSON.stringify(state.form))
    // const res = await addWarehouse(data)
    // if(res.code === 200){
    //   ElMessage({
    //     type: 'success',
    //     message: '新增成功'
    //   });
    // }else{
    //   ElMessage.warning(res.message)
    // }
    if(data.initiaiUserId == null) {
      ElMessage.warning('请选择签署人')
      return;
    }
    const res = await addSignProject(data)
    if(res.code === 200){
      ElMessage({
        type: 'success',
        message: '新增成功'
      });
    }else{
      ElMessage.warning(res.message)
    }
    emit("getList")
    busRef.value.clearValidate();
    reset();
@@ -133,8 +141,10 @@
const reset = () => {
  state.form = {
    id: '',
    name: '',
    remark: '',
    itemName: '',
    deptId: null,
    initiaiUserId: null,
    templateId: null
  }
}
const getUserList = async (val,deptId)=>{
src/views/templateManage/components/templateDialog.vue
@@ -11,53 +11,54 @@
      <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="模板名称:" prop="name" >
              <el-input v-model="state.form.name" placeholder="请输入模板名称"></el-input>
            <el-form-item label="模板名称:" prop="templateName" >
              <el-input v-model="state.form.templateName" placeholder="请输入模板名称"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="创建部门:"  >
              <span style="font-size: 16px">{{state.form.deptName}}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="签署类型:"  >
              <el-select
                  v-model="state.form.type"
                  placeholder="请选择"
                  style="width: 100%"
              >
        <div style="display: flex;align-items: center;justify-content: space-between">
          <el-form-item label="创建部门:"  >
            <span style="font-size: 16px">{{state.deptName}}</span>
          </el-form-item>
          <el-form-item label="签署类型:"  prop="typeId">
            <el-select
                v-model="state.form.typeId"
                placeholder="请选择"
                style="width: 100%"
            >
              <el-option
                  v-for="item in state.typeList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                  :key="item.id"
                  :label="item.typeName"
                  :value="item.id"
              />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
            </el-select>
          </el-form-item>
        </div>
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="签名文件附件:" prop="name" >
            <el-form-item label="签名文件附件:" prop="fileList" >
              <el-upload
                  :auto-upload="false"
                  v-model:file-list="state.form.fileList"
                  :action="uploadFileUrl"
                  :file-list="state.fileList"
                  :headers="state.header"
                  :remove="handleRemove"
                  :on-success="handleAvatarSuccess"
                  :on-change="handleChange"
                  accept=".pdf,.word"
                  :limit="state.limit"
                  style="width: 230px"
              >
                <el-button type="primary" plain> 点击上传 </el-button>
                <template #tip>
                  <div class="el-upload__tip">只能上传pdf类型,最多上传1份。</div>
                </template>
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="签名文件附件:" style="display: flex;flex-direction: column;align-items: flex-start">
        <el-form-item label="签署效果预览:" style="display: flex;flex-direction: column;align-items: flex-start">
          <div style="width: 500px;height: 100px;margin-left: 50px">
          </div>
@@ -77,6 +78,10 @@
import {ElMessage} from "element-plus";
import {listDept} from "@/api/system/dept";
import {listUser} from "@/api/system/user";
import {addTemplate, editTemplate} from "@/api/signAgreement/template";
import {addType, editType, getSignType} from "@/api/signAgreement/signType";
import {getInfo} from "@/api/login";
import {getToken} from "@/utils/auth";
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传文件服务器地址
const { proxy } = getCurrentInstance();
@@ -89,50 +94,99 @@
const state = reactive({
  form: {
    id: '',
    deptId: '',
    deptName: '综合办',
    people: []
    templateName: '',
    typeId:null,
    deptId: null,
    filePath: '',
    fileList: []
  },
  typeList: [
    {
      value: '1',
      label: 'xx'
    }
  ],
  fileList: [],
  header: {
    Authorization: getToken()
  },
  deptName: '',
  typeList: [],
  limit: 1,
  formRules:{
    deptId: [{ required: true, trigger: "blur", message:'请选择部门' }],
    people: [{ required: true, trigger: "blur", message:'请选择签署人' }],
    templateName: [{ required: true, trigger: "blur", message:'请输入模板名称' }],
    typeId: [{ required: true, trigger: "blur", message:'请选择签署类型' }],
    fileList: [{ required: true, trigger: "blur", message:'请上传签名文件' }],
  },
})
const openDialog = async (type,value) => {
  await getSignTypeList()
  await getUserInfo()
  title.value = type === 'add' ? '新增' : '编辑'
  if(type === 'edit') {
    state.form = JSON.parse(JSON.stringify(value))
    if(state.form.filePath && state.form.fileName){
      const obj = {
        name: state.form.fileName,
        url : import.meta.env.VITE_APP_BASE_API + state.form.filePath
      }
      state.form.fileList = [obj]
    }else {
      state.form.fileList = []
    }
  }
  dialogVisible.value = true;
}
const getSignTypeList = async () => {
  const res = await getSignType()
  if(res.code == 200){
    state.typeList = res.data
  }else{
    ElMessage.warning(res.message)
  }
}
const getUserInfo = async () => {
  const res = await getInfo()
  if(res.code == 200){
    state.deptName = res.user.dept.deptName
    state.form.deptId = res.user.deptId
  }else{
    ElMessage.warning(res.message)
  }
}
const onSubmit = async () => {
  console.log('form',state.form)
  const valid = await busRef.value.validate();
  if(valid){
    const {id, ...data} = JSON.parse(JSON.stringify(state.form))
    // const res = await addWarehouse(data)
    // if(res.code === 200){
    //   ElMessage({
    //     type: 'success',
    //     message: '新增成功'
    //   });
    // }else{
    //   ElMessage.warning(res.message)
    // }
    emit("getList")
    busRef.value.clearValidate();
    reset();
    dialogVisible.value = false;
    if(title.value === '新增'){
      const {id,fileList, ...data} = JSON.parse(JSON.stringify(state.form))
      const res = await addTemplate(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '新增成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }else if(title.value === '编辑'){
      const {...data} = JSON.parse(JSON.stringify(state.form))
      const res = await editTemplate(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '编辑成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      busRef.value.clearValidate();
      reset();
      dialogVisible.value = false;
    }
  }
}
@@ -146,28 +200,45 @@
const reset = () => {
  state.form = {
    id: '',
    name: '',
    remark: '',
    templateName: '',
    typeId:null,
    deptId: null,
    filePath: '',
    fileList: []
  }
}
const handleRemove = (file) => {
  const index = data.fileList.indexOf(file)
  const newFileList = data.fileList.slice()
  const index = state.form.fileList.indexOf(file)
  const newFileList = state.form.fileList.slice()
  newFileList.splice(index, 1)
  data.fileList = newFileList;
  state.form.fileList = newFileList;
}
const f = ref()
const handleChange = (file,fileList) => {
  console.log('file',file)
  let fileExtension = file.name.split('.').pop();
  if(fileExtension == 'pdf' || fileExtension == 'word'){
    f.value = file.raw
  }else {
    data.fileList = []
    state.form.fileList = []
    ElMessage.warning('仅可上传pdf或word文件')
  }
}
const handleAvatarSuccess = (res) => {
  if(res.code === 200){
    // ElMessage({
    //   type: 'success',
    //   message: '文件上传成功'
    // })
    state.form.filePath = res.fileName
  }else {
    state.form.fileList = []
    ElMessage({
      type: 'warning',
      message: res.message
    })
  }
}
defineExpose({
  openDialog
});
src/views/templateManage/index.vue
@@ -2,35 +2,37 @@
  <div class="app-container">
    <div style="display: flex;justify-content: space-between;margin-bottom: 20px">
      <el-form :inline="true" style="display: flex;align-items: center;flex-wrap: wrap;" >
        <el-button
          type="primary"
          @click="addProject('add',{})"
        >
          新增模板
        </el-button>
        <!--        <el-form-item label="仓库名称:" >-->
        <!--          <el-input v-model="data.queryParams.name" placeholder="请输仓库名称"></el-input>-->
        <!--        </el-form-item>-->
        <!--        <el-form-item >-->
        <!--          <el-button-->
        <!--              type="primary"-->
        <!--              @click="getList"-->
        <!--          >查询</el-button>-->
        <!--          <el-button-->
        <!--              type="primary"-->
        <!--              plain-->
        <!--              @click="reset"-->
        <!--          >重置</el-button>-->
        <!--        </el-form-item>-->
        <el-form-item>
          <el-button
              type="primary"
              @click="addProject('add',{})"
          >
            新增模板
          </el-button>
        </el-form-item>
        <el-form-item label="模板名称:" >
          <el-input v-model="data.queryParams.templateName" placeholder="请输入模板名称"></el-input>
        </el-form-item>
        <el-form-item >
          <el-button
              type="primary"
              @click="getList"
          >查询</el-button>
          <el-button
              type="primary"
              plain
              @click="reset"
          >重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true">
      <el-table-column label="序号" type="index" align="center" width="80" />
      <el-table-column label="模板ID" prop="remark" align="center" />
      <el-table-column label="模板名称" prop="name" align="center"  />
      <el-table-column label="类型" prop="remark" align="center" />
      <el-table-column label="提交部门" prop="remark" align="center" />
      <el-table-column label="模板ID" prop="id" align="center" />
      <el-table-column label="模板名称" prop="templateName" align="center"  />
      <el-table-column label="类型" prop="typeName" align="center" />
      <el-table-column label="提交部门" prop="deptName" align="center" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="250" >
        <template #default="scope">
          <el-button link type="primary" @click="createS(scope.row)">创建签署项目</el-button>
@@ -56,15 +58,14 @@
import {ElMessage, ElMessageBox} from "element-plus";
import templateDialog from './components/templateDialog.vue'
import createSignDialog from './components/createSign.vue'
import {delTemplate, getTemplate} from "@/api/signAgreement/template";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const dialogRef = ref();
const createSignRef = ref();
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    type: ''
    templateName: ''
  },
  total: 0,
  dataList: []
@@ -88,33 +89,20 @@
}
const getList = async () => {
  loading.value = true
  // const res = await getWarehouse(data.queryParams)
  // if(res.code == 200){
  //   data.dataList = res.data.list
  //   data.total = res.data.total
  // }else{
  //   ElMessage.warning(res.message)
  // }
  data.dataList = [
    {
      id: 1,
      name: 'xxx',
      count: 2
    }
  ]
  const res = await getTemplate(data.queryParams)
  if(res.code == 200){
    data.dataList = res.data
    // data.total = res.data.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false
}
const openDialog = (type, value) => {
  dialogRef.value.openDialog(type, value);
}
const record = (val) => {
  timeRecordRef.value.openDialog(val)
}
const circulationBtn = (value) => {
  circulationRef.value.openDialog(value)
}
/** 重置新增的表单以及其他数据  */
function reset() {
  data.queryParams = {
@@ -134,7 +122,7 @@
        type: 'warning',
      })
      .then( async() => {
        const res = await delWarehouse(val.id)
        const res = await delTemplate(val.id)
        if(res.code == 200){
          ElMessage.success('数据删除成功')
          await getList()
@@ -143,28 +131,8 @@
        }
      })
}
const delCup = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delCupboard(val.id)
        if(res.code == 200){
          ElMessage.success('数据删除成功')
          await getList()
        }else{
          ElMessage.warning(res.message)
        }
      })
}
const addCupboard = (type,value) => {
  cupDialogRef.value.openDialog(type, value);
}
const getRowKeys = (row) => {
  return row.name