jiangping
2024-05-29 261f60837f9224fa1afdaf819cb33b85ff9f4d77
最新版本
已添加1个文件
已修改9个文件
583 ■■■■■ 文件已修改
admin/src/api/business/member.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaCarUseBookWindow.vue 510 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaHiddenDangerWindow.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/utils/request.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/operation/serviceCar/apprRecord.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/MemberCloudController.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/ApproveParam.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/CarUseBook.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/MemberService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/member.js
@@ -10,13 +10,15 @@
  })
}
export function allList (data) {
  // return request.post('/business/member/page', data, {
  //   trim: true
  // })
  return request.post('/visitsAdmin/cloudService/business/member/list', data, {
    trim: true
  })
}
export function driveList (data) {
  return request.post('/visitsAdmin/cloudService/business/member/driveList', data, {
    trim: true
  })
}
// éƒ¨é—¨ä¿¡æ¯åŒæ­¥
export function memberSync (data) {
  return request.post('/visitsAdmin/cloudService/business/member/syncAll', data)
admin/src/components/business/OperaCarUseBookWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,510 @@
<template>
  <GlobalWindow
      :title="title"
      :visible.sync="visible"
      @confirm="confirm"
      @close="reject"
  >
    <div class="modal_wrap">
      <div class="modal_content">
        <div class="header">
          <div class="left">
            <div class="h1">公务车申请</div>
            <div class="time">提交时间:{{model.createDate}}</div>
          </div>
          <span class="right"  v-if="model.status === 0">申请中</span>
          <span class="right"  v-if="model.status === 1">待审批</span>
          <span class="right" style="background:#53b76f " v-if="model.status === 2">审批通过</span>
          <span class="right" style="background:#dc362e " v-if="model.status === 3">审批不通过</span>
          <span class="right" style="background:#dc362e " v-if="model.status === 4">已取消</span>
        </div>
        <div class="info">
          <div class="title">公务车申请信息</div>
          <div class="list">
            <div class="item">
              <div class="label">申请人</div>
              <div class="value">{{model.memberName || ''}} {{model.memberPhone || ''}} ({{model.companyName || ''}})</div>
            </div>
            <div class="item">
              <div class="label">申请车辆</div>
              <div class="value">{{model.carCode || ''}}</div>
            </div>
            <div class="item">
              <div class="label">司机信息</div>
              <div class="value" v-if="model.driverId !=null">{{model.driverName || ''}} {{model.driverPhone || ''}}</div>
              <div class="value" v-if="model.driverId ==null">未指派</div>
            </div>
            <div class="item"  >
            <div class="label">用车事由</div>
            <div class="value">{{model.content}}</div>
          </div>
            <div class="item">
              <div class="label">乘车人员</div>
              <div class="value">{{model.memberNames || ''}}</div>
            </div>
            <div class="item">
              <div class="label">目的地类别</div>
              <div class="value status-green" v-if="model.type === 0">【市内用车】</div>
              <spdivan class="value status-red"   v-if="model.type === 1">【市内用车】</spdivan>
            </div>
            <div class="item">
              <div class="label">目的地</div>
              <div class="value">{{model.addr || ''}}</div>
            </div>
            <div class="item">
              <div class="label">预计出发时间</div>
              <div class="value">{{model.planUseDate || ''}}</div>
            </div>
            <div class="item">
              <div class="label">用车时段</div>
              <div class="value">{{model.startTime || ''}}-{{model.endTime || ''}}</div>
            </div>
          </div>
        </div>
      </div>
      <div class="side">
        <div class="side_title">审批流程</div>
        <div class="list">
          <div class="item" v-for="(item,index) in logList" :key="item.id">
            <div class="separate" v-if="index < logList.length-1"></div>
            <div class="info">
              <i class="el-icon-success icon" v-if="(model.status ==1) || index < logList.length-1"></i>
              <i class="el-icon-question icon1" v-if="(model.status==0)  && index == logList.length-1"></i>
              <i class="el-icon-error icon2" v-if="(model.status==2)  && index == logList.length-1"></i>
              <img v-if="item.avatar!=null && item.avatar !=''" :src="item.avatar" class="avatar" alt="" />
              <img v-if="item.avatar ==null ||item.avatar ==''"  src="@/assets/avatar/man.png" class="avatar" alt="" />
              <div class="content">
                <div class="line">
                  <div class="name">{{ item.title}}</div>
                  <div class="time">{{ item.createDate }}</div>
                </div>
                <div class="line">
                  <div class="company">
                    {{ item.createUserName }} {{ item.companyName }}
                    <div style="display: inline">
                      ï¼ˆ<span class="status-green">{{stausInfo}}</span>
                    </div>
                  </div>
                </div>
                <div class="line">
                  <div class="remark">
                    {{ item.checkInfo ||'' }}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!--  -->
    <template   v-slot:footer>
      <el-button @click="isShowProblem = true"  type="primary"  v-if="model.approveDateVO!=null&& model.approveDateVO.canBeApproved!=null &&model.approveDateVO.canBeApproved ==1 "  class="status-red">同意</el-button>
      <el-button @click="isBackProblem=true"  type="danger"  v-if="model.approveDateVO!=null&& model.approveDateVO.canBeApproved!=null &&model.approveDateVO.canBeApproved ==1 "  >拒绝</el-button>
      <el-button @click="visible=false">返回</el-button>
    </template>
    <el-dialog
        append-to-body
        title="转交"
        class="dialogCl"
        :visible.sync="isShowTransfer"
        width="480px"
    >
      <el-form :model="dealForm" ref="dealForm" >
        <el-form-item label="派车司机" prop="driverId" required v-if="model.approveDateVO!=null && model.approveDateVO.drvierParam ===1">
          <el-select v-model="transForm.driverId" style="width: 300px"  filterable clearable placeholder="请选择派遣司机">
            <el-option
                v-for="item in memberList"
                :key="item.id"
                :label="item.name+'-'+item.phone"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="同意说明">
          <el-input
              type="textarea"
              placeholder="请填写说明"
              :rows="4"
              v-model="backForm.checkInfo"
          />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="isShowProblem = false">取消</el-button>
        <el-button type="primary" :loading="transfering" @click="dealDo">确定</el-button>
      </span>
    </el-dialog>
    <el-dialog
        append-to-body
        title="拒绝申请"
        class="dialogCl"
        :visible.sync="isBackProblem"
        width="600px"
    >
      <el-form :model="backForm"  ref="backForm" label-width="100px">
        <el-form-item label="拒绝说明">
          <el-input
              type="textarea"
              placeholder="请填写说明"
              :rows="4"
              v-model="backForm.checkInfo"
          />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="isBackProblem= false">取消</el-button>
        <el-button type="primary" :loading="transfering" @click="backDo">确定</el-button>
      </span>
    </el-dialog>
  </GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
import { driveList } from '@/api/business/member'
import { mapState } from 'vuex'
export default {
  name:'OperaCarUseBookWindow.vue',
  components: { GlobalWindow },
  extends: BaseOpera,
  data () {
    return {
      title: '公务车申请',
      visible: false,
      dataId: null,
      model: { },
      dealing: false,
      isShowProblem: false,
      isBackProblem: false,
      memberList: [],
      logList:[],
      copyList:[],
      dealForm: {
        driveId: null,
        checkInfo: null
      },
      backForm: {
        checkInfo: null
      }
    }
  },
  computed: {
    ...mapState(['userInfo'])
  },
  created () {
    this.config({
      api: '/business/carUserBook',
      'field.id': 'id'
    })
  },
  methods: {
    dealDo () {
      this.$refs.dealForm.validate((valid) => {
        if (!valid) {
          return
        }
        this.$dialog.actionConfirm('操作确认', '您确认提交该隐患处理情况吗?')
          .then(() => {
            this.dealing = true
            this.api.dealHiddenDanger({
              id: this.dataId,
              status: 1,
              driverId: this.dealForm.driveId,
              checkInfo: this.dealForm.checkInfo
            })
              .then(res => {
                this.$tip.apiSuccess('处理成功')
                this.getDetail()
                this.isShowProblem = false
              })
              .finally(() => {
                this.dealing = false
              })
          })
      })
    },
    backDo () {
      this.$refs.backForm.validate((valid) => {
        if (!valid) {
          return
        }
        this.$dialog.actionConfirm('操作确认', '您确认退回该隐患处理情况吗?')
          .then(() => {
            this.dealing = true
            this.api.dealHiddenDanger({
              id: this.dataId,
              status: 2,
              checkInfo: this.backForm.checkInfo
            })
              .then(res => {
                this.$tip.apiSuccess('退回成功')
                this.getDetail()
                this.isBackProblem = false
              })
              .catch(e => {
              })
              .finally(() => {
                this.dealing = false
              })
          })
      })
    },
    open (title, target) {
      this.title = title
      this.visible = true
      this.model = {}
      this.dataId = target.id
      this.$nextTick(() => {
        this.memberList = []
        this.logList = []
        this.copyList = []
        this.dealForm = {
          driveId: null,
          checkInfo: null
        }
        this.backForm = {
          checkInfo: null
        }
        this.getDetail()
      })
    },
    getDetail () {
      this.api.detail(this.dataId)
        .then(res => {
          this.model = res
          this.dealForm.driveId = res.driveId
          if(res.approveDateVO){
            if(res.approveDateVO.approveList){
              this.logList = res.approveDateVO.approveList
            }
            if(res.approveDateVO.copyList){
              this.copyList = res.approveDateVO.copyList
            }
          }
        })
    },
    handleTransfer () {
      this.isShowTransfer = true
      this.loadMemberList()
    },
    loadMemberList () {
      driveList({}).then(res => {
        this.memberList = res
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.side_title{
  font-weight: 600;
  font-size: 18px;
  color: #111111;
  margin-bottom: 20px;
  margin-left: 20px;
  margin-top: 20px;
}
.upload_box {
  width: 84px;
  height: 84px;
  border-radius: 4px;
  background-color: #f7f7f7;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #999999;
  border: 1px solid #e4e4e4;
  .icon {
    font-size: 24px;
  }
  .text {
    font-size: 12px;
  }
}
.modal_wrap {
  display: flex;
  height: 100%;
  .modal_content {
    flex: 1;
    padding: 0px 30px;
    border-radius: 8px;
    overflow: hidden;
    height: 100%;
    .title {
      font-weight: 600;
      font-size: 18px;
      color: #333333;
      margin-bottom: 20px;
      margin-top: 30px;
    }
    .info {
      .list {
        display: flex;
        flex-wrap: wrap;
        .item {
          display: flex;
          width: 40%;
          margin-bottom: 20px;
          &:nth-of-type(2n) {
            width: 60%;
          }
          .label {
            color: #888888;
            width: 68px;
          }
          .value {
            color: #111111;
          }
        }
      }
    }
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 20px 30px;
      margin: 0 -30px;
      border-radius: 8px 8px 0 0;
      background: linear-gradient(to right, #f2f6fe, #cadffa);
      .h1 {
        font-weight: 600;
        font-size: 22px;
        color: #111111;
        margin-bottom: 8px;
      }
      .time {
        font-size: 14px;
        color: #999999;
      }
      .right {
        height: 40px;
        font-size: 16px;
        color: #ffffff;
        line-height: 40px;
        padding: 0 20px;
        background: #207ff7;
        box-shadow: 4px 4px 0px 0px rgba(32, 127, 247, 0.16);
        border-radius: 16px 0px 16px 0px;
      }
    }
    .table_info {
      .name_wrap {
        display: flex;
        align-items: center;
        .avatar {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin-right: 12px;
        }
        .content {
          .line {
            display: flex;
          }
          .tag {
            color: #b2cbf9;
            border: 1px solid #b2cbf9;
            padding: 0px 4px;
            border-radius: 4px;
            margin-left: 6px;
          }
        }
      }
    }
  }
  .side {
    height: 100%;
    width: 420px;
    background: #ffffff;
    border-left: 20px solid #f7f7f7;
    .list {
      .item {
        padding: 8px 0;
        position: relative;
        .separate {
          position: absolute;
          border-left: 2px dashed #cccccc;
          left: 31px;
          height: calc(100% - 24px);
          top: 46px;
        }
        .info {
          display: flex;
          align-items: center;
          margin-left: 20px;
          .icon {
            position: relative;
            z-index: 11;
            color: #53b76f;
            font-size: 24px;
          }
          .icon1 {
            position: relative;
            z-index: 11;
            color: deepskyblue;
            font-size: 24px;
          }
          .icon2 {
            position: relative;
            z-index: 11;
            color: #dc362e;
            font-size: 24px;
          }
          .avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            margin: 0 12px 0 16px;
            border: 1px solid;
          }
          .content {
            flex: 1;
            .line {
              display: flex;
              justify-content: space-between;
              align-content: center;
              margin-bottom: 6px;
              .name {
                font-weight: 600;
                font-size: 16px;
                color: #111111;
              }
              .time {
                color: #888888;
              }
              .company {
                font-size: 13px;
                color: #888888;
                .status {
                  color: #00ba67;
                }
              }
            }
          }
        }
        .remark {
          background: #f7f7f7;
          border-radius: 4px;
          padding: 13px 15px;
          color: #666666;
          margin-left: 120px;
        }
      }
    }
  }
}
</style>
admin/src/components/business/OperaHiddenDangerWindow.vue
@@ -266,7 +266,6 @@
import upload from '@/components/common/upload'
import { memberList } from '@/api/business/hiddenDangerParam'
import { mapState } from 'vuex'
import { dealHiddenDanger } from '@/api/business/hiddenDanger'
export default {
  components: { GlobalWindow, upload },
  extends: BaseOpera,
@@ -306,7 +305,8 @@
      rulesBack: {
        checkDate: [
          { required: true, message: '请选择退回时间' }
        ]/*,
        ]
        /*,
        dealBeforeFileList: [
          { required: true, message: '请上传整改前情况' }
        ]*/
@@ -455,13 +455,13 @@
        this.memberList = []
        this.transForm = {
          memberId: null
        },
        }
        this.dealForm = {
          checkDate: null,
          checkInfo: null,
          dealBeforeFileList: [],
          dealAfterFileList: []
        },
        }
        this.backForm = {
          checkDate: null,
          checkInfo: null,
admin/src/utils/request.js
@@ -53,7 +53,7 @@
  if (response.data.code === 503) {
    return Promise.reject(new Error('服务器繁忙,请稍后再试'))
  }
  if (response.data.code === 401) {
  if (response.data.code === 401 || response.data.code === 5112) {
    if (response.config.autoLogin !== false) {
      Cookies.set('dm_user_token','')
      window.location.href = process.env.VUE_APP_ROUTER_MODE === 'hash' ? (process.env.VUE_APP_CONTEXT_PATH +'/#/login') : (process.env.VUE_APP_CONTEXT_PATH+'/login')
admin/src/views/operation/serviceCar/apprRecord.vue
@@ -71,13 +71,13 @@
          </template>
        </el-table-column>
        <el-table-column prop="planUseDate" label="出发时间" min-width="150px"></el-table-column>
        <el-table-column label="目的地类型" min-width="100px">
        <el-table-column label="目的地" min-width="200px">
          <template slot-scope="{row}">
            <span class="status-green" v-if="row.type === 0">市内用车</span>
            <span class="status-red"   v-if="row.type === 1">市外用车</span>
            <span class="status-green" v-if="row.type === 0">【市内】</span>
            <span class="status-red"   v-if="row.type === 1">【市外】</span>
            <span >{{ row.addr }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="addr" label="目的地" min-width="200px"></el-table-column>
        <el-table-column label="状态" min-width="100px">
          <template slot-scope="{row}">
            <span class="status-blue"  v-if="row.status === 0">申请中</span>
@@ -97,7 +97,7 @@
            fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" icon="el-icon-edit" @click="$refs.OperaHiddenDangerWindow.open('隐患随手拍详情',row)" >查看详情</el-button>
            <el-button type="text" icon="el-icon-edit" @click="$refs.OperaDetailsWindow.open('公务车申请详情',row)" >查看详情</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -108,7 +108,7 @@
      >
      </pagination>
    </template>
    <OperaHiddenDangerWindow ref="OperaHiddenDangerWindow" @success="handlePageChange"/>
    <OperaCarUseBookWindow ref="OperaDetailsWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
@@ -116,13 +116,13 @@
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaHiddenDangerWindow from '@/components/business/OperaHiddenDangerWindow'
import OperaCarUseBookWindow from '@/components/business/OperaCarUseBookWindow'
import { timeForMat } from '@/utils/util'
import { allList } from '@/api/business/hiddenDangerParam'
export default {
  name: 'Empower',
  extends: BaseTable,
  components: { TableLayout, Pagination ,OperaHiddenDangerWindow},
  components: { TableLayout, Pagination ,OperaCarUseBookWindow},
  data () {
    return {
      // æœç´¢
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/MemberCloudController.java
@@ -245,9 +245,15 @@
    @ApiOperation("查询全部")
    @PostMapping("/list")
    @CloudRequiredPermission("business:member:query")
    public ApiResponse<List<Member>> findPage (@RequestBody Member model,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
    public ApiResponse<List<Member>> list (@RequestBody Member model,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
        return ApiResponse.success(memberService.findList(model));
    }
    @ApiOperation("查询全部司机")
    @PostMapping("/driveList")
    @CloudRequiredPermission("business:member:query")
    public ApiResponse<List<Member>> findDriveList (@RequestBody Member model,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
        return ApiResponse.success(memberService.findDriveList(model));
    }
    @ApiOperation("导出Excel")
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/ApproveParam.java
@@ -46,8 +46,8 @@
    @ExcelColumn(name="是否删除0否 1是")
    private Integer isdeleted;
    @ApiModelProperty(value = "备注")
    @ExcelColumn(name="备注")
    @ApiModelProperty(value = "节点名称")
    @ExcelColumn(name="节点名称")
    private String remark;
    @ApiModelProperty(value = "类型 0审批 1抄送", example = "1")
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/CarUseBook.java
@@ -23,7 +23,6 @@
@ApiModel("车辆_用车申请信息表")
@TableName("`car_use_book`")
public class CarUseBook extends LoginUserModel {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty(value = "主键", example = "1")
    @ExcelColumn(name="主键")
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/MemberService.java
@@ -215,5 +215,5 @@
    String importBatch(MultipartFile file, Integer companyType,LoginUserInfo loginUser);
    List<Member>  findDriveList(Member model);
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -1100,6 +1100,30 @@
        }
        return  list;
    }
    @Override
    public List<Member> findDriveList(Member member) {
        MPJLambdaWrapper<Member> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.leftJoin(Company.class,Company::getId,Member::getCompanyId);
        queryWrapper.selectAll(Member.class)
                .selectAs(Company::getName,Member::getCompanyName)
                .eq(Member::getType,Constants.TWO)
                .exists("select d.id from car_driver b where b.isdeleted=0 and b.member_id=t.id");
        if(null != member.getType()) {
            queryWrapper.eq(Member::getType,member.getType());
        }
        if(null != member.getCompanyId()) {
            queryWrapper.eq(Member::getCompanyId,member.getCompanyId());
        }
        queryWrapper.eq(Member::getIsdeleted,Constants.ZERO);
        List<Member> list =  memberJoinMapper.selectJoinList(Member.class,queryWrapper);
        if(list!=null){
            for(Member m : list){
                m.setName(StringUtils.defaultString(m.getName(),"")+"-"+StringUtils.defaultString(m.getCompanyName(),""));
            }
        }
        return  list;
    }
    @Override
    public PageData<Member> findPage(PageWrap<Member> pageWrap) {