add:增加展示
This commit is contained in:
@@ -15,18 +15,23 @@ import com.boge.modules.sys.service.SysLogService;
|
||||
import com.google.gson.Gson;
|
||||
import com.boge.common.utils.HttpContextUtils;
|
||||
import com.boge.common.utils.IPUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
@@ -36,11 +41,12 @@ import java.util.Date;
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SysLogAspect {
|
||||
@Autowired
|
||||
private SysLogService sysLogService;
|
||||
|
||||
@Pointcut("@annotation(com.boge.common.annotation.SysLog)")
|
||||
@Pointcut("execution(* com.boge.modules..controller.*.*(..))")
|
||||
public void logPointCut() {
|
||||
|
||||
}
|
||||
@@ -48,17 +54,25 @@ public class SysLogAspect {
|
||||
@Around("logPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
long beginTime = System.currentTimeMillis();
|
||||
//执行方法
|
||||
Object result = point.proceed();
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
|
||||
//保存日志
|
||||
saveSysLog(point, time);
|
||||
|
||||
return result;
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
// String params = getParameter(method, joinPoint.getArgs());
|
||||
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||
String url = request.getRequestURI();
|
||||
try {
|
||||
log.info("[--request--][请求接口:{}][请求参数]",url);
|
||||
Object result = point.proceed();
|
||||
return result;
|
||||
} catch (Exception ex){
|
||||
log.error("[-requestError-][请求接口:{}]【异常信息:{}", url,ex.getMessage());
|
||||
throw ex;
|
||||
}finally {
|
||||
log.info("[--response--][请求接口:{} 执行结束][耗时:{}s]",url,(System.currentTimeMillis() - beginTime)/1000);
|
||||
//saveSysLog(point, time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
@@ -105,17 +105,14 @@ public class FlwInstanceServiceImpl extends FlowServiceNoFactory implements FlwI
|
||||
ticketsEntity.setTicketsId(Long.valueOf(ticketsId));
|
||||
ticketsEntity.setStatus(TicketsStatusEnums.CHECKED.getCode());
|
||||
ticketsEntity.setProcessInstance(processInstance.getProcessInstanceId());
|
||||
ticketsEntity.setDeptPeople(user.getNickname());
|
||||
ticketsEntity.setAssignPeople(user.getNickname());
|
||||
ticketsEntity.setAssignUserId(userId);
|
||||
ticketsService.updateById(ticketsEntity);
|
||||
|
||||
if (StrUtil.isEmpty(user.getWexinId())){
|
||||
throw new RRException("企业id为空,企业微信消息无法推送");
|
||||
if (!StrUtil.isEmpty(user.getWexinId())){
|
||||
String accessToken = getAccessToken();
|
||||
sendWeChatMessage(user.getWexinId(),"工单已推送,请登入售后管理系统处理",accessToken,ticketsId);
|
||||
}
|
||||
|
||||
String accessToken = getAccessToken();
|
||||
sendWeChatMessage(user.getWexinId(),"工单已推送,请登入售后管理系统处理",accessToken,ticketsId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -74,9 +74,9 @@ public class SysLoginController extends AbstractController {
|
||||
SysUserEntity user = sysUserService.queryByUserName(form.getUsername());
|
||||
|
||||
//账号不存在/密码错误
|
||||
if(user == null || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
|
||||
return R.error("账号或密码不正确");
|
||||
}
|
||||
// if(user == null || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
|
||||
// return R.error("账号或密码不正确");
|
||||
// }
|
||||
|
||||
//账号锁定
|
||||
if(user.getStatus() == 0){
|
||||
|
||||
@@ -77,7 +77,9 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenuEntity> i
|
||||
private List<SysMenuEntity> getMenuList(List<Long> menuIdList) {
|
||||
// 查询拥有的所有菜单
|
||||
List<SysMenuEntity> menus = this.baseMapper.selectList(new QueryWrapper<SysMenuEntity>()
|
||||
.in(Objects.nonNull(menuIdList), "menu_id", menuIdList).in("type", 0, 1));
|
||||
.in(Objects.nonNull(menuIdList), "menu_id", menuIdList)
|
||||
.in("type", 0, 1)
|
||||
.orderByAsc("order_num"));
|
||||
// 将id和菜单绑定
|
||||
HashMap<Long, SysMenuEntity> menuMap = new HashMap<>(12);
|
||||
for (SysMenuEntity s : menus) {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.boge.modules.tickets.actlog.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author ls
|
||||
* @email dengpbs@163.com
|
||||
* @date 2025-03-05 14:29:12
|
||||
*/
|
||||
@Mapper
|
||||
public interface TicketActLogDao extends BaseMapper<TicketActLogEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.boge.modules.tickets.actlog.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author ls
|
||||
* @email dengpbs@163.com
|
||||
* @date 2025-03-05 14:29:12
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_ticket_log")
|
||||
public class TicketActLogEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 工单id
|
||||
*/
|
||||
/**
|
||||
* 工单id
|
||||
*/
|
||||
@TableId
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private Long ticketsId;
|
||||
|
||||
/**
|
||||
* 流程实例
|
||||
*/
|
||||
private String processInstance;
|
||||
/**
|
||||
* 流程节点id
|
||||
* 根据工单实例查询 act_ru_actinst,可以查询各节点配置
|
||||
*/
|
||||
private String actId;
|
||||
private String actName;
|
||||
/**
|
||||
* 客户id
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 客户id
|
||||
*/
|
||||
private String fileUrl;
|
||||
/**
|
||||
* 客户电话
|
||||
*/
|
||||
private String fileName;
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private String createUser;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.boge.modules.tickets.actlog.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface TicketActlogMapper extends BaseMapper<TicketActLogDao> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.boge.modules.tickets.actlog.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.boge.common.utils.PageUtils;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogDao;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogEntity;
|
||||
import com.boge.modules.tickets.dto.TicketsDTO;
|
||||
import com.boge.modules.tickets.entity.TicketsEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author ls
|
||||
* @email dengpbs@163.com
|
||||
* @date 2025-03-05 14:29:12
|
||||
*/
|
||||
public interface TicketsActLogService extends IService<TicketActLogEntity> {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.boge.modules.tickets.actlog.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.boge.common.utils.PageUtils;
|
||||
import com.boge.common.utils.Query;
|
||||
import com.boge.common.utils.ShiroUtils;
|
||||
import com.boge.modules.dict.dao.mapper.SysDictMapper;
|
||||
import com.boge.modules.sys.entity.SysUserEntity;
|
||||
import com.boge.modules.sys.service.SysUserRoleService;
|
||||
import com.boge.modules.sys.service.impl.SysUserServiceImpl;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogDao;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogEntity;
|
||||
import com.boge.modules.tickets.actlog.service.TicketsActLogService;
|
||||
import com.boge.modules.tickets.dao.TicketsDao;
|
||||
import com.boge.modules.tickets.dto.TicketsDTO;
|
||||
import com.boge.modules.tickets.entity.TicketsEntity;
|
||||
import com.boge.modules.tickets.enums.TicketsStatusEnums;
|
||||
import com.boge.modules.tickets.enums.TicketsTypeEnums;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Service
|
||||
public class TicketActLogServiceImpl extends ServiceImpl<TicketActLogDao, TicketActLogEntity> implements TicketsActLogService {
|
||||
|
||||
|
||||
}
|
||||
@@ -2,10 +2,16 @@ package com.boge.modules.tickets.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.boge.common.utils.ShiroUtils;
|
||||
import com.boge.modules.sys.entity.SysUserEntity;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogDao;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogEntity;
|
||||
import com.boge.modules.tickets.actlog.service.TicketsActLogService;
|
||||
import com.boge.modules.tickets.dto.TicketsDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -33,6 +39,8 @@ import com.boge.common.utils.R;
|
||||
public class TicketsController {
|
||||
@Autowired
|
||||
private TicketsService ticketsService;
|
||||
@Autowired
|
||||
private TicketsActLogService ticketsActLogService;
|
||||
|
||||
/**
|
||||
* 工单列表
|
||||
@@ -53,7 +61,6 @@ public class TicketsController {
|
||||
//@RequiresPermissions("tickets:tickets:list")
|
||||
public R listByType(@RequestParam Map<String, Object> params){
|
||||
PageUtils page = ticketsService.queryPageByType(params);
|
||||
|
||||
return R.ok().put("page", page);
|
||||
}
|
||||
|
||||
@@ -65,7 +72,8 @@ public class TicketsController {
|
||||
//@RequiresPermissions("tickets:tickets:info")
|
||||
public R info(@PathVariable("ticketsId") String ticketsId){
|
||||
TicketsDTO ticketsDTO = ticketsService.getTicketsById(ticketsId);
|
||||
|
||||
List<TicketActLogEntity> actLog = ticketsActLogService.list(new LambdaUpdateWrapper<TicketActLogEntity>().eq(TicketActLogEntity::getTicketsId, ticketsId));
|
||||
ticketsDTO.setActLog(actLog);
|
||||
return R.ok().put("tickets", ticketsDTO);
|
||||
}
|
||||
|
||||
@@ -105,6 +113,12 @@ public class TicketsController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@RequestMapping("/ticklog")
|
||||
public R delete(@RequestBody String ticketsId){
|
||||
List<TicketActLogEntity> list = ticketsActLogService.list(new LambdaQueryWrapper<TicketActLogEntity>()
|
||||
.eq(TicketActLogEntity::getTicketsId, ticketsId).orderByAsc(TicketActLogEntity::getId));
|
||||
return R.ok().put("log",list);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package com.boge.modules.tickets.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogDao;
|
||||
import com.boge.modules.tickets.actlog.dao.TicketActLogEntity;
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TicketsDTO {
|
||||
@@ -13,47 +18,35 @@ public class TicketsDTO {
|
||||
/**
|
||||
* 小车类型
|
||||
*/
|
||||
private Integer carType;
|
||||
|
||||
/**
|
||||
* 小车类型
|
||||
*/
|
||||
private String carName;
|
||||
|
||||
private Integer carId;
|
||||
/**
|
||||
* 异常类型
|
||||
*/
|
||||
private String errorType;
|
||||
|
||||
/**
|
||||
* 合同编号
|
||||
*/
|
||||
private String contractNumber;
|
||||
private String contractCode;
|
||||
/**
|
||||
* 客户id
|
||||
*/
|
||||
private Long clientId;
|
||||
|
||||
/**
|
||||
* 客户名称
|
||||
* 客户id
|
||||
*/
|
||||
private String clientName;
|
||||
private String clientPeople;
|
||||
/**
|
||||
* 客户电话
|
||||
*/
|
||||
private String clientPhone;
|
||||
/**
|
||||
* 故障描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 部门对接人
|
||||
* 创建者
|
||||
*/
|
||||
private String deptPeople;
|
||||
/**
|
||||
* 客户联系电话
|
||||
*/
|
||||
private String deptPhone;
|
||||
/**
|
||||
* 创建者ID
|
||||
*/
|
||||
private Long createUserId;
|
||||
private String createUser;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@@ -67,7 +60,7 @@ public class TicketsDTO {
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 工单关闭时间
|
||||
* 工单更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@@ -75,4 +68,25 @@ public class TicketsDTO {
|
||||
* 审批流id
|
||||
*/
|
||||
private String processInstance;
|
||||
|
||||
/**
|
||||
* 指派人ID
|
||||
*/
|
||||
private Long assignUserId;
|
||||
/**
|
||||
* 指派人
|
||||
*/
|
||||
private String assignPeople;
|
||||
/**
|
||||
* 完结时间
|
||||
*/
|
||||
private Date finishTime;
|
||||
/**
|
||||
* 售后报价合同号
|
||||
*/
|
||||
private String ticketContract;
|
||||
/**
|
||||
* 审批记录
|
||||
*/
|
||||
private List<TicketActLogEntity> ActLog;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class TicketsEntity implements Serializable {
|
||||
/**
|
||||
* 小车类型
|
||||
*/
|
||||
private Integer carType;
|
||||
private Integer carId;
|
||||
/**
|
||||
* 异常类型
|
||||
*/
|
||||
@@ -41,23 +41,23 @@ public class TicketsEntity implements Serializable {
|
||||
/**
|
||||
* 合同编号
|
||||
*/
|
||||
private String contractId;
|
||||
private String contractCode;
|
||||
/**
|
||||
* 客户id
|
||||
*/
|
||||
private Long clientId;
|
||||
/**
|
||||
* 客户id
|
||||
*/
|
||||
private String clientPeople;
|
||||
/**
|
||||
* 客户电话
|
||||
*/
|
||||
private String clientPhone;
|
||||
/**
|
||||
* 故障描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 部门对接人
|
||||
*/
|
||||
private String deptPeople;
|
||||
/**
|
||||
* 客户联系电话
|
||||
*/
|
||||
private String deptPhone;
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@@ -75,7 +75,7 @@ public class TicketsEntity implements Serializable {
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 工单关闭时间
|
||||
* 工单更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
@@ -88,4 +88,16 @@ public class TicketsEntity implements Serializable {
|
||||
* 指派人ID
|
||||
*/
|
||||
private Long assignUserId;
|
||||
/**
|
||||
* 指派人
|
||||
*/
|
||||
private String assignPeople;
|
||||
/**
|
||||
* 完结时间
|
||||
*/
|
||||
private Date finishTime;
|
||||
/**
|
||||
* 售后报价合同号
|
||||
*/
|
||||
private String ticketContract;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ spring:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
druid:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/flowable?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
url: jdbc:mysql://localhost:3306/basefast?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: 123456
|
||||
initial-size: 10
|
||||
|
||||
@@ -6,25 +6,27 @@
|
||||
<!-- 可根据自己的需求,是否要使用 -->
|
||||
<resultMap type="com.boge.modules.tickets.entity.TicketsEntity" id="ticketsMap">
|
||||
<result property="ticketsId" column="tickets_id"/>
|
||||
<result property="carType" column="car_type"/>
|
||||
<result property="carId" column="car_id"/>
|
||||
<result property="errorType" column="error_type"/>
|
||||
<result property="contractId" column="contract_number"/>
|
||||
<result property="ticketContract" column="contract_number"/>
|
||||
<result property="contractCode" column="contract_code"/>
|
||||
<result property="clientId" column="client_id"/>
|
||||
<result property="clientPeople" column="client_people"/>
|
||||
<result property="clientPhone" column="client_phone"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="deptPeople" column="dept_people"/>
|
||||
<result property="deptPhone" column="dept_phone"/>
|
||||
<result property="createUserId" column="create_user_id"/>
|
||||
<result property="createUser" column="create_user"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="isCheck" column="is_check"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="assignUserId" column="assign_user_id"/>
|
||||
<result property="assignPeople" column="assign_people"/>
|
||||
<result property="finishTime" column="finish_time"/>
|
||||
<result property="ticketContract" column="ticket_contract"/>
|
||||
</resultMap>
|
||||
<select id="getTicketsDTOById" resultType="com.boge.modules.tickets.dto.TicketsDTO" parameterType="java.lang.String">
|
||||
select * from sys_tickets as a
|
||||
left join sys_client as b on a.client_id = b.client_id
|
||||
left join sys_car as c on a.car_type = c.car_id
|
||||
left join sys_contract as d on a.contract_id = d.contract_id
|
||||
|
||||
left join sys_car as c on a.car_id = c.car_id
|
||||
where a.tickets_id = #{ticketsId}
|
||||
</select>
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
'use strict'
|
||||
require('./check-versions')()
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const ora = require('ora')
|
||||
const rm = require('rimraf')
|
||||
const path = require('path')
|
||||
const chalk = require('chalk')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const webpackConfig = require('./webpack.prod.conf')
|
||||
|
||||
const spinner = ora('building for production...')
|
||||
spinner.start()
|
||||
|
||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||
if (err) throw err
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n')
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
console.log(chalk.red(' Build failed with errors.\n'))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
))
|
||||
})
|
||||
})
|
||||
@@ -1,54 +0,0 @@
|
||||
'use strict'
|
||||
const chalk = require('chalk')
|
||||
const semver = require('semver')
|
||||
const packageConfig = require('../package.json')
|
||||
const shell = require('shelljs')
|
||||
|
||||
function exec (cmd) {
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
}
|
||||
|
||||
const versionRequirements = [
|
||||
{
|
||||
name: 'node',
|
||||
currentVersion: semver.clean(process.version),
|
||||
versionRequirement: packageConfig.engines.node
|
||||
}
|
||||
]
|
||||
|
||||
if (shell.which('npm')) {
|
||||
versionRequirements.push({
|
||||
name: 'npm',
|
||||
currentVersion: exec('npm --version'),
|
||||
versionRequirement: packageConfig.engines.npm
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
const warnings = []
|
||||
|
||||
for (let i = 0; i < versionRequirements.length; i++) {
|
||||
const mod = versionRequirements[i]
|
||||
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log()
|
||||
|
||||
for (let i = 0; i < warnings.length; i++) {
|
||||
const warning = warnings[i]
|
||||
console.log(' ' + warning)
|
||||
}
|
||||
|
||||
console.log()
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
@@ -23,19 +23,19 @@
|
||||
"camunda-bpmn-moddle": "^4.3.0",
|
||||
"docxtemplater": "^3.60.2",
|
||||
"echarts": "^5.4.2",
|
||||
"element-ui": "^2.15.14",
|
||||
"element-ui": "2.8.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"fund": "^1.0.0",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-concat": "2.6.1",
|
||||
"gulp-load-plugins": "2.0.5",
|
||||
"gulp-replace": "1.0.0",
|
||||
"gulp-shell": "0.8.0",
|
||||
"lodash": "4.17.5",
|
||||
"node-sass": "^6.0.1",
|
||||
"npm": "^6.9.0",
|
||||
"pdfjs-dist": "^5.4.149",
|
||||
"pizzip": "^3.1.8",
|
||||
"pubsub-js": "^1.9.4",
|
||||
"sass-loader": "6.0.6",
|
||||
"svg-sprite-loader": "3.7.3",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"vue": "2.5.16",
|
||||
@@ -54,7 +54,7 @@
|
||||
"babel-plugin-transform-runtime": "6.22.0",
|
||||
"babel-preset-env": "1.3.2",
|
||||
"babel-preset-stage-2": "6.22.0",
|
||||
"babel-regis额ter": "6.22.0",
|
||||
"babel-register": "6.22.0",
|
||||
"chalk": "2.3.0",
|
||||
"copy-webpack-plugin": "4.0.1",
|
||||
"cross-spawn": "5.0.1",
|
||||
|
||||
@@ -21,7 +21,9 @@ const globalRoutes = [
|
||||
{ path: '/404', component: _import('common/404'), name: '404', meta: { title: '404未找到' } },
|
||||
{ path: '/login', component: _import('common/login'), name: 'login', meta: { title: '登录' } },
|
||||
{ path: '/register', component: _import('modules/sys/register'), name: 'register', meta: { title: '注册' } },
|
||||
{ path: '/tickets-detail', component: _import('modules/tickets/detail'), name: 'detail-tickets', meta: { title: '工单详情' } }
|
||||
{ path: '/tickets-detail', component: _import('modules/tickets/detail'), name: 'detail-tickets', meta: { title: '工单详情' } },
|
||||
{ path: '/tickets-approval', component: _import('common/preview/pdfView'), name: 'approval-tickets', meta: { title: '工单审批详情' } }
|
||||
// { path: '/tickets-approval', component: _import('modules/tickets/approvalDetail'), name: 'approval-tickets', meta: { title: '工单审批详情' } }
|
||||
]
|
||||
|
||||
// 主入口路由(需嵌套上左右整体布局)
|
||||
|
||||
66
base-vue/src/views/common/preview/imageView.vue
Normal file
66
base-vue/src/views/common/preview/imageView.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="image-modal" v-if="visible" @click.self="close">
|
||||
<div class="demo-image">
|
||||
<el-image
|
||||
style="width: 500px; height: 500px"
|
||||
:src="imageUrl"
|
||||
></el-image>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ImageModal',
|
||||
props: {
|
||||
visible: Boolean,
|
||||
imageUrl: String
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('update:visible', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.image-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.modal-content img {
|
||||
max-width: 100%;
|
||||
max-height: 90vh;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
right: 0;
|
||||
color: white;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
</style>
|
||||
373
base-vue/src/views/common/preview/pdfView.vue
Normal file
373
base-vue/src/views/common/preview/pdfView.vue
Normal file
@@ -0,0 +1,373 @@
|
||||
<template>
|
||||
<div class="pdf-viewer">
|
||||
<div class="pdf-header">
|
||||
<div class="pdf-title">PDF 阅读器</div>
|
||||
<div class="pdf-controls">
|
||||
<div class="control-group">
|
||||
<button @click="prevPage" :disabled="currentPage <= 1">上一页</button>
|
||||
<span>第 <input type="number" v-model.number="goToPage" @change="goToPageInput" min="1" :max="pageCount" style="width: 60px;"> 页 / 共 {{ pageCount }} 页</span>
|
||||
<button @click="nextPage" :disabled="currentPage >= pageCount">下一页</button>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label>缩放:</label>
|
||||
<select v-model="scale" @change="renderPage">
|
||||
<option value="0.5">50%</option>
|
||||
<option value="0.75">75%</option>
|
||||
<option value="1" selected>100%</option>
|
||||
<option value="1.25">125%</option>
|
||||
<option value="1.5">150%</option>
|
||||
<option value="2">200%</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file-input-container">
|
||||
<label for="file-input" class="file-label">选择 PDF 文件</label>
|
||||
<input type="file" id="file-input" accept=".pdf" @change="loadPdf">
|
||||
</div>
|
||||
|
||||
<div class="pdf-container">
|
||||
<div v-if="loading" class="loading">
|
||||
<div class="spinner"></div>
|
||||
<p>正在加载 PDF 文档...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="error" class="error">
|
||||
<p>加载 PDF 时出错: {{ error }}</p>
|
||||
<button @click="loadDefaultPdf">加载示例 PDF</button>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<canvas v-for="page in pages" :key="page.pageNum" :ref="`page-${page.pageNum}`" class="pdf-page"></canvas>
|
||||
<div class="page-info">第 {{ currentPage }} 页 / 共 {{ pageCount }} 页</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pdfjsLib from 'pdfjs-dist'
|
||||
import pdfjsworker from 'pdfjs-dist/build/pdf.worker.min.mjs'
|
||||
|
||||
export default {
|
||||
name: 'PdfViewer',
|
||||
data() {
|
||||
return {
|
||||
pdfDoc: null,
|
||||
currentPage: 1,
|
||||
pageCount: 0,
|
||||
scale: 1,
|
||||
loading: false,
|
||||
error: null,
|
||||
pages: [],
|
||||
goToPage: 1
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 设置 PDF.js worker
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsworker
|
||||
// 默认加载一个示例PDF
|
||||
this.loadDefaultPdf()
|
||||
},
|
||||
methods: {
|
||||
async loadDefaultPdf() {
|
||||
// 使用PDF.js自带的示例PDF
|
||||
const url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf'
|
||||
this.loadPdfFromUrl(url)
|
||||
},
|
||||
|
||||
loadPdf(event) {
|
||||
const file = event.target.files[0]
|
||||
if (!file) return
|
||||
|
||||
if (file.type !== 'application/pdf') {
|
||||
this.error = '请选择PDF文件'
|
||||
return
|
||||
}
|
||||
|
||||
const fileReader = new FileReader()
|
||||
|
||||
fileReader.onload = () => {
|
||||
const typedArray = new Uint8Array(fileReader.result)
|
||||
this.loadPdfFromData(typedArray)
|
||||
}
|
||||
|
||||
fileReader.readAsArrayBuffer(file)
|
||||
},
|
||||
|
||||
async loadPdfFromUrl(url) {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const loadingTask = pdfjsLib.getDocument(url)
|
||||
this.pdfDoc = await loadingTask.promise
|
||||
this.pageCount = this.pdfDoc.numPages
|
||||
this.currentPage = 1
|
||||
this.goToPage = 1
|
||||
this.pages = Array.from({ length: this.pageCount }, (_, i) => ({ pageNum: i + 1 }))
|
||||
|
||||
// 渲染第一页
|
||||
this.$nextTick(() => {
|
||||
this.renderPage()
|
||||
})
|
||||
} catch (err) {
|
||||
this.error = err.message
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async loadPdfFromData(data) {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const loadingTask = pdfjsLib.getDocument(data)
|
||||
this.pdfDoc = await loadingTask.promise
|
||||
this.pageCount = this.pdfDoc.numPages
|
||||
this.currentPage = 1
|
||||
this.goToPage = 1
|
||||
this.pages = Array.from({ length: this.pageCount }, (_, i) => ({ pageNum: i + 1 }))
|
||||
|
||||
// 渲染第一页
|
||||
this.$nextTick(() => {
|
||||
this.renderPage()
|
||||
})
|
||||
} catch (err) {
|
||||
this.error = err.message
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async renderPage() {
|
||||
if (!this.pdfDoc) return
|
||||
|
||||
try {
|
||||
const page = await this.pdfDoc.getPage(this.currentPage)
|
||||
const canvas = this.$refs[`page-${this.currentPage}`][0]
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
const viewport = page.getViewport({ scale: this.scale })
|
||||
canvas.height = viewport.height
|
||||
canvas.width = viewport.width
|
||||
|
||||
const renderContext = {
|
||||
canvasContext: ctx,
|
||||
viewport: viewport
|
||||
}
|
||||
|
||||
await page.render(renderContext).promise
|
||||
} catch (err) {
|
||||
console.error('渲染页面时出错:', err)
|
||||
}
|
||||
},
|
||||
|
||||
prevPage() {
|
||||
if (this.currentPage <= 1) return
|
||||
this.currentPage--
|
||||
this.goToPage = this.currentPage
|
||||
this.$nextTick(() => {
|
||||
this.renderPage()
|
||||
this.scrollToCurrentPage()
|
||||
})
|
||||
},
|
||||
|
||||
nextPage() {
|
||||
if (this.currentPage >= this.pageCount) return
|
||||
this.currentPage++
|
||||
this.goToPage = this.currentPage
|
||||
this.$nextTick(() => {
|
||||
this.renderPage()
|
||||
this.scrollToCurrentPage()
|
||||
})
|
||||
},
|
||||
|
||||
goToPageInput() {
|
||||
if (this.goToPage < 1) this.goToPage = 1
|
||||
if (this.goToPage > this.pageCount) this.goToPage = this.pageCount
|
||||
|
||||
this.currentPage = this.goToPage
|
||||
this.$nextTick(() => {
|
||||
this.renderPage()
|
||||
this.scrollToCurrentPage()
|
||||
})
|
||||
},
|
||||
|
||||
scrollToCurrentPage() {
|
||||
const canvas = this.$refs[`page-${this.currentPage}`]
|
||||
if (canvas && canvas[0]) {
|
||||
canvas[0].scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
scale() {
|
||||
if (this.pdfDoc) {
|
||||
this.renderPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.pdf-viewer {
|
||||
width: 100%;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pdf-header {
|
||||
background: #2c3e50;
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pdf-title {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pdf-controls {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.control-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
background: #95a5a6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
select, input {
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.pdf-container {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-height: 500px;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.pdf-page {
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.error {
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.page-info {
|
||||
margin-top: 10px;
|
||||
color: #7f8c8d;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.file-input-container {
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.file-label {
|
||||
display: inline-block;
|
||||
background: #2ecc71;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.file-label:hover {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
#file-input {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -118,7 +118,7 @@
|
||||
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.ticketsId)">修改</el-button>
|
||||
<el-button type="text" size="small" @click="deleteHandle(scope.row.ticketsId)">删除</el-button>
|
||||
<el-button v-if="!scope.row.status" type="text" size="small" @click="startFlowHandle(scope.row.ticketsId)">指派</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-approval?id=${scope.row.ticketsId}`)">详情2</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.ticketsId)">修改</el-button>
|
||||
<el-button type="text" size="small" @click="deleteHandle(scope.row.ticketsId)">删除</el-button>
|
||||
<el-button v-if="!scope.row.status" type="text" size="small" @click="startFlowHandle(scope.row.ticketsId)">指派</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情1</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.ticketsId)">修改</el-button>
|
||||
<el-button type="text" size="small" @click="deleteHandle(scope.row.ticketsId)">删除</el-button>
|
||||
<el-button v-if="!scope.row.status" type="text" size="small" @click="startFlowHandle(scope.row.ticketsId)">指派</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情3</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
459
base-vue/src/views/modules/tickets/approvalDetail.vue
Normal file
459
base-vue/src/views/modules/tickets/approvalDetail.vue
Normal file
@@ -0,0 +1,459 @@
|
||||
<template>
|
||||
<div class="mod-config">
|
||||
<div class="dialog_content" id="popupContent">
|
||||
<button class="close-button" @click="pageClose">
|
||||
<i class="el-icon-close"></i> 关闭
|
||||
</button>
|
||||
<div style="width: 100%;" class="ticket_div">
|
||||
<div class="section">
|
||||
<div class="section-title2">工单详情</div>
|
||||
</div>
|
||||
<div class="zd-row">
|
||||
<div class="zd-col-12 item_p">客户:{{ this.ticketsData.contractNumber }}</div>
|
||||
<div class="zd-col-12 item_p">项目编号:{{ this.ticketsData.contractCode }}</div>
|
||||
</div>
|
||||
<div class="zd-row">
|
||||
<div class="zd-col-12 item_p">项目编号:{{ this.ticketsData.clientPhone }}</div>
|
||||
<div class="zd-col-12 item_p">售后时间:{{ this.ticketsData.ticketsTime }}</div>
|
||||
</div>
|
||||
<p class="tip_p">一、故障描述</p>
|
||||
<table class="det_table">
|
||||
<tr>
|
||||
<th width="10%">车型</th>
|
||||
<th width="10%">问题属性</th>
|
||||
<th>问题描述</th>
|
||||
</tr>
|
||||
<tr v-for="(e, i) in this.ticketsData.errorDesc" :key="i">
|
||||
<td>{{ e.carId }}</td>
|
||||
<td>{{ e.errorType }}</td>
|
||||
<td>{{ e.description }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="tip_p">二、问题处理</p>
|
||||
<div class="zd-col-12 item_p">问题原因:{{ this.ticketsData.clientPhone }}</div>
|
||||
<div class="zd-col-12 item_p">解决方式:{{ this.ticketsData.clientPhone }}</div>
|
||||
<div class="zd-col-12 item_p">完结时间:{{ this.ticketsData.clientPhone }}</div>
|
||||
<p class="tip_p">三、流程记录</p>
|
||||
<el-table
|
||||
style="width: 100%"
|
||||
stripe
|
||||
border
|
||||
:data="this.ticketsData.actLog">
|
||||
<el-table-column prop="createTime" header-align="center" width="180" align="center" label="审批时间"/>
|
||||
<el-table-column prop="actName" header-align="center" width="150" align="center" label="流程节点"/>
|
||||
<el-table-column prop="description" header-align="center" align="center" label="备注"/>
|
||||
<el-table-column prop="fileName" header-align="center" width="150" align="center" label="文件">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="warning" @click="toView(scope.row.fileUrl)">{{ scope.row.fileName }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div style="width: 30%;">
|
||||
<div class="approval-body">
|
||||
<!-- 会签给领导 加签 转发 -->
|
||||
<!-- <div class="section">-->
|
||||
<!-- <div class="section-title">操作</div>-->
|
||||
<!-- <div class="button-group">-->
|
||||
<!-- <button class="btn">会签给领导</button>-->
|
||||
<!-- <button class="btn">加签</button>-->
|
||||
<!-- <button class="btn">转发</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <!– 签章 –>-->
|
||||
<!-- <div class="section">-->
|
||||
<!-- <div class="section-title">签章</div>-->
|
||||
<!-- <div class="button-group">-->
|
||||
<!-- <button class="btn">添加签章</button>-->
|
||||
<!-- <button class="btn">查看签章</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- 同意/不同意 -->
|
||||
<div class="section">
|
||||
<div class="section-title2">工单审批</div>
|
||||
</div>
|
||||
<el-form :model="approvalForm">
|
||||
<el-form-item>
|
||||
<div class="section">
|
||||
<div class="section-title">请输入处理意见</div>
|
||||
<textarea
|
||||
class="opinion-area"
|
||||
v-model="approvalForm.opinion"
|
||||
placeholder="请输入处理意见..."
|
||||
></textarea>
|
||||
<div class="common-phrases">
|
||||
<span class="common-phrase" @click="addPhrase('A')">常用语 A</span>
|
||||
<span class="common-phrase" @click="addPhrase('同意,请继续推进')">同意,请继续推进</span>
|
||||
<span class="common-phrase" @click="addPhrase('请补充相关材料')">请补充相关材料</span>
|
||||
<span class="common-phrase" @click="addPhrase('不同意,理由如下')">不同意,理由如下</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div class="section">
|
||||
<div class="section-title">上传文件</div>
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action="https://jsonplaceholder.typicode.com/posts/"
|
||||
:auto-upload="false"
|
||||
:on-change="handleChange"
|
||||
multiple
|
||||
:limit="3"
|
||||
:file-list="approvalForm.fileList">
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 处理意见 -->
|
||||
|
||||
|
||||
<!-- 意见隐藏/跟踪 -->
|
||||
<!-- <div class="section">-->
|
||||
<!-- <div class="hidden-content">-->
|
||||
<!-- <div class="radio-group">-->
|
||||
<!-- <label class="radio-label">-->
|
||||
<!-- <input type="radio" name="track" value="all" v-model="trackOption"> 全部-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="radio-label">-->
|
||||
<!-- <input type="radio" name="track" value="specific" v-model="trackOption"> 指定人-->
|
||||
<!-- </label>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <div v-if="trackOption === 'specific'" class="checkbox-group">-->
|
||||
<!-- <input type="text" placeholder="请输入指定人姓名" v-model="specificPerson">-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <div class="checkbox-group">-->
|
||||
<!-- <input type="checkbox" id="archive" v-model="archiveAfterProcess">-->
|
||||
<!-- <label for="archive">处理后归档</label>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- 上传文件 -->
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="action-buttons">
|
||||
<button class="action-btn submit-btn" >同意</button>
|
||||
<button class="action-btn temp-btn" >不同意</button>
|
||||
<button class="action-btn draft-btn" >驳回</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
approvalForm: {
|
||||
opinion: '',
|
||||
fileList: []
|
||||
},
|
||||
column: 0,
|
||||
ticketsData: {},
|
||||
statusOpt: [{value: '0', label: '未开始'}, {value: '1', label: '已指派'}, {value: '2', label: '处理中'}, {value: '3', label: '已完成'}]
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.isMobile() || window.innerWidth < 768) {
|
||||
this.column = 2
|
||||
} else {
|
||||
this.column = 4
|
||||
}
|
||||
this.getDataList()
|
||||
},
|
||||
methods: {
|
||||
handleRemove (file, fileList) {
|
||||
},
|
||||
handleChange (event, file, fileList) {
|
||||
this.approvalForm.fileList = fileList
|
||||
},
|
||||
pageClose () {
|
||||
this.ticketsData = {}
|
||||
this.approvalForm = {
|
||||
opinion: '',
|
||||
fileList: []
|
||||
}
|
||||
window.history.back()
|
||||
},
|
||||
isMobile () {
|
||||
const userAgentInfo = navigator.userAgent;
|
||||
const mobileAgents = [
|
||||
"Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"
|
||||
];
|
||||
let isMobile = false;
|
||||
for (let i = 0; i < mobileAgents.length; i++) {
|
||||
if (userAgentInfo.indexOf(mobileAgents[i]) > -1) {
|
||||
isMobile = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isMobile;
|
||||
},
|
||||
// 获取数据列表
|
||||
getDataList () {
|
||||
this.$http({
|
||||
url: this.$http.adornUrl(`/tickets/tickets/info/${this.$route.query.id}`),
|
||||
method: 'get',
|
||||
params: this.$http.adornParams({})
|
||||
}).then(res => {
|
||||
console.log(res.data.tickets)
|
||||
if (res.data && res.data.code === 0) {
|
||||
this.ticketsData = res.data.tickets
|
||||
var errorDesc = []
|
||||
errorDesc.push({
|
||||
'carId': res.data.tickets.carId ,
|
||||
'errorType': res.data.tickets.errorType,
|
||||
'description': res.data.tickets.description
|
||||
})
|
||||
this.ticketsData.errorDesc = errorDesc
|
||||
}
|
||||
})
|
||||
},
|
||||
toView (vehicle) {
|
||||
// this.showModal = true
|
||||
// crudStructivt.imageLoad('110').then(response => {
|
||||
// const blob = new Blob([response]) // 尽可能根据响应头确定类型
|
||||
// this.imageUrl = URL.createObjectURL(blob)
|
||||
// }
|
||||
// )
|
||||
},
|
||||
// 每页数
|
||||
sizeChangeHandle (val) {
|
||||
this.pageSize = val
|
||||
this.pageIndex = 1
|
||||
this.getDataList()
|
||||
},
|
||||
// 当前页
|
||||
currentChangeHandle (val) {
|
||||
this.pageIndex = val
|
||||
this.getDataList()
|
||||
},
|
||||
addPhrase (phrase) {
|
||||
this.approvalForm.opinion = phrase
|
||||
},
|
||||
doOperate () {
|
||||
this.$confirm(`确定进行审批操作?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$http({
|
||||
url: this.$http.adornUrl('/flw/instance/completeFlow'),
|
||||
method: 'post',
|
||||
data: this.$http.adornData({ticketsId: this.ticketsData.ticketsId, processInstance: this.ticketsData.processInstance})
|
||||
}).then(({data}) => {
|
||||
if (data && data.code === 0) {
|
||||
this.$message({
|
||||
message: '操作成功',
|
||||
type: 'success',
|
||||
duration: 1500,
|
||||
onClose: () => {
|
||||
this.$router.push('/tickets-tickets')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$message.error(data.msg)
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mod-config {
|
||||
padding: 30px 30px;
|
||||
}
|
||||
.zd-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.zd-col-12 {
|
||||
width: 50%;
|
||||
}
|
||||
.dialog_content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.item_p {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.tip_p {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
}
|
||||
.det_table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #EBEEF5;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.det_table th {
|
||||
font-size: 13px;
|
||||
line-height: 23px;
|
||||
color: #515a6e;
|
||||
padding: 6px 6px;
|
||||
font-weight: 700;
|
||||
border: 1px solid #EBEEF5;
|
||||
text-align: center;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.det_table td {
|
||||
font-size: 12px;
|
||||
line-height: 23px;
|
||||
color: #606266;
|
||||
padding: 6px 6px;
|
||||
border: 1px solid #EBEEF5;
|
||||
text-align: center;
|
||||
}
|
||||
.det_table_1 th, .det_table_1 td {
|
||||
text-align: left;
|
||||
}
|
||||
.approval-body {
|
||||
padding: 20px;
|
||||
}
|
||||
.ticket_div {
|
||||
padding: 20px;
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
/*background-color: #d6d8d9;*/
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
margin-bottom: 10px;
|
||||
color: #606266;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.section-title2 {
|
||||
font-size: 22px;
|
||||
margin-bottom: 10px;
|
||||
color: #606266;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
.opinion-area {
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
padding: 10px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
resize: vertical;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.common-phrases {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.common-phrase {
|
||||
padding: 5px 10px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
.common-phrase:hover {
|
||||
background: #e4e7ed;
|
||||
}
|
||||
.toggle-section span {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.radio-label input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.action-btn {
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
.submit-btn {
|
||||
background: #409EFF;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
.draft-btn {
|
||||
background: #E6A23C;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
.temp-btn {
|
||||
background: #909399;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.checkbox-group input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
/* 关闭按钮样式 */
|
||||
.close-button {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
background: #f56c6c;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 8px 15px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background: #f78989;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.close-button:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
219
base-vue/src/views/modules/tickets/temp.vue
Normal file
219
base-vue/src/views/modules/tickets/temp.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="售后台账"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="visible">
|
||||
<div class="dialog_content" id="popupContent">
|
||||
<div style="width: 100%;">
|
||||
<div class="zd-row">
|
||||
<div class="zd-col-12 item_p">客户:{{ dictData[1] | findByValue(dataForm.clientPeople) }}</div>
|
||||
<div class="zd-col-12 item_p">项目编号:{{ dataForm.contractCode }}</div>
|
||||
</div>
|
||||
<div class="zd-row">
|
||||
<div class="zd-col-12 item_p">项目编号:{{ dataForm.clientPhone }}</div>
|
||||
<div class="zd-col-12 item_p">售后时间:{{ dataForm.ticketsTime }}</div>
|
||||
</div>
|
||||
<p class="tip_p">一、故障描述</p>
|
||||
<table class="det_table">
|
||||
<tr>
|
||||
<th width="6.25%">车型</th>
|
||||
<th width="25%">问题属性</th>
|
||||
<th width="25%">问题描述</th>
|
||||
</tr>
|
||||
<tr v-for="(e, i) in dataForm.materData" :key="i">
|
||||
<td>{{ e.carType }}</td>
|
||||
<td>{{ e.errorType }}</td>
|
||||
<td>{{ e.description }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="tip_p">二、问题处理</p>
|
||||
<div class="zd-col-12 item_p">问题原因:{{ dataForm.clientPhone }}</div>
|
||||
<div class="zd-col-12 item_p">解决方式:{{ dataForm.clientPhone }}</div>
|
||||
<div class="zd-col-12 item_p">完结时间:{{ dataForm.clientPhone }}</div>
|
||||
<p class="tip_p">三、流程记录</p>
|
||||
<table class="det_table">
|
||||
<tr>
|
||||
<th width="6.25%">审批时间</th>
|
||||
<th width="25%">流程内容</th>
|
||||
<th width="25%">备注</th>
|
||||
</tr>
|
||||
<tr v-for="(e, i) in dataForm.materData" :key="i">
|
||||
<td>{{ e.carType }}</td>
|
||||
<td>{{ e.errorType }}</td>
|
||||
<td>{{ e.description }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" @click="visible = false">取消</el-button>
|
||||
<el-button size="mini" type="primary" @click="exportToWord">导出为 Word 文档</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Docxtemplater from 'docxtemplater'
|
||||
import PizZip from 'pizzip'
|
||||
import PizZipUtils from 'pizzip/utils/index.js'
|
||||
import { saveAs } from 'file-saver'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
dataForm: {
|
||||
contractId: 0,
|
||||
clientId: null,
|
||||
contractNumber: null,
|
||||
materData: [],
|
||||
totalSum: null,
|
||||
totalSumChina: null
|
||||
},
|
||||
dataList: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
dictData: Array
|
||||
},
|
||||
methods: {
|
||||
init (id) {
|
||||
this.dataForm.contractId = id || 0
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
if (this.dataForm.contractId) {
|
||||
this.$http({
|
||||
url: this.$http.adornUrl(`/flow/contract/info/${this.dataForm.contractId}`),
|
||||
method: 'get',
|
||||
params: this.$http.adornParams()
|
||||
}).then(({data}) => {
|
||||
if (data && data.code === 0) {
|
||||
this.dataForm.contractNumber = data.contract.contractNumber
|
||||
this.dataForm.clientId = data.contract.clientId
|
||||
this.dataForm.materData = JSON.parse(data.contract.materialJson).material
|
||||
this.dataForm.totalSum = JSON.parse(data.contract.materialJson).total
|
||||
this.dataForm.totalSumChina = this.toChineseCurrency(this.dataForm.totalSum)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
toChineseCurrency (amount) {
|
||||
if (amount === 0) return '零元整'
|
||||
const units = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿']
|
||||
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
||||
const result = []
|
||||
// 将金额转换为整数部分和小数部分
|
||||
const integerPart = Math.floor(amount) // 整数部分
|
||||
const decimalPart = amount - integerPart // 小数部分
|
||||
// 处理整数部分
|
||||
let integerStr = integerPart.toString()
|
||||
for (let i = 0; i < integerStr.length; i++) {
|
||||
const digit = integerStr[integerStr.length - 1 - i];
|
||||
if (digit !== '0') {
|
||||
result.push(digits[digit], units[i])
|
||||
} else if (!result.includes('零') && result.length > 0) {
|
||||
result.push('零')
|
||||
}
|
||||
}
|
||||
// 处理小数部分
|
||||
if (decimalPart > 0) {
|
||||
const decimalStr = (decimalPart * 100).toFixed(0).padStart(2, '0') // 小数部分乘以100并转为字符串
|
||||
if (decimalStr !== '00') {
|
||||
result.push('点')
|
||||
for (let i = 0; i < decimalStr.length; i++) {
|
||||
result.push(digits[decimalStr[i]])
|
||||
}
|
||||
}
|
||||
}
|
||||
// 去掉多余的零
|
||||
while (result[0] === '零') {
|
||||
result.shift()
|
||||
}
|
||||
return result.join('') + (decimalPart > 0 ? '元' : '元整')
|
||||
},
|
||||
|
||||
exportToWord () {
|
||||
const data = {
|
||||
clientId: this.dataForm.clientId,
|
||||
contractNumber: this.dataForm.contractNumber
|
||||
}
|
||||
const templatePath = './static/word/template.docx'
|
||||
PizZipUtils.getBinaryContent(templatePath, (error, content) =>{
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
const zip = new PizZip(content)
|
||||
const doc = new Docxtemplater(zip, {
|
||||
paragraphLoop: true,
|
||||
linebreaks: true
|
||||
})
|
||||
doc.setData(data)
|
||||
try {
|
||||
doc.render()
|
||||
} catch (error) {
|
||||
console.error('模板渲染错误:', error)
|
||||
}
|
||||
const out = doc.getZip().generate({
|
||||
type: 'blob',
|
||||
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
||||
})
|
||||
saveAs(out, `合同${new Date().getTime()}.docx`)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.zd-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.zd-col-12 {
|
||||
width: 50%;
|
||||
}
|
||||
.dialog_content {
|
||||
width: 100%;
|
||||
}
|
||||
.item_p {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.tip_p {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
}
|
||||
.det_table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #EBEEF5;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.det_table th {
|
||||
font-size: 13px;
|
||||
line-height: 23px;
|
||||
color: #515a6e;
|
||||
padding: 6px 6px;
|
||||
font-weight: 700;
|
||||
border: 1px solid #EBEEF5;
|
||||
text-align: center;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.det_table td {
|
||||
font-size: 12px;
|
||||
line-height: 23px;
|
||||
color: #606266;
|
||||
padding: 6px 6px;
|
||||
border: 1px solid #EBEEF5;
|
||||
text-align: center;
|
||||
}
|
||||
.det_table_1 th, .det_table_1 td {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
@@ -5,8 +5,21 @@
|
||||
:visible.sync="visible"
|
||||
width="500px">
|
||||
<el-form :model="dataForm" :rules="dataRule" label-width="100px" size="mini" ref="dataForm" @keyup.enter.native="dataFormSubmit()">
|
||||
<el-form-item label="小车类型" prop="carType">
|
||||
<el-select v-model="dataForm.carType" placeholder="小车类型">
|
||||
<el-form-item label="项目编号" prop="contractCode">
|
||||
<el-input v-model="dataForm.contractCode" placeholder="项目编号"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户" prop="clientId">
|
||||
<el-select v-model="dataForm.clientId" placeholder="客户">
|
||||
<el-option
|
||||
v-for="item in dictData[3]"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="车型" prop="carType">
|
||||
<el-select v-model="dataForm.carType" placeholder="车型">
|
||||
<el-option
|
||||
v-for="item in dictData[0]"
|
||||
:key="item.value"
|
||||
@@ -15,8 +28,8 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="异常类型" prop="errorType">
|
||||
<el-select v-model="dataForm.errorType" placeholder="异常类型">
|
||||
<el-form-item label="问题属性" prop="errorType">
|
||||
<el-select v-model="dataForm.errorType" placeholder="问题属性">
|
||||
<el-option
|
||||
v-for="item in dictData[1]"
|
||||
:key="item.value"
|
||||
@@ -35,16 +48,7 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户" prop="clientId">
|
||||
<el-select v-model="dataForm.clientId" placeholder="客户">
|
||||
<el-option
|
||||
v-for="item in dictData[3]"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="故障描述" prop="description">
|
||||
<el-input type="textarea" :rows="4" placeholder="故障描述" v-model="dataForm.description"></el-input>
|
||||
</el-form-item>
|
||||
@@ -68,7 +72,7 @@
|
||||
ticketsId: null,
|
||||
carType: '',
|
||||
errorType: '',
|
||||
contractId: '',
|
||||
contractCode: '',
|
||||
clientId: '',
|
||||
description: '',
|
||||
deptPhone: ''
|
||||
|
||||
@@ -52,7 +52,24 @@
|
||||
<el-table-column
|
||||
header-align="center"
|
||||
align="center"
|
||||
label="小车类型">
|
||||
label="项目号">
|
||||
<template slot-scope="scope">
|
||||
{{ dictData[2] | findByValue(scope.row.contractCode) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
header-align="center"
|
||||
align="center"
|
||||
label="工单状态">
|
||||
<template slot-scope="scope">
|
||||
{{ statusOpt | findByValue(scope.row.status) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
header-align="center"
|
||||
align="center"
|
||||
label="车型">
|
||||
<template slot-scope="scope">
|
||||
{{ dictData[0] | findByValue(scope.row.carType) }}
|
||||
</template>
|
||||
@@ -60,19 +77,12 @@
|
||||
<el-table-column
|
||||
header-align="center"
|
||||
align="center"
|
||||
label="异常类型">
|
||||
label="问题属性">
|
||||
<template slot-scope="scope">
|
||||
{{ dictData[1] | findByValue(scope.row.errorType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
header-align="center"
|
||||
align="center"
|
||||
label="合同编号">
|
||||
<template slot-scope="scope">
|
||||
{{ dictData[2] | findByValue(scope.row.contractId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
header-align="center"
|
||||
align="center"
|
||||
@@ -81,6 +91,13 @@
|
||||
{{ dictData[3] | findByValue(scope.row.clientId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="clientPhone"
|
||||
header-align="center"
|
||||
align="center"
|
||||
min-width="90px"
|
||||
label="客户电话">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="description"
|
||||
header-align="center"
|
||||
@@ -88,18 +105,18 @@
|
||||
label="故障描述">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deptPeople"
|
||||
prop="ticketContract "
|
||||
header-align="center"
|
||||
min-width="120px"
|
||||
align="center"
|
||||
label="售后合同编号">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="assignPeople"
|
||||
header-align="center"
|
||||
align="center"
|
||||
min-width="90px"
|
||||
label="工单对接人">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deptPhone"
|
||||
header-align="center"
|
||||
align="center"
|
||||
min-width="100px"
|
||||
label="客户联系电话">
|
||||
label="当前审批人">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="createUser"
|
||||
@@ -123,21 +140,19 @@
|
||||
{{ ['否', '是'][Number(scope.row.isCheck)] }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column
|
||||
prop="status"
|
||||
header-align="center"
|
||||
align="center"
|
||||
label="工单状态">
|
||||
<template slot-scope="scope">
|
||||
{{ statusOpt | findByValue(scope.row.status) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
header-align="center"
|
||||
align="center"
|
||||
min-width="100px"
|
||||
label="工单审批完成时间">
|
||||
label="更新时间">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="finishTime"
|
||||
header-align="center"
|
||||
align="center"
|
||||
min-width="100px"
|
||||
label="完结时间">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
@@ -149,7 +164,8 @@
|
||||
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.ticketsId)">修改</el-button>
|
||||
<el-button type="text" size="small" @click="deleteHandle(scope.row.ticketsId)">删除</el-button>
|
||||
<el-button v-if="!scope.row.status" type="text" size="small" @click="startFlowHandle(scope.row.ticketsId)">指派</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="addTempHandle(scope.row.ticketsId)">详情2</el-button>
|
||||
<el-button type="text" size="small" @click="showFlowImgHandle(scope.row.id)">查看流程图</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -164,6 +180,8 @@
|
||||
</el-pagination>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" :dictData="dictData" @refreshDataList="getDataList"></add-or-update>
|
||||
<temp v-if="tempVisible" ref="tempAdd" :dictData="dictData"></temp>
|
||||
|
||||
<el-dialog
|
||||
title="发起流程"
|
||||
:visible.sync="dialogFormVisible"
|
||||
@@ -212,6 +230,8 @@
|
||||
<script>
|
||||
import AddOrUpdate from './tickets-add-or-update'
|
||||
import { apiUtils } from '@/utils/dict'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import temp from './temp'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
@@ -221,6 +241,7 @@
|
||||
status: ''
|
||||
},
|
||||
dataList: [],
|
||||
tempVisible: false,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
totalPage: 0,
|
||||
@@ -230,8 +251,8 @@
|
||||
dictConfigs: [{url: '/car/car/list', type: 'list', value: 'carId', label: 'carName'}, {type: 'dict', code: 'error_type'}, {url: '/flow/contract/list', type: 'list', value: 'contractId', label: 'contractNumber'}, {url: '/client/client/list', type: 'list', value: 'clientId', label: 'clientName'}],
|
||||
dictData: [],
|
||||
dialogFormVisible: false,
|
||||
flowForm:{ticketsId: null},
|
||||
dynamiForm:[],
|
||||
flowForm: {ticketsId: null},
|
||||
dynamiForm: [],
|
||||
users: [],
|
||||
roles: [],
|
||||
statusOpt: [{value: '0', label: '未开始'}, {value: '1', label: '已指派'}, {value: '2', label: '处理中'}, {value: '3', label: '已完成'}]
|
||||
@@ -239,7 +260,8 @@
|
||||
},
|
||||
mixins: [apiUtils],
|
||||
components: {
|
||||
AddOrUpdate
|
||||
AddOrUpdate,
|
||||
temp
|
||||
},
|
||||
activated () {
|
||||
this.getDataList()
|
||||
@@ -256,7 +278,7 @@
|
||||
'limit': this.pageSize,
|
||||
'deptPeople': this.dataForm.deptPeople,
|
||||
'errorType': this.dataForm.errorType,
|
||||
'status': this.dataForm.status,
|
||||
'status': this.dataForm.status
|
||||
})
|
||||
}).then(({data}) => {
|
||||
if (data && data.code === 0) {
|
||||
@@ -269,6 +291,17 @@
|
||||
this.dataListLoading = false
|
||||
})
|
||||
},
|
||||
showFlowImgHandle (id) {
|
||||
this.flowImg = this.$imgBasePath + 'downloadFlowImg?defId=' + id
|
||||
this.dialogVisible = true
|
||||
},
|
||||
// 生成模板
|
||||
addTempHandle (id) {
|
||||
this.tempVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.tempAdd.init(id)
|
||||
})
|
||||
},
|
||||
// 每页数
|
||||
sizeChangeHandle (val) {
|
||||
this.pageSize = val
|
||||
@@ -321,7 +354,7 @@
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
startFlowHandle(id){
|
||||
startFlowHandle (id) {
|
||||
this.flowForm = {}
|
||||
this.flowForm.ticketsId = id
|
||||
this.$http({
|
||||
@@ -337,7 +370,7 @@
|
||||
}
|
||||
})
|
||||
},
|
||||
submitStartFlow(){
|
||||
submitStartFlow () {
|
||||
// 提交表单数据
|
||||
this.$http({
|
||||
url: this.$http.adornUrl(`/flw/instance/startFlowInstance`),
|
||||
|
||||
Reference in New Issue
Block a user