Commit cc7dd8de authored by liuChang's avatar liuChang

Merge branch 'V20230915' of 192.168.60.201:root/dsk-operate-sys into V20230915

parents 9cb4e776 8e4ccc6b
......@@ -61,6 +61,11 @@
<artifactId>dsk-biz-api</artifactId>
</dependency>
<dependency>
<groupId>com.dsk</groupId>
<artifactId>dsk-biz-bi</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
......@@ -84,6 +89,7 @@
<!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
</dependencies>
<build>
......
......@@ -3,6 +3,7 @@ package com.dsk.web.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.dsk.common.annotation.Log;
import com.dsk.common.annotation.RepeatSubmit;
......@@ -15,9 +16,13 @@ import com.dsk.common.core.validate.AddGroup;
import com.dsk.common.core.validate.EditGroup;
import com.dsk.common.enums.BusinessType;
import com.dsk.common.tenant.helper.TenantHelper;
import com.dsk.common.utils.StringUtils;
import com.dsk.system.domain.SysUser;
import com.dsk.system.domain.bo.SysTenantAdminBo;
import com.dsk.system.domain.bo.SysTenantBo;
import com.dsk.system.domain.vo.SysTenantVo;
import com.dsk.system.service.ISysTenantService;
import com.dsk.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
......@@ -39,11 +44,12 @@ import java.util.Arrays;
@RequestMapping("/system/tenant")
public class SysTenantController extends BaseController {
private final ISysTenantService tenantService;
private final ISysUserService userService;
/**
* 查询租户列表
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:tenant:list", orRole = "accountAdmin")
@GetMapping("/list")
public TableDataInfo<SysTenantVo> list(SysTenantBo bo, PageQuery pageQuery) {
......@@ -67,7 +73,7 @@ public class SysTenantController extends BaseController {
*
* @param id 主键
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:tenant:query", orRole = "accountAdmin")
@GetMapping("/{id}")
public R<SysTenantVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
......@@ -77,7 +83,7 @@ public class SysTenantController extends BaseController {
/**
* 新增租户
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:tenant:add", orRole = "accountAdmin")
@Log(title = "租户", businessType = BusinessType.INSERT)
@Lock4j
......@@ -90,10 +96,26 @@ public class SysTenantController extends BaseController {
return toAjax(TenantHelper.ignore(() -> tenantService.insertByBo(bo)));
}
/**
* 新增企业普通管理员账号
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:user:add")
@Log(title = "用户管理", businessType = BusinessType.INSERT)
@PostMapping("/addTenantAdmin")
public R<Void> addTenantAdmin(@Validated @RequestBody SysTenantAdminBo tenantAdminBo) {
//校验手机号是否已存在
if (TenantHelper.ignore(()->userService.checkTenantAdminPhoneUnique(tenantAdminBo))) {
return R.fail("新增用户'" + tenantAdminBo.getPhonenumber() + "'失败,手机号码已存在");
}
return toAjax(TenantHelper.ignore(() -> tenantService.addTenantAdmin(tenantAdminBo)));
//return R.ok("手机号验证成功");
}
/**
* 修改租户
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:tenant:edit", orRole = "accountAdmin")
@Log(title = "租户", businessType = BusinessType.UPDATE)
@RepeatSubmit()
......@@ -123,7 +145,7 @@ public class SysTenantController extends BaseController {
*
* @param ids 主键串
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:tenant:remove", orRole = "accountAdmin")
@Log(title = "租户", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
......@@ -146,7 +168,7 @@ public class SysTenantController extends BaseController {
/**
* 清除动态租户
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@GetMapping("/dynamic/clear")
public R<Void> dynamicClear() {
TenantHelper.clearDynamic();
......@@ -159,7 +181,7 @@ public class SysTenantController extends BaseController {
* @param tenantId 租户id
* @param packageId 套餐id
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY,TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY},mode = SaMode.OR)
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:tenant:edit", orRole = "accountAdmin")
@Log(title = "租户", businessType = BusinessType.UPDATE)
@GetMapping("/syncTenantPackage")
......
package com.dsk.web.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
......@@ -9,6 +11,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.dsk.biz.utils.ExcelUtils;
import com.dsk.common.annotation.Log;
import com.dsk.common.constant.GlobalConstants;
import com.dsk.common.constant.TenantConstants;
import com.dsk.common.core.controller.BaseController;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.domain.R;
......@@ -16,6 +19,7 @@ import com.dsk.common.core.page.TableDataInfo;
import com.dsk.common.enums.BusinessType;
import com.dsk.common.exception.ServiceException;
import com.dsk.common.helper.LoginHelper;
import com.dsk.common.tenant.helper.TenantHelper;
import com.dsk.common.utils.StreamUtils;
import com.dsk.common.utils.StringUtils;
import com.dsk.common.utils.poi.ExcelUtil;
......@@ -37,6 +41,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.*;
/**
......@@ -55,6 +60,16 @@ public class SysUserController extends BaseController {
private final ISysPostService postService;
private final ISysDeptService deptService;
/**
* 根据租户ID查询大司空超管or租户管理员为其创建的企业管理员和管理员账号数量
*/
@SaCheckRole(value = {TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.DSK_TENANT_ADMIN_ROLE_KEY}, mode = SaMode.OR)
@SaCheckPermission(value = "system:user:query", orRole = "accountAdmin")
@GetMapping("/queryTenantAdminNumCreatedByDSK/{tenantId}")
public R<Long> queryTenantAdminNumCreatedByDSK(@NotNull(message = "租户ID不能为空") @PathVariable Long tenantId) {
return R.ok(TenantHelper.ignore(() -> userService.queryTenantAdminNumCreatedByDSK(tenantId)));
}
/**
* 获取用户列表
*/
......
......@@ -140,7 +140,7 @@ security:
- /*/api-docs
- /*/api-docs/**
# actuator 监控配置
- /actuator
- /api/**
- /actuator/**
......@@ -300,3 +300,25 @@ management:
show-details: ALWAYS
logfile:
external-file: ./logs/sys-console.log
gv:
img-path: D:\dsk\dsk-operate-sys\
#spring:
# datasource:
# type: com.alibaba.druid.pool.DruidDataSource
# druid:
# driver-class-name: com.mysql.cj.jdbc.Driver
# username: ${MYSQL_USER:root}
# password: ${MYSQL_PWD:root}
# url: jdbc:mysql://${MYSQL_HOST:pigx-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:pigxx_report}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true
# jpa:
# database-platform:
# org.hibernate.dialect.MySQL8Dialectsecurity:
# oauth2:
# client:
# ignore-urls:
# - /
# - /api/project/getData
# - /static/**
# - /api/project/get-file/*
# # 文件上传路径
......@@ -18,34 +18,44 @@ public interface TenantConstants {
String DISABLE = "1";
/**
* 超级管理员ID
* 大司空超级管理员ID
*/
Long SUPER_ADMIN_ID = 1L;
/**
* 超级管理员角色 roleKey
* 大司空超级管理员角色 roleKey
*/
String SUPER_ADMIN_ROLE_KEY = "superadmin";
/**
* 租户管理员角色 roleKey
* 大司空租户管理员角色
*/
String TENANT_ADMIN_ROLE_KEY = "admin";
String DSK_TENANT_ADMIN_ROLE_KEY = "accountAdmin";
/**
* 租户管理员角色名称
* 大司空租户管理员角色名称
*/
String TENANT_ADMIN_ROLE_NAME = "管理员";
String DSK_TENANT_ADMIN_ROLE_NAME = "企业账号管理员";
/**
* 大司空租户管理员角色
* 企业超级管理员角色 roleKey
*/
String DSK_TENANT_ADMIN_ROLE_KEY = "accountAdmin";
String TENANT_SUPER_ADMIN_ROLE_KEY = "tenantSuperAdmin";
/**
* 大司空租户管理员角色名称
* 企业超级管理员角色名称
*/
String DSK_TENANT_ADMIN_ROLE_NAME = "企业账号管理员";
String TENANT_SUPER_ADMIN_ROLE_NAME = "企业管理员";
/**
* 企业普通管理员角色 roleKey
*/
String TENANT_ADMIN_ROLE_KEY = "tenantAdmin";
/**
* 企业普通管理员角色名称
*/
String TENANT_ADMIN_ROLE_NAME = "管理员";
/**
* 默认租户ID
......
......@@ -169,7 +169,7 @@ public class LoginHelper {
* @return 结果
*/
public static boolean isTenantAdmin(Set<String> rolePermission) {
return rolePermission.contains(TenantConstants.TENANT_ADMIN_ROLE_KEY);
return rolePermission.contains(TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY);
}
public static boolean isTenantAdmin() {
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>dsk-module</artifactId>
<groupId>com.dsk</groupId>
<version>4.8.0</version>
</parent>
<groupId>com.dsk</groupId>
<artifactId>dsk-biz-bi</artifactId>
<name>dsk-biz-bi</name>
<description>BI数字大屏</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.dsk</groupId>
<artifactId>dsk-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- ORM -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- hutool-core -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<!-- hutool-core -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
</dependency>
<!-- hutool-http -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<!-- hutool-extra -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
</dependency>
<!--数据库-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<!-- <build>-->
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- <configuration>-->
<!-- <image>-->
<!-- <builder>paketobuildpacks/builder-jammy-base:latest</builder>-->
<!-- </image>-->
<!-- </configuration>-->
<!-- </plugin>-->
<!-- </plugins>-->
<!-- </build>-->
</project>
package com.dsk.biz.goview.common.base;
import cn.hutool.core.util.StrUtil;
import com.dsk.biz.goview.common.bean.AjaxResult;
import com.dsk.biz.goview.common.domain.ResultTable;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* web层通用数据处理
*
* @author fuce
* @ClassName: BaseController
* @date 2018年8月18日
*/
public class BaseController {
/**
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
/**
* 响应返回结果
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows) {
return rows > 0 ? success() : error();
}
/**
* 返回成功
*/
public AjaxResult success() {
return AjaxResult.success();
}
/**
* 返回失败消息
*/
public AjaxResult error() {
return AjaxResult.error();
}
/**
* 返回成功消息
*/
public AjaxResult success(String message) {
return AjaxResult.success(message);
}
/**
* 返回失败消息
*/
public AjaxResult error(String message) {
return AjaxResult.error(message);
}
/**
* 返回错误码消息
*/
public AjaxResult error(int code, String message) {
return AjaxResult.error(code, message);
}
/**
* 返回object数据
*/
public AjaxResult retobject(int code, Object data) {
return AjaxResult.successData(code, data);
}
/**
* 页面跳转
*/
public String redirect(String url) {
return StrUtil.format("redirect:{}", url);
}
/**
* Describe: 返回数据表格数据 分页 Param data Return 表格分页数据
*/
protected static ResultTable pageTable(Object data, long count) {
return ResultTable.pageTable(count, data);
}
/**
* Describe: 返回数据表格数据 Param data Return 表格分页数据
*/
protected static ResultTable dataTable(Object data) {
return ResultTable.dataTable(data);
}
/**
* Describe: 返回树状表格数据 分页 Param data Return 表格分页数据
*/
protected static ResultTable treeTable(Object data) {
return ResultTable.dataTable(data);
}
}
package com.dsk.biz.goview.common.base;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 抽象类BaseService
*
* @ClassName: BaseService
* @Description: Service实现这个
* @author fuce
* @date 2018年6月3日
*
*/
public interface BaseService<T, T2> {
int deleteByPrimaryKey(String id);
int insertSelective(T record);
T selectByPrimaryKey(String id);
int updateByPrimaryKeySelective(T record);
int updateByExampleSelective(@Param("record") T record, @Param("example") T2 example);
int updateByExample(@Param("record") T record, @Param("example") T2 example);
List<T> selectByExample(T2 example);
long countByExample(T2 example);
int deleteByExample(T2 example);
}
package com.dsk.biz.goview.common.bean;
import java.util.HashMap;
/**
* @ClassName: AjaxResult
* @Description: ajax操作消息提醒
* @author fuce
* @date 2018年8月18日
*
*/
public class AjaxResult extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
/**
* 初始化一个新创建的 Message 对象
*/
public AjaxResult() {
}
/**
* 返回错误消息
* @return 错误消息
*/
public static AjaxResult error() {
return error(500, "操作失败");
}
/**
* 返回错误消息
* @param msg 内容
* @return 错误消息
*/
public static AjaxResult error(String msg) {
return error(500, msg);
}
/**
* 返回错误消息
* @param code 错误码
* @param msg 内容
* @return 错误消息
*/
public static AjaxResult error(int code, String msg) {
AjaxResult json = new AjaxResult();
json.put("code", code);
json.put("msg", msg);
return json;
}
/**
* 返回成功消息
* @param msg 内容
* @return 成功消息
*/
public static AjaxResult success(String msg) {
AjaxResult json = new AjaxResult();
json.put("msg", msg);
json.put("code", 200);
return json;
}
/**
* 返回成功消息
* @param msg 内容
* @return 成功消息
*/
public static AjaxResult successNullData(String msg) {
AjaxResult json = new AjaxResult();
json.put("msg", msg);
json.put("data", null);
json.put("code", 200);
return json;
}
/**
* 返回成功消息
* @return 成功消息
*/
public static AjaxResult success() {
return AjaxResult.success("操作成功");
}
public static AjaxResult successData(int code, Object value) {
AjaxResult json = new AjaxResult();
json.put("code", code);
json.put("data", value);
return json;
}
/**
* 返回成功消息
* @param key 键值
* @param value 内容
* @return 成功消息
*/
@Override
public AjaxResult put(String key, Object value) {
super.put(key, value);
return this;
}
}
package com.dsk.biz.goview.common.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Entity
public class GoviewProject implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String projectName;
private Integer state;
private LocalDateTime createTime;
private String createUserId;
private Integer isDelete;
private String indexImage;
private String remarks;
private Long tenantId;
@Transient
@TableField(exist = false)
private String content;
}
package com.dsk.biz.goview.common.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Entity
public class GoviewProjectData implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String projectId;
private LocalDateTime createTime;
private String createUserId;
private Long tenantId;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(columnDefinition = "TEXT")
private String content;
}
package com.dsk.biz.goview.common.domain;
import java.util.Map;
public class MagicHttp {
/**
* 请求url
*/
private String url;
/**
* 请求类型 get post
*/
private String requestType;
private Map<String, String> head;
private String body;
private Integer timeout;
private Map<String, Object> form;
private String cookie;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public Map<String, String> getHead() {
return head;
}
public void setHead(Map<String, String> head) {
this.head = head;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getCookie() {
return cookie;
}
public void setCookie(String cookie) {
this.cookie = cookie;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public Map<String, Object> getForm() {
return form;
}
public void setForm(Map<String, Object> form) {
this.form = form;
}
}
package com.dsk.biz.goview.common.domain;
public class ResultTable {
/**
* 状态码
*/
private Integer code;
/**
* 提示消息
*/
private String msg;
/**
* 消息总量
*/
private Long count;
/**
* 数据对象
*/
private Object data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Long getCount() {
return count;
}
public void setCount(Long count) {
this.count = count;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 构 建
*/
public static ResultTable pageTable(long count, Object data) {
ResultTable resultTable = new ResultTable();
resultTable.setData(data);
resultTable.setCode(0);
resultTable.setCount(count);
if (data != null) {
resultTable.setMsg("获取成功");
}
else {
resultTable.setMsg("获取失败");
}
return resultTable;
}
public static ResultTable dataTable(Object data) {
ResultTable resultTable = new ResultTable();
resultTable.setData(data);
resultTable.setCode(0);
if (data != null) {
resultTable.setMsg("获取成功");
}
else {
resultTable.setMsg("获取失败");
}
return resultTable;
}
}
package com.dsk.biz.goview.common.domain;
/**
* boostrap table post 参数
*
* @author fc
*
*/
public class Tablepar {
private int page;// 页码
private int limit;// 数量
private String orderByColumn;// 排序字段
private String isAsc;// 排序字符 asc desc
private String searchText;// 列表table里面的搜索
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public String getOrderByColumn() {
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn) {
this.orderByColumn = orderByColumn;
}
public String getIsAsc() {
return isAsc;
}
public void setIsAsc(String isAsc) {
this.isAsc = isAsc;
}
public String getSearchText() {
return searchText;
}
public void setSearchText(String searchText) {
this.searchText = searchText;
}
}
///*
// * Copyright (c) 2018-2025, lengleng All rights reserved.
// *
// * Redistribution and use in source and binary forms, with or without
// * modification, are permitted provided that the following conditions are met:
// *
// * Redistributions of source code must retain the above copyright notice,
// * this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// * notice, this list of conditions and the following disclaimer in the
// * documentation and/or other materials provided with the distribution.
// * Neither the name of the pig4cloud.com developer nor the names of its
// * contributors may be used to endorse or promote products derived from
// * this software without specific prior written permission.
// * Author: lengleng (wangiegie@gmail.com)
// */
//
//package com.dsk.biz.goview.config;
//
//import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import net.sf.jsqlparser.expression.Expression;
//import net.sf.jsqlparser.expression.LongValue;
//import net.sf.jsqlparser.expression.NullValue;
//
///**
// * @author lengleng
// * @date 2018-12-26
// * <p>
// * 租户维护处理器
// */
//@Slf4j
//@RequiredArgsConstructor
//public class DataVTenantHandler implements TenantLineHandler {
//
// /**
// * 获取租户 ID 值表达式,只支持单个 ID 值
// * <p>
// * @return 租户 ID 值表达式
// */
// @Override
// public Expression getTenantId() {
// Long tenantId = TenantContextHolder.getTenantId();
// log.debug("当前租户为 >> {}", tenantId);
//
// if (tenantId == null) {
// return new NullValue();
// }
// return new LongValue(tenantId);
// }
//
//}
package com.dsk.biz.goview.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2022/5/2
* <p>
* 数据大屏配置
*/
@Data
//@ConfigurationProperties("gv")
@Component
@ConfigurationProperties(prefix = "gv")
public class GoviewProperties {
/**
* 服务 http://IP:port
*/
private String host = "";
/**
* 路由前缀
*/
private String gatewayPrefix = "/api/gv";
/**
* 图片存放路径
*/
private String imgPath;
/**
* 项目 license
*/
private String license;
/**
* 是否开启检查更新
*/
private boolean checkUpdate = true;
}
///*
// * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package com.dsk.biz.goview.config;
//
//import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
//import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
//import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
//import org.mybatis.spring.annotation.MapperScan;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
//import org.springframework.boot.autoconfigure.domain.EntityScan;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
///**
// * @author lengleng
// * @date 2020-03-14
// * <p>
// * mybatis plus 统一配置
// */
//@Configuration(proxyBeanMethods = false)
//@MapperScan(basePackages = "io.springboot.plugin.goview.mapper")
//@EntityScan(basePackages = "io.springboot.plugin.goview.common.domain")
//public class MybatisAutoConfiguration {
//
// @Bean
// public TenantContextHolderFilter tenantContextHolderFilter() {
// return new TenantContextHolderFilter();
// }
//
// /**
// * 分页插件, 对于单一数据库类型来说,都建议配置该值,避免每次分页都去抓取数据库类型
// */
// @Bean
// @ConditionalOnMissingBean
// public MybatisPlusInterceptor mybatisPlusInterceptor() {
// MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new DataVTenantHandler()));
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// return interceptor;
// }
//
//}
package com.dsk.biz.goview.config;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.lang.Nullable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
/**
* @author lengleng
* @date 2023/4/5
*/
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
Properties propertiesFromYaml = loadYamlIntoProperties(resource);
String sourceName = name != null ? name : resource.getResource().getFilename();
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
}
private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException {
try {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
catch (IllegalStateException e) {
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
}
}
}
package com.dsk.biz.goview.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsk.biz.goview.common.base.BaseController;
import com.dsk.biz.goview.common.bean.AjaxResult;
import com.dsk.biz.goview.common.domain.*;
import com.dsk.biz.goview.config.GoviewProperties;
import com.dsk.biz.goview.mapper.GoviewProjectDataMapper;
import com.dsk.biz.goview.mapper.GoviewProjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 项目表Controller
*
* @author fuce
* @ClassName: GoviewProjectController
* @date 2022-05-18 21:43:25
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/goview/project")
public class GoViewProjectAPIController extends BaseController {
private final GoviewProjectDataMapper projectDataMapper;
private final GoviewProjectMapper projectMapper;
private final GoviewProperties goviewProperties;
@GetMapping("/list")
public ResultTable list(Tablepar tablepar, GoviewProject goviewProject) {
Page page = new Page(tablepar.getPage(), tablepar.getLimit());
Page result = projectMapper.selectPage(page, Wrappers.query(goviewProject));
ResultTable resultTable = pageTable(result.getRecords(), result.getTotal());
resultTable.setCode(200);
return resultTable;
}
/**
* 新增保存
* @param
* @return
*/
@PostMapping("/create")
public AjaxResult add(@RequestBody GoviewProject goviewProject) {
projectMapper.insert(goviewProject);
return AjaxResult.successData(200, goviewProject).put("msg", "创建成功");
}
/**
* 项目表删除
* @param ids
* @return
*/
@DeleteMapping("/delete")
public AjaxResult delete(String ids) {
projectMapper.deleteById(ids);
return success();
}
@PostMapping("/edit")
public AjaxResult editSave(@RequestBody GoviewProject goviewProject) {
projectMapper.updateById(goviewProject);
return success();
}
@PostMapping("/rename")
public AjaxResult rename(@RequestBody GoviewProject goviewProject) {
projectMapper.updateById(goviewProject);
return success();
}
// 发布/取消项目状态
@PutMapping("/publish")
@ResponseBody
public AjaxResult updateVisible(@RequestBody GoviewProject goviewProject) {
projectMapper.updateById(goviewProject);
return success();
}
/**
* 获取项目存储数据
* @param id 项目id
* @param mmap
* @return
*/
@GetMapping("/getData")
public AjaxResult getData(String projectId, ModelMap map) {
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build());
GoviewProject goviewProject = projectMapper.selectById(projectId);
if (goviewProject == null) {
return AjaxResult.successData(200, null).put("msg", "无数据");
}
List<GoviewProjectData> goviewProjectDataList = projectDataMapper
.selectList(Wrappers.<GoviewProjectData>lambdaQuery().eq(GoviewProjectData::getProjectId, projectId));
if (CollUtil.isNotEmpty(goviewProjectDataList)) {
goviewProject.setContent(goviewProjectDataList.get(0).getContent());
return AjaxResult.successData(200, goviewProject).put("msg", "获取成功");
}
return AjaxResult.successData(200, null).put("msg", "无数据");
}
@PostMapping("/save/data")
public AjaxResult saveData(GoviewProjectData data) {
boolean exists = projectDataMapper
.exists(Wrappers.<GoviewProjectData>lambdaQuery().eq(GoviewProjectData::getProjectId, data.getProjectId()));
if (exists) {
projectDataMapper.update(data,
Wrappers.<GoviewProjectData>lambdaQuery().eq(GoviewProjectData::getProjectId, data.getProjectId()));
}
else {
projectDataMapper.insert(data);
}
return AjaxResult.success("操作成功");
}
/**
* 模拟请求
* @return
*/
@PostMapping("/magicHttp")
public AjaxResult magicHttp(@RequestBody MagicHttp magicHttp) {
return AjaxResult.successNullData("参数异常为null");
}
/**
* 上传文件
* @param file 文件流对象
* @return
* @throws Exception
*/
@PostMapping("/upload")
@ResponseBody
public AjaxResult upload(@RequestBody MultipartFile object) throws IOException {
File dest = new File(goviewProperties.getImgPath() + object.getOriginalFilename());
object.transferTo(dest);
Map<String, String> map = new HashMap(4);
String url;
if (StrUtil.isNotBlank(goviewProperties.getHost())) {
url = goviewProperties.getHost() + goviewProperties.getGatewayPrefix() + "/api/project/get-file/"
+ object.getOriginalFilename();
}
else {
url = goviewProperties.getGatewayPrefix() + "/api/project/get-file/" + object.getOriginalFilename();
}
map.put("link", url);
return AjaxResult.successData(200, map);
}
/**
* 文件获取
* @param fileName 文件名
*/
@GetMapping("/get-file/{fileName}")
public ResponseEntity<byte[]> getFile(@PathVariable String fileName) {
HttpHeaders headers = new HttpHeaders();
// 通知浏览器以下载文件方式打开
ContentDisposition contentDisposition = ContentDisposition.builder("attachment").filename(fileName).build();
headers.setContentDisposition(contentDisposition);
try {
return new ResponseEntity<>(
FileCopyUtils.copyToByteArray(new File(goviewProperties.getImgPath() + fileName)), headers,
HttpStatus.OK);
}
catch (IOException e) {
log.warn(e.getLocalizedMessage());
}
return null;
}
}
package com.dsk.biz.goview.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.dsk.biz.goview.common.bean.AjaxResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import static com.dsk.biz.goview.common.bean.AjaxResult.success;
/**
* @author lengleng
* @date 2022/5/21
*/
@Slf4j
@Controller
@RequestMapping
@RequiredArgsConstructor
public class GoviewPageController {
@SaIgnore
@GetMapping({ "/", "/chart/**", "/project/**" })
public String index() {
return "index";
}
@GetMapping("/api/goview/sys/getOssInfo")
@ResponseBody
public AjaxResult getOssInfo() {
return success();
}
}
package com.dsk.biz.goview.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsk.biz.goview.common.domain.GoviewProjectData;
import org.apache.ibatis.annotations.Mapper;
/**
* @author lengleng
* @date 2023/4/4
*/
@Mapper
public interface GoviewProjectDataMapper extends BaseMapper<GoviewProjectData> {
}
package com.dsk.biz.goview.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsk.biz.goview.common.domain.GoviewProject;
import org.apache.ibatis.annotations.Mapper;
/**
* @author lengleng
* @date 2023/4/4
*/
@Mapper
public interface GoviewProjectMapper extends BaseMapper<GoviewProject> {
}
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<script>self["MonacoEnvironment"] = (function (paths) {
return {
globalAPI: false,
getWorkerUrl : function (moduleId, label) {
var result = paths[label];
if (/^((http:)|(https:)|(file:)|(\/\/))/.test(result)) {
var currentUrl = String(window.location);
var currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length);
if (result.substring(0, currentOrigin.length) !== currentOrigin) {
var js = '/*' + label + '*/importScripts("' + result + '");';
var blob = new Blob([js], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
}
return result;
}
};
})({
"editorWorkerService": "/api/gv/monacoeditorwork/editor.worker.bundle.js",
"typescript": "/api/gv/monacoeditorwork/ts.worker.bundle.js",
"json": "/api/gv/monacoeditorwork/json.worker.bundle.js",
"html": "/api/gv/monacoeditorwork/html.worker.bundle.js",
"javascript": "/api/gv/monacoeditorwork/ts.worker.bundle.js",
"handlebars": "/api/gv/monacoeditorwork/html.worker.bundle.js",
"razor": "/api/gv/monacoeditorwork/html.worker.bundle.js"
});</script>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta name="description" content="GoView 是高效、高性能的拖拽式低代码数据可视化开发平台,将页面元素封装为基础组件,无需编写代码即可完成业务需求。">
<meta name="keywords" content="GoView,goview,低代码,可视化">
<meta name="author" content="奔跑的面条,面条">
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<link rel="icon" href="./favicon.ico" />
<title>GoView</title>
<script type="module" crossorigin src="/api/gv/static/js/index-ebdecea3.js"></script>
<link rel="stylesheet" href="/api/gv/static/css/index-9c2eb289.css">
</head>
<body>
<div id="appProvider" style="display: none;"></div>
<div id="app">
<div class="first-loading-wrp">
<div class="loading-wrp">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
</body>
</html>
......@@ -22,6 +22,7 @@
<modules>
<module>dsk-biz-api</module>
<module>dsk-biz-bi</module>
</modules>
<build>
......
......@@ -39,6 +39,7 @@
"dependencies": {
"@cell-x/el-table-sticky": "^1.0.2",
"@riophae/vue-treeselect": "0.4.0",
"@vue/composition-api": "^1.7.2",
"axios": "0.24.0",
"clipboard": "2.0.8",
"core-js": "^3.32.2",
......@@ -56,6 +57,7 @@
"js-cookie": "3.0.1",
"js-md5": "^0.7.3",
"jsencrypt": "3.0.0-rc.1",
"json-editor-vue": "^0.11.0",
"nprogress": "0.2.0",
"quill": "1.3.7",
"screenfull": "5.0.2",
......
......@@ -141,3 +141,12 @@ export function peojectTop(data) {
data: data
})
}
// 集团成员导出
export function memberListExport(data) {
return request({
url: '/combine/info/memberList/export',
method: 'post',
data: data
})
}
......@@ -178,6 +178,51 @@ export const searchOwnerUnitListApi = (data) => request({
method: 'post',
data
});
// 查城投平台导出
export const uipSerachExport = (data) => request({
url: '/enterprise/uipSerach/export',
method: 'post',
data
});
// 企业基本信息导出
export const infoExport = (data) => request({
url: '/enterprise/info/export',
method: 'post',
data
});
// 企业资质导出
export const aptitudeExport = (data) => request({
url: '/enterprise/aptitude/export',
method: 'post',
data
});
export default { label, centralEnterprsesocialPage, centralEnterprselocalPage, centralEnterprseChildPage, centralEnterprsesocial, centralEnterprselocal, centralEnterprseChild, searchCentralEnterprse, centralEnterprse, region, aptitudeCode, personCert, searchDic, regionWebList, uipGroupData, uipSerach, claim, cancelClaim, enterprisePage, infoHeader, historyClaim, customerStatus, searchOwnerUnitListApi };
export default {
label,
centralEnterprsesocialPage,
centralEnterprselocalPage,
centralEnterprseChildPage,
centralEnterprsesocial,
centralEnterprselocal,
centralEnterprseChild,
searchCentralEnterprse,
centralEnterprse,
region,
aptitudeCode,
personCert,
searchDic,
regionWebList,
uipGroupData,
uipSerach,
claim,
cancelClaim,
enterprisePage,
infoHeader,
historyClaim,
customerStatus,
searchOwnerUnitListApi,
uipSerachExport,
infoExport,
aptitudeExport
};
import request from '@/utils/request'
import request from '@/utils/request';
//新增租户套餐
export function addTenantPackage(param) {
return request({
url: '/system/tenant/package',
method: 'POST',
data: param
})
});
}
//修改租户套餐
export function saveTenantPackage(param) {
......@@ -13,21 +13,21 @@ export function saveTenantPackage(param) {
url: '/system/tenant/package/',
method: 'PUT',
data: param
})
});
}
//获取租户套餐
export function detailTenantPackage(packageId) {
return request({
url: '/system/tenant/package/'+packageId,
url: '/system/tenant/package/' + packageId,
method: 'get',
})
});
}
//删除租户套餐
export function deleteTenantPackage(packageId) {
return request({
url: '/system/tenant/package/'+packageId,
url: '/system/tenant/package/' + packageId,
method: 'DELETE',
})
});
}
//租户套餐列表
export function getTenantPackage(param) {
......@@ -35,7 +35,7 @@ export function getTenantPackage(param) {
url: '/system/tenant/package/list',
method: 'get',
params: param
})
});
}
//同步企业方案
export function syncTenantPackage(param) {
......@@ -43,7 +43,7 @@ export function syncTenantPackage(param) {
url: '/system/tenant/syncTenantPackage',
method: 'get',
params: param
})
});
}
//租户列表
......@@ -52,15 +52,15 @@ export function getTenantList(param) {
url: '/system/tenant/list',
method: 'get',
params: param
})
});
}
//获取租户详情
export function getTenant(id) {
return request({
url: '/system/tenant/'+id,
url: '/system/tenant/' + id,
method: 'get',
})
});
}
//修改租户
......@@ -68,31 +68,52 @@ export function editTenant(data) {
return request({
url: '/system/tenant/',
method: 'PUT',
data:data,
})
data: data,
});
}
//新增租户
export function saveTenant(data) {
return request({
url: '/system/tenant/',
method: 'POST',
data:data,
})
data: data,
});
}
//删除租户
export function deleteTenant(ids) {
return request({
url: '/system/tenant/'+ids,
url: '/system/tenant/' + ids,
method: 'Delete',
})
});
}
//租户请求企业套餐下拉
export function selectTenant(ids) {
return request({
url: '/system/tenant/package/selectList',
method: 'Get',
})
});
}
/**
* 企业管理新增账号
* @param {object} data
* @returns
*/
export const enterpriseAddAccountApi = (data) => request({
url: "/system/tenant/addTenantAdmin",
method: "post",
data
});
/**
* 租户ID查询大司空超管or租户管理员为其创建的企业管理员和管理员账号数量
* @param {*} tenantId
* @returns
*/
export const getEnterpriseAddAccountCountApi = (tenantId) => request({
url: `/system/user/queryTenantAdminNumCreatedByDSK/${tenantId}`,
method: "get"
})
......@@ -337,6 +337,15 @@ export function getUipIdByCid(param) {
})
}
//城投平台导出
export function urbanInvestmentExport(param) {
return request({
url: '/urbanInvestment/export',
method: 'POST',
data: param
})
}
......
......@@ -230,10 +230,9 @@ let getImportantDetail = function getImportantDetail(param) {
})
}
//项目清单导出
let radarExport = function radarExport(param) {
return request({
url: '/radar/export/important',
url: '/radar/importantPage/export',
method: 'post',
data: param
})
......
......@@ -26,6 +26,16 @@
opacity: 0;
}
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter,
.list-leave-to {
opacity: 0;
transform: translateX(50px);
}
.el-message {
z-index: 3000 !important;
}
......@@ -246,7 +246,7 @@ li {
}
}
.el-input__inner::placeholder {
color: rgba(35, 35, 35, 0.8) !important;
color: rgba(35, 35, 35, 0.4) !important;
}
.el-select .el-input .el-select__caret {
color: #232323;
......@@ -322,14 +322,14 @@ li {
.table-item {
width: 100%;
.el-table {
font-size: 13px;
font-size: 14px;
color: #232323;
th {
font-size: 13px !important;
font-weight: 400 !important;
}
td {
font-size: 13px;
font-size: 14px;
}
.cell {
padding-right: 12px !important;
......
......@@ -329,7 +329,7 @@ select {
.el-icon-caret-bottom:before{
color: rgba(35,35,32,0.4);
}
}
.land_date_picker {
position: absolute !important;
......@@ -762,7 +762,7 @@ select {
.checkbox .el-checkbox__label {
padding-left: 6px;
color: #232323;
color: #606266;
}
.checkbox .checkbox-content .checkbox-content-qx {
......@@ -1171,11 +1171,11 @@ select {
.table-item .el-table tr,
.table-item .el-table td {
font-size: 13px;
font-size: 14px;
}
.table-item-jf .el-table tr,
.table-item-jf .el-table td {
font-size: 13px;
font-size: 14px;
}
......@@ -1220,7 +1220,7 @@ select {
line-height: 16px;
font-weight: 700;
color: #232323;
}
}
.enterprise_contatiner{
}
......@@ -1245,4 +1245,4 @@ select {
.btn-search1{
width: 60px;
}
}
}
......@@ -145,7 +145,8 @@
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
color: #232323;
font-size: 14px;
}
.el-tree-node__content > .el-checkbox {
......
<template>
<div class="dsk-json-editor">
<json-editor-vue class="dsk-json-editor-ins" v-model="modelValue" ref="dskJsonEditor" :mode.sync="mode" :readOnly="readOnly"
@input="jsonChange"></json-editor-vue>
</div>
</template>
<script>
import JsonEditorVue from 'json-editor-vue';
import { jsonEscape, jsonTraversal } from "@/utils";
export default {
name: "dskJsonEditor",
components: {
JsonEditorVue
},
props: {
jsonValue: {
required: true,
type: [Object, String],
default: ""
},
defaultMode: {
required: true,
type: [String],
default: "text"
},
jsonReadOnly: {
required: true,
type: [Boolean],
default: false
}
},
watch: {
jsonValue: {
handler(newValue) {
this.modelValue = newValue;
},
deep: true
}
},
data() {
return {
modelValue: this.jsonValue,
mode: this.defaultMode,
readOnly: this.jsonReadOnly
};
},
//可访问data属性
created() {
},
//计算集
computed: {
},
//方法集
methods: {
validateJson() {
return new Promise((resolve, reject) => {
try {
let isPass = false;
// 验证通过
if (!this.$refs["dskJsonEditor"].jsonEditor.validate()) {
isPass = true;
let jsonText = this.modelValue;
// 初始默认对象
if (Object.prototype.toString.call(jsonText) == "[object Object]") {
// 对象转为json字符串
jsonText = JSON.stringify(jsonText);
}
// 转换字符串 去除空格 换行符
jsonText = jsonEscape(jsonText);
// 特殊字符识别编码
jsonText = JSON.stringify(jsonTraversal(JSON.parse(jsonText)));
console.log(jsonText);
return resolve({ isPass, value: jsonText });
}
resolve({ isPass });
} catch (error) {
console.log(error);
reject(error);
}
});
},
jsonChange(e) {
try {
this.$emit("jsonChange", e);
} catch (error) {
console.log(error);
}
}
},
}
</script>
<style lang="scss" scoped>
.dsk-json-editor {
width: 100%;
height: 100%;
box-sizing: border-box;
::v-deep .dsk-json-editor-ins {
width: 100%;
height: 100%;
.jsoneditor-vue {
width: 100%;
height: 100%;
}
.jsoneditor-poweredBy {
display: none;
}
}
}
</style>
......@@ -3,9 +3,9 @@
<div class="table-item">
<el-table v-if="tableDataTotal>0" class="fixed-table" :class="headerFixed ? 'headerFixed':''" v-loading="tableLoading" :data="tableData"
element-loading-text="Loading" ref="tableRef" border fit highlight-current-row v-sticky-header.always="stickyHeader"
:default-sort="defaultSort?defaultSort:{}" @sort-change="sortChange" @selection-change="selectionChange">
:default-sort="defaultSort?defaultSort:{}" @sort-change="sortChange" @selection-change="selectionChange" :cell-class-name="cellClassName" :cell-style="cellStyle">
<el-table-column type="selection" :width="needSelection.width ? needSelection.width : '38px'" v-if="needSelection.flag"
:fixed="needSelection.fixed" :align="needSelection.align">
:fixed="needSelection.fixed" :align="needSelection.align" :show-overflow-tooltip="needSelection.showOverflowTooltip">
</el-table-column>
<el-table-column v-if="isIndex" label="序号" :width="flexWidth(tableData)" align="left" :fixed="indexFixed" :resizable="false">
<template slot-scope="scope">{{ queryParams.pageNum * queryParams.pageSize - queryParams.pageSize + scope.$index + 1 }}</template>
......@@ -69,9 +69,18 @@ export default {
flag: false,
width: "39px",
fixed: false,
align: "left"
align: "left",
showOverflowTooltip: false
})
},
cellClassName: {
type: Function,
default: () => () => { }
},
cellStyle: {
type: Function,
default: () => () => { }
},
// 吸顶偏移量
stickyHeader: {
type: Object,
......
......@@ -3,7 +3,7 @@
<!-- 展开 -->
<template v-if="!isCollapse">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path,onlyOneChild.query)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="sideIcon(item, onlyOneChild)" :title="onlyOneChild.meta.title" />
</el-menu-item>
......@@ -13,31 +13,20 @@
<template slot="title">
<item v-if="item.meta" :icon="sideIcon(item)" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
:active-menu="activeMenu"
class="nest-menu"
/>
<sidebar-item v-for="child in item.children" :key="child.path" :is-nest="true" :item="child" :base-path="resolvePath(child.path,child.query)"
:active-menu="activeMenu" class="nest-menu" />
</el-submenu>
</template>
<!-- 收起 -->
<template v-else>
<div v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow" class="side-retract">
<el-popover
placement="right-start"
popper-class="side-popover side-one-popover"
:visible-arrow="true"
trigger="hover"
:disabled="onlyOneChild.meta||item.meta?false:true"
>
<div v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow"
class="side-retract">
<el-popover placement="right-start" popper-class="side-popover side-one-popover" :visible-arrow="true" trigger="hover"
:disabled="onlyOneChild.meta||item.meta?false:true">
<div class="side-container">
<div class="side-title">
<!--<app-link v-if="onlyOneChild.meta || item.meta" :to="resolvePath(onlyOneChild.path || item.path)">-->
<app-link :to="resolvePath(onlyOneChild.path || item.path)">
<app-link :to="resolvePath(onlyOneChild.path || item.path,onlyOneChild.query)">
{{ onlyOneChild.meta.title || item.meta.title }}
</app-link>
......@@ -47,18 +36,12 @@
</el-popover>
</div>
<div v-else class="side-retract">
<el-popover
placement="right-start"
popper-class="side-popover"
:visible-arrow="true"
trigger="hover"
:disabled="item.meta?false:true"
>
<el-popover placement="right-start" popper-class="side-popover" :visible-arrow="true" trigger="hover" :disabled="item.meta?false:true">
<div class="side-container">
<div class="side-title">{{ item.meta.title }}</div>
<ul class="side-list">
<li v-for="child in item.children" :key="child.path">
<app-link v-if="child.meta" :to="resolvePath(child.path)">
<app-link v-if="child.meta" :to="resolvePath(child.path,child.query)">
{{ child.meta.title }}
</app-link>
</li>
......@@ -72,11 +55,11 @@
</template>
<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
import path from 'path';
import { isExternal } from '@/utils/validate';
import Item from './Item';
import AppLink from './Link';
import FixiOSBug from './FixiOSBug';
export default {
name: 'SidebarItem',
......@@ -106,42 +89,42 @@ export default {
}
},
data() {
this.onlyOneChild = null
return {}
this.onlyOneChild = null;
return {};
},
computed: {
sideIcon() {
return function(item, onlyOneChild) {
let icon = ''
return function (item, onlyOneChild) {
let icon = '';
if (onlyOneChild) {
if(onlyOneChild.meta.icon || (item.meta && item.meta.icon&&item.meta.icon!='#')){
icon = onlyOneChild.meta.icon || (item.meta && item.meta.icon)
if (onlyOneChild.meta.icon || (item.meta && item.meta.icon && item.meta.icon != '#')) {
icon = onlyOneChild.meta.icon || (item.meta && item.meta.icon);
}
let tempPath = ''
let tempPath = '';
if (onlyOneChild.path) {
tempPath = this.resolvePath(onlyOneChild.path)
tempPath = this.resolvePath(onlyOneChild.path);
if (this.activeMenu === tempPath&&onlyOneChild.meta.icon!='#') {
icon = onlyOneChild.meta.icon+'s'
if (this.activeMenu === tempPath && onlyOneChild.meta.icon != '#') {
icon = onlyOneChild.meta.icon + 's';
}
} else {
tempPath = this.resolvePath(item.path).substring(0, this.resolvePath(item.path).lastIndexOf('/'))
if (this.activeMenu === tempPath&&item.meta.icon!='#') {
icon = item.meta.icon+'s'
tempPath = this.resolvePath(item.path).substring(0, this.resolvePath(item.path).lastIndexOf('/'));
if (this.activeMenu === tempPath && item.meta.icon != '#') {
icon = item.meta.icon + 's';
}
}
} else {
if(item.meta && item.meta.icon&&item.meta.icon!='#'){
icon = item.meta.icon
if (item.meta && item.meta.icon && item.meta.icon != '#') {
icon = item.meta.icon;
}
const tempPath = this.activeMenu.substring(0, this.activeMenu.indexOf('/', this.activeMenu.indexOf('/') + 1))
if (this.resolvePath(item.path) === tempPath&&item.meta.icon!='#') {
icon = item.meta.icon+'s'
const tempPath = this.activeMenu.substring(0, this.activeMenu.indexOf('/', this.activeMenu.indexOf('/') + 1));
if (this.resolvePath(item.path) === tempPath && item.meta.icon != '#') {
icon = item.meta.icon + 's';
}
}
return icon
}
return icon;
};
}
},
methods: {
......@@ -151,48 +134,52 @@ export default {
}
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
return false;
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
this.onlyOneChild = item;
return true;
}
})
});
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
return true;
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
return true
this.onlyOneChild = { ...parent, path: '', noShowingChildren: true };
return true;
}
return false
return false;
},
resolvePath(routePath, routeQuery) {
if (isExternal(routePath)) {
return routePath
return routePath;
}
if (isExternal(this.basePath)) {
return this.basePath
return this.basePath;
}
if (routeQuery) {
let query = JSON.parse(routeQuery);
return { path: path.resolve(this.basePath, routePath), query: query }
let query = routeQuery;
for (const key in query) {
if (query.hasOwnProperty(key)) {
Object.prototype.toString.call(query[key]) == "[object Object]" ? query[key] = JSON.stringify(query[key]) : null;
}
}
return { path: path.resolve(this.basePath, routePath), query: query };
}
return path.resolve(this.basePath, routePath)
return path.resolve(this.basePath, routePath);
}
}
}
</script>
<style lang="scss">
.side-popover.el-popper {
.popper__arrow{
.side-popover.el-popper {
.popper__arrow {
display: block !important;
}
}
}
</style>
......@@ -73,12 +73,9 @@ export default {
};
},
computed: {
visitedViews: {
get() {
visitedViews() {
return this.$store.state.tagsView.visitedViews;
},
set() { }
},
iconName() {
return function (val) {
let svgIcon = val.meta && val.meta.icon, currentIcon = '';
......@@ -105,7 +102,6 @@ export default {
},
watch: {
$route() {
// console.log(this.$route);
this.addTags();
this.moveToCurrentTag();
this.getviews();
......@@ -118,10 +114,11 @@ export default {
}
},
},
mounted() {
created() {
this.$nextTick(() => {
this.initTags();
this.addTags();
// this.getviews()
});
},
methods: {
getviews() {
......
import Vue from 'vue';
import VCA from '@vue/composition-api' //composition APi
import Cookies from 'js-cookie';
......@@ -8,6 +9,7 @@ import './assets/styles/element-variables.scss';
import "@/assets/styles/common.css";
import '@/assets/styles/index.scss'; // global css
import '@/assets/styles/ruoyi.scss'; // ruoyi css
import App from './App';
import store from './store';
import router from './router';
......@@ -22,6 +24,7 @@ import './permission'; // permission control
import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
// 分页组件
import Pagination from "@/components/Pagination";
// 自定义表格工具组件
......@@ -61,6 +64,7 @@ Vue.component('FileUpload', FileUpload);
Vue.component('ImageUpload', ImageUpload);
Vue.component('ImagePreview', ImagePreview);
Vue.use(VCA);
Vue.use(horizontalScroll);
Vue.use(elTableSticky);
Vue.use(directive);
......
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isRelogin } from '@/utils/request'
import router from './router';
import store from './store';
import { Message } from 'element-ui';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { getToken } from '@/utils/auth';
import { isRelogin } from '@/utils/request';
NProgress.configure({ showSpinner: false })
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register']
const whiteList = ['/login', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()
NProgress.start();
if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
// tab页签title
const { tabTitle, url } = to.query;
if (tabTitle) to.meta.title = decodeURIComponent(tabTitle);
if (!tabTitle && to.meta.isSubSystem && url) to.meta.title = decodeURIComponent(url);
to.meta.title && store.dispatch('settings/setTitle', to.meta.title);
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
next({ path: '/' });
NProgress.done();
} else {
if (store.getters.roles.length === 0) {
isRelogin.show = true
isRelogin.show = true;
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
isRelogin.show = false
isRelogin.show = false;
store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
router.addRoutes(accessRoutes); // 动态添加可访问路由表
next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
});
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
sessionStorage.removeItem('views')
next({ path: '/' })
})
})
Message.error(err);
sessionStorage.removeItem('views');
next({ path: '/' });
});
});
} else {
next()
next();
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
next();
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
next(`/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
NProgress.done();
}
}
})
});
router.afterEach(() => {
NProgress.done()
})
NProgress.done();
});
import store from '@/store'
import store from '@/store';
import router from '@/router';
import { paramsToQuery } from "@/utils/";
export default {
// 刷新当前tab页签
......@@ -15,12 +16,12 @@ export default {
});
}
return store.dispatch('tagsView/delCachedView', obj).then(() => {
const { path, query } = obj
const { path, query } = obj;
router.replace({
path: '/redirect' + path,
query: query
})
})
});
});
},
// 关闭当前tab页签,打开新页签
closeOpenPage(obj) {
......@@ -33,9 +34,9 @@ export default {
closePage(obj) {
if (obj === undefined) {
return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => {
const latestView = visitedViews.slice(-1)[0]
const latestView = visitedViews.slice(-1)[0];
if (latestView) {
return router.push(latestView.fullPath)
return router.push(latestView.fullPath);
}
return router.push('/');
});
......@@ -59,13 +60,16 @@ export default {
return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
},
// 添加tab页签
openPage(title, url, params) {
var obj = { path: url, meta: { title: title } }
store.dispatch('tagsView/addView', obj);
async openPage(title, url, params) {
const obj = { path: url, fullPath: url, query: params, meta: { title: title } };
if (params && Object.keys(params).length) {
obj.fullPath = `${obj.path}${paramsToQuery(params) ? "?" + paramsToQuery(params) : ""}`;
}
await store.dispatch('tagsView/addView', obj);
return router.push({ path: url, query: params });
},
// 修改tab页签
updatePage(obj) {
return store.dispatch('tagsView/updateVisitedView', obj);
}
}
};
import Vue from 'vue'
import Router from 'vue-router'
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router)
Vue.use(Router);
/* Layout */
import Layout from '@/layout'
import Layout from '@/layout';
/**
* Note: 路由配置项
......@@ -28,6 +28,7 @@ import Layout from '@/layout'
}
*/
// 公共路由
export const constantRoutes = [
{
......@@ -70,7 +71,7 @@ export const constantRoutes = [
path: 'index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'index', noCache: true}
meta: { title: '首页', icon: 'index', noCache: true }
}
]
},
......@@ -303,6 +304,7 @@ export const constantRoutes = [
path: '/gzsc/:id',
component: () => import('@/views/detail'),
name: 'detail-gzsc',
meta: { title: "公招市场详情" }
}
]
},
......@@ -552,7 +554,7 @@ export const constantRoutes = [
path: '/biddetail/:id(\\d+)',
component: () => import('@/views/detail/biddetail/index'),
name: 'Biddetail',
meta: { title: '中标业绩详情',icon: 'enterprise'}
meta: { title: '中标业绩详情', icon: 'enterprise' }
}
]
},
......@@ -566,7 +568,7 @@ export const constantRoutes = [
path: '/macro/financing/details/:id(\\d+)',
component: () => import('@/views/macro/financing/details'),
name: 'financingDetails',
meta: { title: '区域专项债详情',icon: 'radar'}
meta: { title: '区域专项债详情', icon: 'radar' }
}
]
},
......@@ -688,8 +690,28 @@ export const constantRoutes = [
}
]
},
]
// 子系统
// {
// path: '',
// redirect: '/subsystem',
// component: Layout,
// hidden: false,
// children: [
// {
// path: 'subsystem',
// hidden: false,
// component: () => import('@/views/subsystem/index'),
// name: 'Subsystem',
// meta: {
// title: '子系统',
// icon: 'index',
// noCache: true,
// isSubSystem: true
// },
// }
// ]
// },
];
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
......@@ -777,22 +799,22 @@ export const dynamicRoutes = [
}
]
}
]
];
// 防止连续点击多次路由报错
let routerPush = Router.prototype.push;
let routerReplace = Router.prototype.replace;
// push
Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(err => err)
}
return routerPush.call(this, location).catch(err => err);
};
// replace
Router.prototype.replace = function push(location) {
return routerReplace.call(this, location).catch(err => err)
}
return routerReplace.call(this, location).catch(err => err);
};
export default new Router({
mode: 'history', // 去掉url中的#
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
});
import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'
import auth from '@/plugins/auth';
import router, { constantRoutes, dynamicRoutes } from '@/router';
import { getRouters } from '@/api/menu';
import Layout from '@/layout/index';
import ParentView from '@/components/ParentView';
import InnerLink from '@/layout/components/InnerLink';
const permission = {
state: {
......@@ -15,17 +15,17 @@ const permission = {
},
mutations: {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
state.addRoutes = routes;
state.routes = constantRoutes.concat(routes);
},
SET_DEFAULT_ROUTES: (state, routes) => {
state.defaultRoutes = constantRoutes.concat(routes)
state.defaultRoutes = constantRoutes.concat(routes);
},
SET_TOPBAR_ROUTES: (state, routes) => {
state.topbarRouters = routes
state.topbarRouters = routes;
},
SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes
state.sidebarRouters = routes;
},
},
actions: {
......@@ -34,100 +34,108 @@ const permission = {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const sdata = JSON.parse(JSON.stringify(res.data));
const rdata = JSON.parse(JSON.stringify(res.data));
const sidebarRoutes = filterAsyncRouter(sdata);
const rewriteRoutes = filterAsyncRouter(rdata, false, true);
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true });
router.addRoutes(asyncRoutes);
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
resolve(rewriteRoutes)
})
})
commit('SET_ROUTES', rewriteRoutes);
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes));
commit('SET_DEFAULT_ROUTES', sidebarRoutes);
commit('SET_TOPBAR_ROUTES', sidebarRoutes);
resolve(rewriteRoutes);
});
});
}
}
}
};
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
return asyncRouterMap.filter(route => {
if (type && route.children) {
route.children = filterChildren(route.children)
route.children = filterChildren(route.children);
}
// query默认参数转换
if (route.query) {
try {
route.query = JSON.parse(route.query);
} catch (error) {
}
}
if (route.component) {
// Layout ParentView 组件特殊处理
if (route.component === 'Layout') {
route.component = Layout
route.component = Layout;
} else if (route.component === 'ParentView') {
route.component = ParentView
route.component = ParentView;
} else if (route.component === 'InnerLink') {
route.component = InnerLink
route.component = InnerLink;
} else {
route.component = loadView(route.component)
route.component = loadView(route.component);
}
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
route.children = filterAsyncRouter(route.children, route, type);
} else {
delete route['children']
delete route['redirect']
delete route['children'];
delete route['redirect'];
}
return true
})
return true;
});
}
function filterChildren(childrenMap, lastRouter = false) {
var children = []
var children = [];
childrenMap.forEach((el, index) => {
if (el.children && el.children.length) {
if (el.component === 'ParentView' && !lastRouter) {
el.children.forEach(c => {
c.path = el.path + '/' + c.path
c.path = el.path + '/' + c.path;
if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c))
return
children = children.concat(filterChildren(c.children, c));
return;
}
children.push(c)
})
return
children.push(c);
});
return;
}
}
if (lastRouter) {
el.path = lastRouter.path + '/' + el.path
el.path = lastRouter.path + '/' + el.path;
}
children = children.concat(el)
})
return children
children = children.concat(el);
});
return children;
}
// 动态路由遍历,验证是否具备权限
export function filterDynamicRoutes(routes) {
const res = []
const res = [];
routes.forEach(route => {
if (route.permissions) {
if (auth.hasPermiOr(route.permissions)) {
res.push(route)
res.push(route);
}
} else if (route.roles) {
if (auth.hasRoleOr(route.roles)) {
res.push(route)
res.push(route);
}
}
})
return res
});
return res;
}
export const loadView = (view) => {
if (process.env.NODE_ENV === 'development') {
return (resolve) => require([`@/views/${view}`], resolve)
return (resolve) => require([`@/views/${view}`], resolve);
} else {
// 使用 import 实现生产环境的路由懒加载
return () => import(`@/views/${view}`)
return () => import(`@/views/${view}`);
}
}
};
export default permission
export default permission;
......@@ -3,227 +3,227 @@ const state = {
visitedViews: [],
cachedViews: [],
iframeViews: []
}
};
const mutations = {
ADD_IFRAME_VIEW: (state, view) => {
if (state.iframeViews.some(v => v.fullPath === view.fullPath)) return
if (state.iframeViews.some(v => v.fullPath === view.fullPath)) return;
state.iframeViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
);
},
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.fullPath === view.fullPath)) return
if (state.visitedViews.some(v => v.fullPath === view.fullPath)) return;
state.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
);
},
ADD_CACHED_VIEW: (state, view) => {
if (state.cachedViews.includes(view.name)) return
if (state.cachedViews.includes(view.name)) return;
if (view.meta && !view.meta.noCache) {
state.cachedViews.push(view.name)
state.cachedViews.push(view.name);
}
},
DEL_VISITED_VIEW: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.fullPath === view.fullPath) {
state.visitedViews.splice(i, 1)
break
state.visitedViews.splice(i, 1);
break;
}
}
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath)
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath);
},
DEL_IFRAME_VIEW: (state, view) => {
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath)
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath);
},
DEL_CACHED_VIEW: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
const index = state.cachedViews.indexOf(view.name);
index > -1 && state.cachedViews.splice(index, 1);
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.fullPath === view.fullPath
})
state.iframeViews = state.iframeViews.filter(item => item.fullPath === view.fullPath)
return v.meta.affix || v.fullPath === view.fullPath;
});
state.iframeViews = state.iframeViews.filter(item => item.fullPath === view.fullPath);
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
const index = state.cachedViews.indexOf(view.name);
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
state.cachedViews = state.cachedViews.slice(index, index + 1);
} else {
state.cachedViews = []
state.cachedViews = [];
}
},
DEL_ALL_VISITED_VIEWS: state => {
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
state.iframeViews = []
const affixTags = state.visitedViews.filter(tag => tag.meta.affix);
state.visitedViews = affixTags;
state.iframeViews = [];
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
state.cachedViews = [];
},
UPDATE_VISITED_VIEW: (state, view) => {
for (let v of state.visitedViews) {
if (v.fullPath === view.fullPath) {
v = Object.assign(v, view)
break
v = Object.assign(v, view);
break;
}
}
},
DEL_RIGHT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath)
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath);
if (index === -1) {
return
return;
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx <= index || (item.meta && item.meta.affix)) {
return true
return true;
}
const i = state.cachedViews.indexOf(item.name)
const i = state.cachedViews.indexOf(item.name);
if (i > -1) {
state.cachedViews.splice(i, 1)
state.cachedViews.splice(i, 1);
}
if(item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath)
state.iframeViews.splice(fi, 1)
if (item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath);
state.iframeViews.splice(fi, 1);
}
return false
})
return false;
});
},
DEL_LEFT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath)
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath);
if (index === -1) {
return
return;
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx >= index || (item.meta && item.meta.affix)) {
return true
return true;
}
const i = state.cachedViews.indexOf(item.name)
const i = state.cachedViews.indexOf(item.name);
if (i > -1) {
state.cachedViews.splice(i, 1)
state.cachedViews.splice(i, 1);
}
if(item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath)
state.iframeViews.splice(fi, 1)
if (item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath);
state.iframeViews.splice(fi, 1);
}
return false
})
return false;
});
}
}
};
const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
dispatch('addVisitedView', view);
dispatch('addCachedView', view);
},
addIframeView({ commit }, view) {
commit('ADD_IFRAME_VIEW', view)
commit('ADD_IFRAME_VIEW', view);
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
commit('ADD_VISITED_VIEW', view);
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
commit('ADD_CACHED_VIEW', view);
},
delView({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delVisitedView', view)
dispatch('delCachedView', view)
dispatch('delVisitedView', view);
dispatch('delCachedView', view);
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
});
});
},
delVisitedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_VISITED_VIEW', view)
resolve([...state.visitedViews])
})
commit('DEL_VISITED_VIEW', view);
resolve([...state.visitedViews]);
});
},
delIframeView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_IFRAME_VIEW', view)
resolve([...state.iframeViews])
})
commit('DEL_IFRAME_VIEW', view);
resolve([...state.iframeViews]);
});
},
delCachedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
commit('DEL_CACHED_VIEW', view);
resolve([...state.cachedViews]);
});
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delOthersVisitedViews', view)
dispatch('delOthersCachedViews', view)
dispatch('delOthersVisitedViews', view);
dispatch('delOthersCachedViews', view);
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
});
});
},
delOthersVisitedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
commit('DEL_OTHERS_VISITED_VIEWS', view);
resolve([...state.visitedViews]);
});
},
delOthersCachedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_CACHED_VIEWS', view)
resolve([...state.cachedViews])
})
commit('DEL_OTHERS_CACHED_VIEWS', view);
resolve([...state.cachedViews]);
});
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delAllVisitedViews', view)
dispatch('delAllCachedViews', view)
dispatch('delAllVisitedViews', view);
dispatch('delAllCachedViews', view);
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
});
});
},
delAllVisitedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_VISITED_VIEWS')
resolve([...state.visitedViews])
})
commit('DEL_ALL_VISITED_VIEWS');
resolve([...state.visitedViews]);
});
},
delAllCachedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_CACHED_VIEWS')
resolve([...state.cachedViews])
})
commit('DEL_ALL_CACHED_VIEWS');
resolve([...state.cachedViews]);
});
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
commit('UPDATE_VISITED_VIEW', view);
},
delRightTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_RIGHT_VIEWS', view)
resolve([...state.visitedViews])
})
commit('DEL_RIGHT_VIEWS', view);
resolve([...state.visitedViews]);
});
},
delLeftTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_LEFT_VIEWS', view)
resolve([...state.visitedViews])
})
commit('DEL_LEFT_VIEWS', view);
resolve([...state.visitedViews]);
});
},
}
};
export default {
namespaced: true,
state,
mutations,
actions
}
};
/*
* @Author: thy
* @Date: 2023-11-08 09:28:17
* @LastEditors: thy
* @LastEditTime: 2023-11-17 09:36:01
* @Description: file content
* @FilePath: \dsk-operate-ui\src\utils\iframeTools.js
*/
import { dskAccessToken } from '@/api/common';
import { getUrlSearchQuery, isUrl, paramsToQuery } from "@/utils/";
import { Message } from "element-ui";
/**
* iframe嵌入参数处理
*/
class IframeTools {
queryParams = {};
pluginDomain = "";
subSystemIframe = null;
refreshTimer = null;
count = 0;
authToken = "";
origin = location.origin;
isOuter = false;
/**
* 插件域名地址
* @param {string} pluginDomain 默认当前环境变量VUE_APP_SUB_SYSTEM_ADDRESS
* @param {HTMLIFrameElement} subSystemIframe 子系统iframe dom节点
* @returns
*/
constructor(subSystemIframe, pluginDomain = process.env.VUE_APP_SUB_SYSTEM_ADDRESS) {
try {
const query = getUrlSearchQuery();
if (!query.url) return Message.warning("缺少子系统目标地址");
// 传入的iframeUrl不是一个合法地址
if (!isUrl(pluginDomain)) return Message.warning("子系统源地址不合法");
// 未获取到子系统节点
if (!subSystemIframe) return Message.warning("未获取到子系统节点");
this.queryParams = query;
this.pluginDomain = pluginDomain;
this.subSystemIframe = subSystemIframe;
this.isOuter = query.isOuter && typeof JSON.parse(query.isOuter) == "boolean" ? JSON.parse(query.isOuter) : false;
// 是一个合法地址 初始化 先替换域名地址 再获取令牌并 拼接
this.init();
} catch (error) {
throw new Error(error);
}
}
/**
* 初始化类
*/
async init() {
try {
// 不是合法url的情况下需要拼接完整路径 例如path /xxxx/xxx
!isUrl(this.queryParams.url) ? this.queryParams.url = `${this.pluginDomain}${this.queryParams.url}` : null;
// 获取到子系统加载地址query参数
const subSystemParams = getUrlSearchQuery(this.queryParams.url);
// 获取子系统path
const subSystemUrl = new URL(this.queryParams.url);
// 以环境文件地址为准 拼接子系统查询参数
let url = this.isOuter ? this.queryParams.url : `${this.pluginDomain}${subSystemUrl.pathname == "/" ? "" : subSystemUrl.pathname}`;
// 子系统地址带有查询参数 处理
Object.keys(subSystemParams).length ? url = `${url}?${paramsToQuery(subSystemParams)}` : null;
// 获取授权 token
const { accessToken, expire } = await this.getSubSystemToken();
// 拼接授权地址
if (accessToken) {
this.authToken = accessToken;
const query = {
initTime: new Date().valueOf(),
ak: accessToken,
uid: accessToken,
origin: this.origin
};
url = `${url}${paramsToQuery(query) ? "?" + paramsToQuery(query) : ""}`;
this.queryParams.url = url;
console.log(this.queryParams.url);
// 倒计时刷新token 正常误差10s 提前获取
this.setTokenRefresh(expire * 1000 - 1000 * 10);
}
} catch (error) {
console.log(error);
Message.warning(error.message ? error.message : (typeof error == "string") ? error : "子系统初始化错误");
}
}
/**
* 获取子系统token
*/
async getSubSystemToken() {
try {
const result = await dskAccessToken();
if (result.code == 200) {
return result.data;
}
throw new Error("子系统获取授权失败");
} catch (error) {
throw error;
}
}
/**
* 根据服务端返回过期时间刷新token有效期
*/
setTokenRefresh(expire) {
if (!expire) throw new Error("令牌无有效的刷新时间");
return new Promise((resolve, reject) => {
// 只允许出现一个定时器实例状态
this.clearRefreshTimer();
this.refreshTimer = setTimeout(async () => {
const result = await this.getSubSystemToken();
if (result.accessToken) {
this.count = 0;
this.authToken = result.accessToken;
this.setTokenRefresh(result.expire);
resolve(result);
} else {
// 请求失败进行重试 清理定时器
this.clearRefreshTimer();
// 尝试最多3次刷新 重新调取接口
while (this.count < 3) {
// 重试次数大于等于三次 停止刷新
if (this.count >= 3) {
return reject("子系统令牌刷新失败,请稍后重试");
}
this.count++;
Message.warning(`授权失败,正在尝试第 ${this.count} 次刷新令牌,请勿进行操作`);
const refreshAuth = await this.getSubSystemToken();
if (refreshAuth.accessToken) {
this.count = 0;
this.authToken = refreshAuth.accessToken;
this.setTokenRefresh(refreshAuth.expire);
resolve(refreshAuth);
}
}
}
}, expire);
});
}
clearRefreshTimer() {
clearTimeout(this.refreshTimer);
this.refreshTimer = null;
}
}
export default IframeTools;
\ No newline at end of file
import { Message } from "element-ui";
import { parseTime } from './ruoyi';
/**
......@@ -431,8 +432,7 @@ export const paramsToQuery = (query) => {
searchStrArray.push(`${key}=${decodeURIComponent(value)}`);
}
});
searchStrArray = searchStrArray.join("&");
return searchStr;
return searchStrArray.join("&");
} catch (error) {
console.log(error);
}
......@@ -457,6 +457,136 @@ export const searchTextToQuery = (text) => {
}
};
/**
* 验证链接是否是url
* @param {string} url
* @returns
*/
export function isUrl(url) {
return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*[\u4e00-\u9fa5\w]*)$/.test(url);
}
// 对查询关键字中的特殊字符进行编码
export function encodeSearchKey(key) {
const encodeArr = [{
code: '%',
encode: '%25'
}, {
code: '?',
encode: '%3F'
}, {
code: '#',
encode: '%23'
}, {
code: '&',
encode: '%26'
}, {
code: '=',
encode: '%3D'
}];
return key.replace(/[%?#&=]/g, ($, index, str) => {
for (const k of encodeArr) {
if (k.code === $) {
return k.encode;
}
}
});
}
/**
* 去除json 换行空格符号
* @param {string} str
* @returns
*/
export function jsonEscape(str) {
return str.replace(/(\r\n|\n|\r)/gm, "");
}
/**
* json递归特殊参数处理
* @param {object} target
*/
export function jsonTraversal(target, decode = false) {
try {
if (Object.prototype.toString.call(target) != "[object Object]") throw new Error("传入参数不是一个对象");
for (const key in target) {
// 传入指定key 或者 key数组长度未0 默认全编码
if (Object.prototype.toString.call(target[key]) == "[object Object]") {
target[key] = jsonTraversal(target[key], decode);
} else {
if (decode) {
isencodingStr(target[key]) ? target[key] = decodeURIComponent(target[key]) : null;
} else {
needEncodeComponent(target[key]) ? target[key] = encodeURIComponent(target[key]) : null;
}
}
}
return target;
} catch (error) {
console.log(error);
}
}
/**
* url查询参数中需要编码的特殊字符
* @param {string} componentStr
* @returns
*/
export function needEncodeComponent(componentStr) {
const reg = /[^a-zA-Z0-9\-_.!~*'()]/gim;
return reg.test(componentStr);
}
/**
* 字符串是否被编码过
* @param {string} checkStr
* @returns
*/
export function isencodingStr(checkStr) {
const reg = /%[0-9A-Fa-f]{2}/gim;
return reg.test(checkStr);
}
let messageSingleton = null;
/**
* element message 弹窗单例模式
* @param {string} type
* @param {string} messgage
*/
export async function elementMessageSingleton(type = "success", messgage = "") {
try {
if (messageSingleton) {
messageSingleton.close();
}
} catch (error) {
console.log(error);
} finally {
messageSingleton = Message[type](messgage);
}
}
/**
* 检测数组对象中是否有重复数据
* @param {Array} arr
* @param {string | null} mapKey
* @returns
*/
export function hasDuplicates(arr, mapKey = null) {
try {
const map = new Map();
for (const item of arr) {
const key = mapKey ? item[mapKey] : JSON.stringify(item);
if (map.has(key)) {
return { hasRepeat: true, repeatKey: key };
}
map.set(key, true);
}
return { hasRepeat: false };
} catch (error) {
console.log(error);
}
}
// 甲方详情左侧菜单映射
export const detailSideBar = new Map([
// 企业速览
......
......@@ -37,33 +37,33 @@ service.interceptors.request.use(config => {
config.params = {};
config.url = url;
}
cancelPending(config)
config.cancelToken = new CancelToken(res => {
pending.push({'UrlPath': config.url, 'Cancel': res})
})
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 200; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
// cancelPending(config)
// config.cancelToken = new CancelToken(res => {
// pending.push({'UrlPath': config.url, 'Cancel': res})
// })
// if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
// const requestObj = {
// url: config.url,
// data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
// time: new Date().getTime()
// }
// const sessionObj = cache.session.getJSON('sessionObj')
// if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
// cache.session.setJSON('sessionObj', requestObj)
// } else {
// const s_url = sessionObj.url; // 请求地址
// const s_data = sessionObj.data; // 请求数据
// const s_time = sessionObj.time; // 请求时间
// const interval = 200; // 间隔时间(ms),小于此时间视为重复提交
// if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
// const message = '数据正在处理,请勿重复提交';
// console.warn(`[${s_url}]: ` + message)
// return Promise.reject(new Error(message))
// } else {
// cache.session.setJSON('sessionObj', requestObj)
// }
// }
// }
return config
}, error => {
console.log(error)
......@@ -125,10 +125,11 @@ service.interceptors.response.use(res => {
Notification.error({ title: msg })
return Promise.reject('error')
} else {
cancelPending(res.config)
// cancelPending(res.config)
return res.data
}
},error => {
console.log(error);
console.log('err' + error)
let { message } = error;
/*if (message == "Network Error") {
......
......@@ -3,7 +3,7 @@
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
return /^(https?:|mailto:|tel:)/.test(path);
}
/**
......@@ -11,8 +11,8 @@ export function isExternal(path) {
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
const valid_map = ['admin', 'editor'];
return valid_map.indexOf(str.trim()) >= 0;
}
/**
......@@ -20,8 +20,8 @@ export function validUsername(str) {
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
return reg.test(url);
}
/**
......@@ -29,8 +29,8 @@ export function validURL(url) {
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
const reg = /^[a-z]+$/;
return reg.test(str);
}
/**
......@@ -38,8 +38,8 @@ export function validLowerCase(str) {
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
const reg = /^[A-Z]+$/;
return reg.test(str);
}
/**
......@@ -47,8 +47,8 @@ export function validUpperCase(str) {
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
const reg = /^[A-Za-z]+$/;
return reg.test(str);
}
/**
......@@ -56,8 +56,8 @@ export function validAlphabets(str) {
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return reg.test(email);
}
/**
......@@ -66,9 +66,9 @@ export function validEmail(email) {
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true
return true;
}
return false
return false;
}
/**
......@@ -77,7 +77,34 @@ export function isString(str) {
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
return Object.prototype.toString.call(arg) === '[object Array]';
}
return Array.isArray(arg)
return Array.isArray(arg);
}
/**
* 电话号码验证
* @param {object} rule
* @param {string} value
* @param {Function} callback
* @returns
*/
export function phoneNumberValidator(rule, value, callback) {
const phoneReg = /^1[3-9]\d{9}$/;
if (!value && !value?.toString()?.trim()) {
return callback(new Error(`请输入手机号码`));
}
if (value && !phoneReg.test(value)) {
return callback(new Error(`请输入正确的手机号码`));
}
return callback();
}
export function requiredStrLengthValidator(target) {
return function (rule, value, callback) {
if (!value && !value?.toString()?.trim()) {
return callback(new Error(`请输入${target}`));
}
return callback();
};
};
<template>
<div class="child-container">
<el-dialog :visible.sync="dialogExportVisible" width="770px" append-to-body class="dialogExport" :close-on-click-modal="false" :show-close='false'>
<template slot="title">
<!--<img class="tip-img" src="@/assets/images/icon.png" />-->
数据导出
</template>
<div class="exportTitle"><span>文件名称</span><p>{{data.title}}</p></div>
<img class="exportImg" src="@/assets/images/export.png" />
<div class="table-item">
<el-table :data="exportTableData">
<el-table-column
v-for="(item,index) in forData"
:key="index"
:label="item.label"
:prop="item.prop"
:width="item.width"
:min-width="item.minWidth"></el-table-column>
</el-table>
</div>
<div class="input">
<div>
导出数量:
<el-input placeholder="" v-model="value" oninput="value=value.replace(/[^\d]/g,'')">
<template slot="append"></template>
</el-input>
<p class="tips1"><span>导出文件格式为Excel表格</span><span>最多导出2000条数据,若需导出更多数据,请联系大司空工作人员。</span></p>
</div>
<p class="tips2" v-if="value > 2000">导出数据最多支持导出2000条数据</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel()">取消</el-button>
<el-button type="primary" @click="handleEXCEL">确认导出</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogExportVisible1" width="348px" append-to-body class="dialogExport1" @close="handleCancel2">
<template slot="title">
<img class="tip-img" src="@/assets/images/success.png" />
提交成功
</template>
<div class="content">
<p class="p2">
可前往个人中心查看导出的全部表格
<!--<span @click="toUrl">前往个人中心</span>-->
</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel2()">取消</el-button>
<!--<el-button type="primary" @click="downloadFile(exportData.url,exportData.originalName)">下载表格</el-button>-->
<el-button type="primary" @click="toUrl">前往个人中心</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getNationalDetails } from '@/api/macro/macro'
export default {
name: '',
components: {},
props: {
data: {}
},
data() {
return {
dialogExportVisible: this.data.dialogExportVisible,
dialogExportVisible1: false,
exportTableData:[],
forData:[],
value:'',
}
},
watch: {
'data.exportEXCEL':{
handler(newValue, oldValue) {
if(newValue === true){
this.dialogExportVisible=false;
this.dialogExportVisible1=true;
}
},
immediate: true
},
},
created() {
this.exportTableData=this.data.exportTableData
this.forData=this.data.forData;
},
computed: {
},
methods: {
handleEXCEL(){
this.$nextTick(() => {
this.$emit('clickEXCEL',this.value)
})
},
handleCancel(){
this.dialogExportVisible=false;
this.$parent.cancel();
},
handleCancel2(){
this.dialogExportVisible1=false;
this.$parent.cancel();
},
downloadFile() {
const x = new XMLHttpRequest()
x.open("GET", this.exportEXCEL.url, true)
x.responseType = 'blob'
x.onload=function(e) {
const url = window.URL.createObjectURL(x.response)
const a = document.createElement('a')
a.href = url
a.download = this.exportEXCEL.fileName
a.click()
a.remove()
}
x.send()
},
toUrl(){
this.$parent.cancel();
this.dialogExportVisible1=false;
this.$router.push({
path: '/user/profile',
})
},
}
}
</script>
<style lang="scss" scoped>
.dialogExport{
::v-deep .el-dialog{
.el-dialog__header{
height: 48px;
line-height: 48px;
padding: 0 16px;
border-bottom: 1px solid #E1E1E1;
font-weight: bold;
color: #1D2129;
font-size: 16px;
.tip-img{
width: 18px;
height: 18px;
margin-right: 7px;
margin-bottom: -3px;
}
.el-dialog__headerbtn{
font-size: 20px;
font-weight: bold;
top: 15px;
.el-dialog__close{
color:#999999;
}
}
}
.exportTitle{
height: 34px;
margin-bottom: 20px;
span{
color: rgba(35,35,35,0.8);
font-size: 14px;
margin-right: 12px;
}
p{
display: inline-block;
width: 669px;
border: 1px solid #D9D9D9;
border-radius: 2px;
height: 32px;
line-height: 32px;
color: #232323;
margin: 0;
padding-left: 12px;
}
}
.exportImg{
width: 84px;
height: 24px;
display: block;
}
.el-dialog__body{
padding: 16px 16px 24px 16px;
border-bottom: 1px solid #E5E6EB;
.input{
margin-top: 16px;
position: relative;
.el-input{
width: 120px;
border-radius: 2px;
height: 32px;
.el-input__inner{
height: 32px;
line-height: 32px;
}
}
.el-input-group__append{
padding: 0 14px;
}
.el-input-group__append:hover{
background: #F5F7FA !important;
}
.tips1{
color: rgba(35,35,35,0.4);
font-size: 12px;
display: inline-block;
position: absolute;
left: 220px;
top: 0;
span{
display: block;
}
}
.tips2{
color: #FF3C3C;
font-size: 12px;
margin-top: 8px;
line-height: 20px;
margin-left: 75px;
}
}
.content{
/*text-align: center;*/
margin-top: 36px;
.success{
width: 64px;
height: 64px;
margin-bottom: 16px;
}
p{
padding: 0;
margin: 0;
}
}
}
.el-dialog__footer{
text-align: right;
padding: 16px 20px;
}
}
}
.dialogExport1{
::v-deep .el-dialog{
.el-dialog__header{
height: 48px;
line-height: 48px;
padding: 0 16px;
font-weight: bold;
color: #1D2129;
font-size: 16px;
.tip-img{
width: 18px;
height: 18px;
margin-right: 7px;
margin-bottom: -3px;
}
.el-dialog__headerbtn{
font-size: 20px;
font-weight: bold;
top: 15px;
.el-dialog__close{
color:#999999;
}
}
}
.el-dialog__body{
padding: 0 16px;
.content{
text-align: center;
.p2{
color: rgba(35,35,35,0.4);
font-size: 14px;
margin: 6px;
span{
color:#0081FF;
cursor: pointer;
}
}
}
}
.el-dialog__footer{
text-align: right;
padding: 16px 20px;
}
}
}
</style>
......@@ -10,13 +10,13 @@
<div class="table_search">
<div>
<!-- 未点击前的输入框样式 -->
<div class="normal-search-container" :class="{'is-hover-search' : hover}" @mouseover="searchHover($event)"
@mouseleave="searchUnHover($event,searchParam.companyName)">
<div class="normal-search-container" :class="{'is-hover-search' : searchHoverStatus}" @mouseover="searchHover($event)"
@mouseleave="searchUnHover($event)">
<img src="@/assets/images/enterprise/enterprise-search-icon.svg" alt="">
<span v-show="!hover && !searchParam.companyName">搜索</span>
<el-input v-model="searchParam.companyName" placeholder="输入关键词查询"
@focus="searchFocus($event)" @blur="searchBlur($event)" @keydown.native.enter="getCustomerList"
@input="value => searchInput(value)" v-show="hover || searchParam.companyName">
<span v-if="!searchHoverStatus && !searchParam.companyName">搜索</span>
<el-input v-model="searchParam.companyName" placeholder="输入关键词查询" style="width:238px;" @focus="searchFocus($event)"
@blur="searchBlur($event)" @input="value => searchInput(value)" v-else="searchHoverStatus || searchParam.companyName"
@keydown.native.enter="handleSearch">
<template slot="suffix">
<transition mode="out-in" appear name="fade">
<img src="@/assets/images/enterprise/search-input-clear-icon.svg" alt="" @click.stop="searchParam.companyName = '';getCustomerList()"
......@@ -253,6 +253,7 @@ export default {
RLcompanyName:'',//重新认领企业名称
isSkeleton:true,
showClearIcon: false,
searchHoverStatus: false,
hover: false,
}
},
......@@ -345,6 +346,12 @@ export default {
this.handleCurrentChange(1)
}
},
handleSearch() {
this.$nextTick(() => {
this.searchParam.pageNum = 1;
this.getCustomerList();
});
},
//翻页
handleCurrentChange(val) {
this.isSkeleton = true
......@@ -358,19 +365,28 @@ export default {
}
},
searchBlur(event) {
this.showClearIcon=false
const { target } = event;
// 失去焦点没有文字
if (!target?.value?.length) {
this.searchHoverStatus = false;
}
this.showClearIcon = false;
this.getCustomerList();
},
searchInput(value) {
if (value?.length) {
this.showClearIcon=true
this.showClearIcon = true;
} else {
this.showClearIcon = false;
}
},
searchHover(event) {
this.hover=true
this.searchHoverStatus = true;
},
searchUnHover(event, value) {
if (!value) {
this.hover=false
searchUnHover(event) {
if (!this.searchParam.companyName) {
this.showClearIcon = false;
this.searchHoverStatus = false;
}
},
}
......
......@@ -7,7 +7,8 @@
:query-params="queryParams"
:total="tableDataTotal"
:headerFixed="true"
:isExcel="false"
:isExcel="true"
@handle-excel="clickDialog"
@handle-search="handleSearch"
>
<template slot="slot">
......@@ -69,18 +70,21 @@
<div>{{scope.row.stockPercent || '--'}}{{scope.row.stockPercent ? '%':''}}</div>
</template>
</tables>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
<script>
import {memberList,memberCount} from '@/api/detail/groupAccount/groupAccount'
import {memberList,memberCount,memberListExport} from '@/api/detail/groupAccount/groupAccount'
import dataRegion from '@/assets/json/dataRegion'
import { getDictType } from '@/api/main'
import mixin from '../../party-a/mixins/mixin'
import ExportDialog from "../../../component/export-dialog"
export default {
name: 'members',
props: ['customerId'],
mixins: [mixin],
components:{ExportDialog},
data(){
return{
isSkeleton:true,
......@@ -175,6 +179,43 @@
cgblList:['100%','50%以上','20%以上','5%以上','1%-5%'],
cgblName:'',
paramsData:{}, //储存组件筛选的条件
dataEXCEL:{},
exportData:{
title:'集团成员',
dialogExportVisible:false,
forData: [
{label: '企业名称', prop: 'companyName',slot: true,minWidth: '250'},
// {label: '科技型企业', prop: 'companyName', slot: true,minWidth: '160'},
{label: '成员层级', prop: 'combineMemberLevel',slot: true,minWidth: '100'},
// {label: '主营业务', prop: 'projectName', slot: true,minWidth: '260'},
{label: '法定代表人', prop: 'corporatePerson',slot: true,minWidth: '100'},
{label: '企业地区', prop: 'address',minWidth: '120'},
{label: '注册资本', prop: 'regCapital',minWidth: '150'},
{label: '持股比例', prop: 'stockPercent',minWidth: '100'},
{label: '成立日期', prop: 'registeredDate', slot: true,minWidth: '100'},
],
exportTableData:[
{
companyName:'XXX集团有限公司',
combineMemberLevel:'集团本身',
corporatePerson:'柳xx',
regCapital:'8000.0万元',
address:'海南',
stockPercent:'32%',
registeredDate:'2017-9-17',
},
{
companyName:'XXX集团有限公司',
combineMemberLevel:'一级企业',
corporatePerson:'江xx',
regCapital:'14000.0万元',
address:'重庆',
stockPercent:'40%',
registeredDate:'2018-9-17',
},
],
exportEXCEL:false
},
}
},
watch:{
......@@ -253,6 +294,7 @@
if(!data.combineId){
data.combineId=this.customerId;
}
this.dataEXCEL=JSON.parse(JSON.stringify(data));
memberList(data).then(res=>{
this.isSkeleton = false
this.tableLoading = false
......@@ -435,6 +477,30 @@
this.handleQuery(params)
this.$emit('handle-scroll')
},
clickDialog(){
this.exportData.dialogExportVisible=true;
},
clickEXCEL(value) {
if(value > 2000){
return
}
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.pageNum
memberListExport(this.dataEXCEL).then(res=>{
if(res.code === 200){
this.exportData.exportEXCEL=true;
}
})
},
cancel(){
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
}
}
</script>
......
......@@ -9,7 +9,7 @@
:headerFixed="true"
:isExcel="true"
@handle-search="handleSearch"
@handle-excel="clickEXCEL"
@handle-excel="clickDialog"
>
<template slot="slot">
......@@ -51,6 +51,8 @@
<div>{{scope.row.bidAmount || '--'}}{{scope.row.bidAmount ? '万元':''}}</div>
</template>
</tables>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
......@@ -59,11 +61,12 @@
import {businessList,exportWinBid} from '@/api/detail/groupAccount/groupAccount'
import dataRegion from '@/assets/json/dataRegion1'
import { getDictType } from '@/api/main'
import ExportDialog from "../../../component/export-dialog"
export default {
name: 'qualifications',
props: ['customerId','combineName'],
mixins: [mixin],
components:{},
components:{ExportDialog},
data(){
return{
isSkeleton:true,
......@@ -108,7 +111,48 @@
],
timeList: ['近三天', '近七天', '近半月', '自定义'],
moneyList: ['5000万以下', '5000万-1亿', '1亿-5亿', '5亿-10亿','10亿以上', '自定义'],
dataEXCEL:{}
dataEXCEL:{},
exportData:{
title:'集团业绩',
dialogExportVisible:false,
forData: [
{label: '中标时间', prop: 'bidTime',slot: true,minWidth: '100'},
{label: '中标成员', prop: 'companyName', slot: true,minWidth: '160'},
{label: '持股比例', prop: 'stockPercent',slot: true,minWidth: '80'},
{label: '项目名称', prop: 'projectName', slot: true,minWidth: '260'},
{label: '中标金额', prop: 'bidAmount',slot: true,minWidth: '140'},
{label: '中标地区', prop: 'address',minWidth: '100'},
{label: '业绩类型', prop: 'boundType',minWidth: '80'},
{label: '项目类型', prop: 'projectType',minWidth: '80'},
{label: '业主单位', prop: 'projectUnit', slot: true,minWidth: '160'},
],
exportTableData:[
{
bidTime:'2023-11-07',
companyName:'XXX集团有限公司',
stockPercent:'1.56%',
projectName:'新建沪渝蓉高铁武汉至宜昌段汉川东至宜昌北通信系统及铁塔静态验...',
bidAmount:'303.837529万元',
address:'辽宁省',
boundType:'施工',
projectType:'铁路工程',
projectUnit:'xxx有限责任公司',
},
{
bidTime:'2023-11-07',
companyName:'XXX集团有限公司',
stockPercent:'1.24%',
projectName:'国电电力-胜利电厂-灵活性改造可行性研究报告编制',
bidAmount:'465万元',
address:'云南省',
boundType:'施工',
projectType:'铁路工程',
projectUnit:'xxx有限责任公司',
},
],
exportEXCEL:false
},
}
},
created() {
......@@ -267,35 +311,30 @@
this.handleQuery(params)
this.$emit('handle-scroll')
},
clickEXCEL() {
this.dataEXCEL.combineName=this.combineName;
if(this.tableDataTotal > 2000){
this.dataEXCEL.pageSize=2000;
clickDialog(){
this.exportData.dialogExportVisible=true;
},
clickEXCEL(value) {
if(value > 2000){
return
}
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=this.tableDataTotal;
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.pageNum
exportWinBid(this.dataEXCEL).then(res=>{
if(res.code === 200){
this.downloadFile(res.data.url,res.data.originalName)
this.exportData.exportEXCEL=true;
}
})
// this.$download.exportByPost('/combine/info/export/win/bid',this.dataEXCEL,'集团中标.xlsx');
},
downloadFile(url, fileName) {
const x = new XMLHttpRequest()
x.open("GET", url, true)
x.responseType = 'blob'
x.onload=function(e) {
const url = window.URL.createObjectURL(x.response)
const a = document.createElement('a')
a.href = url
a.download = fileName
a.click()
a.remove()
}
x.send()
}
cancel(){
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
}
}
</script>
......
......@@ -2,12 +2,13 @@
<div class="performance">
<head-form-new
ref="headForm"
title=""
title="集团招标"
:form-data="formData"
:query-params="queryParams"
:total="tableDataTotal"
:isExcel="false"
@handle-search="handleSearch"
@handle-excel="clickDialog"
></head-form-new>
<skeleton style="margin-left:16px;" v-if="isSkeleton"></skeleton>
<tables
......@@ -45,53 +46,7 @@
<div>{{scope.row.bidAmount || '--'}}{{scope.row.bidAmount ? '万元':''}}</div>
</template>
</tables>
<el-dialog :visible.sync="dialogExportVisible" width="640px" append-to-body class="dialogExport">
<template slot="title">
<img class="tip-img" src="@/assets/images/icon.png" />数据导出
</template>
<div class="table-item">
<el-table :data="exportTableData">
<el-table-column prop="issueTime" label="招标发布时间" width="110"></el-table-column>
<el-table-column prop="tenderee" label="招标成员" width="200"></el-table-column>
<el-table-column prop="stockPercent" label="持股比例" min-width="100"></el-table-column>
<el-table-column prop="projectName" label="项目名称" min-width="220"></el-table-column>
<el-table-column prop="bidAmount" label="预算金额" min-width="100"></el-table-column>
<el-table-column prop="address" label="项目地区" min-width="110"></el-table-column>
<el-table-column prop="subjectMatter" label="招标采购分类" min-width="130"></el-table-column>
<el-table-column prop="projectType" label="项目类型" min-width="100"></el-table-column>
<el-table-column prop="agency" label="代理单位" min-width="160"></el-table-column>
</el-table>
</div>
<div class="input">
导出数量:
<el-input placeholder="" v-model="value" oninput="value=value.replace(/[^\d]/g,'')">
<template slot="append"></template>
</el-input>
<p v-if="value > 2000"><i class="el-icon-error"></i>最多支持导出2000条,如需更多联系大司空客服人员</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="clickEXCEL">确认导出</el-button>
<el-button @click="cancel">取消</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogExportVisible1" width="640px" append-to-body class="dialogExport">
<template slot="title">
<img class="tip-img" src="@/assets/images/icon.png" />
数据导出
</template>
<div class="content">
<img class="success" src="@/assets/images/success.png" />
<p class="p1">导出成功</p>
<p class="p2">
可在个人中心查看导出表格
<span @click="toUrl">前往个人中心</span>
</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="downloadFile(exportData.url,exportData.originalName)">下载表格</el-button>
<el-button @click="dialogExportVisible1 = false">取消</el-button>
</div>
</el-dialog>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
......@@ -102,11 +57,12 @@
import {bidPage,exportBid} from '@/api/detail/groupAccount/groupAccount'
import dataRegion from '@/assets/json/dataRegion1'
import { getDictType } from '@/api/main'
import ExportDialog from "../../../component/export-dialog"
export default {
name: 'qualifications',
props: ['customerId'],
mixins: [mixin],
components:{CustomTimeSelect,CustomMoneySelect},
components:{CustomTimeSelect,CustomMoneySelect,ExportDialog},
data(){
return{
isSkeleton:true,
......@@ -157,8 +113,6 @@
timeList: ['近三天', '近七天', '近半月', '自定义'],
moneyList: ['5000万以下', '5000万-1亿', '1亿-5亿', '5亿-10亿','10亿以上', '自定义'],
dataEXCEL:{},
dialogExportVisible:false,
dialogExportVisible1:false,
exportTableData:[
{
"address":"四川省-成都市",
......@@ -186,7 +140,46 @@
},
],
value:'',
exportData:{}
exportData:{
title:'集团招标',
dialogExportVisible:false,
forData: [
{label: '招标发布时间', prop: 'issueTime',minWidth: '110'},
{label: '招标成员', prop: 'tenderee', slot: true,minWidth: '130'},
{label: '持股比例', prop: 'stockPercent',slot: true,minWidth: '80'},
{label: '项目名称', prop: 'projectName', slot: true,minWidth: '240'},
{label: '预算金额', prop: 'bidAmount',slot: true,minWidth: '130'},
{label: '项目地区', prop: 'address',minWidth: '110'},
{label: '招标采购分类', prop: 'subjectMatter',minWidth: '110'},
{label: '项目类型', prop: 'projectType',minWidth: '80',slot: true},
{label: '代理单位', prop: 'agency',minWidth: '160',slot: true},
],
exportTableData:[
{
issueTime:'2023-11-07',
tenderee:'XXX有限公司',
stockPercent:'1.56%',
projectName:'新建沪渝蓉高铁武汉至宜昌段汉川东至宜昌北通信系统及铁塔静态验...',
bidAmount:'303.837529万元',
address:'辽宁省',
subjectMatter:'施工',
projectType:'铁路工程',
agency:'xxx有限责任公司',
},
{
issueTime:'2023-11-07',
tenderee:'XXX有限公司',
stockPercent:'1.24%',
projectName:'国电电力-胜利电厂-灵活性改造可行性研究报告编制',
bidAmount:'465万元',
address:'云南省',
subjectMatter:'施工',
projectType:'铁路工程',
agency:'xxx有限责任公司',
},
],
exportEXCEL:{}
},
}
},
created() {
......@@ -320,53 +313,29 @@
clickFocus(e){
document.getElementById(e).classList.toggle('span-ba')
},
clickDialog(){
this.dialogExportVisible=true;
this.exportData.dialogExportVisible=true;
},
clickEXCEL() {
if(this.value > 2000){
clickEXCEL(value) {
if(value > 2000){
return
}
this.dialogExportVisible=false;
this.dataEXCEL.combineName=this.combineName;
if(this.value){
this.dataEXCEL.pageSize=this.value
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=this.tableDataTotal > 2000 ? 2000 : this.tableDataTotal;
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.pageNum
exportBid(this.dataEXCEL).then(res=>{
if(res.code === 200){
this.dialogExportVisible1=true;
this.value=''
this.exportData=res.data;
this.exportData.exportEXCEL=true;
}
})
},
cancel(){
this.dialogExportVisible=false
this.value=''
},
downloadFile(url, fileName) {
const x = new XMLHttpRequest()
x.open("GET", url, true)
x.responseType = 'blob'
x.onload=function(e) {
const url = window.URL.createObjectURL(x.response)
const a = document.createElement('a')
a.href = url
a.download = fileName
a.click()
a.remove()
}
x.send()
},
toUrl(){
this.dialogExportVisible1=false;
this.$router.push({
path: '/user/profile',
})
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
}
}
......
<template>
<div class="head-form-new" :class="headerFixed ? 'headerFixed':''">
<div class="common-title" v-if="title">{{ title }}</div>
<div class="common-title" v-if="title && title !='集团招标'">{{ title }}</div>
<div class="flex-box query-box">
<div class="flex-box query-params">
<div class="headForm-from">
......@@ -27,7 +27,7 @@
<transition name="fade-position" appear mode="out-in">
<span v-if="!form.hover && !form.value">搜索</span>
<el-input v-model="form.value" :placeholder="form.placeholder ? form.placeholder : '输入关键词查询'"
:style="form.width?'width:'+form.width+'px':'width:238px'" @focus="searchFocus($event,form)" @blur="searchBlur($event,form)"
:style="form.width?'width:'+form.width+'px':'width:238px'" @focus.stop="searchFocus($event,form)" @blur.stop="searchBlur($event,form)"
@input="value => searchInput(value,form)" v-else @keydown.native.enter="changeSelect">
<template slot="suffix">
<transition mode="out-in" appear name="fade">
......@@ -78,7 +78,7 @@
</template>
<div v-else class="flex-box">
<span class="flex-box ability-total" v-if="isTotal">共有{{ total }}条</span>
<span class="flex-box ability-excel" v-hasPermi="['combine:info:export:win:bid','combine:info:export:bid']" v-if="isExcel && title ==='集团业绩'"
<span class="flex-box ability-excel" v-hasPermi="['combine:info:export:win:bid','combine:info:export:bid']" v-if="isExcel && title ==='集团业绩'|| title ==='集团业绩' "
@click="clickEXCEL"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<span class="flex-box ability-excel" v-else @click="clickEXCEL"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
</div>
......@@ -296,7 +296,7 @@ export default {
this.$emit('handle-search');
},
clickEXCEL() {
if (this.title === '集团业绩') {
if (this.title === '集团业绩' || this.title === '集团招标' || this.title === '集团成员') {
this.$emit('handle-excel');
} else {
this.$message({
......
......@@ -278,13 +278,13 @@ export default {
this.sideRoute[2].children[7].disabled = true;
}
break;
case 'customer':
case 'customerV1':
if (arr[i][j] < 1) {
this.sideRoute[3].children[0].disabled = true;
}
break;
case 'supplier':
case 'supplierV1':
if (arr[i][j] < 1) {
this.sideRoute[3].children[1].disabled = true;
}
......@@ -369,7 +369,6 @@ export default {
if (this.sideRoute1[i].children) {
for (var j in this.sideRoute1[i].children) {
if (item.title == this.sideRoute1[i].children[j].title) {
console.log(this.sideRoute1[i].children[j]);
obj.pathName = this.sideRoute1[i].children[j].pathName;
}
}
......
......@@ -377,6 +377,7 @@ export default {
<style lang="scss" scoped>
.part-container {
padding: 0;
margin: 0 24px;
}
.part-main {
margin-top: 12px;
......
......@@ -184,7 +184,7 @@ export default {
showMore: false,
showState: false,
graphList: [
{ id: 1, name: '业务往来', isShow: true, intro: [{ id: 101, name: '客户', val: 0, category: 'global', field: 'customer' }, { id: 102, name: '供应商', val: 0, category: 'global', field: 'supplier' }], ico: require('@/assets/images/detail/overview/company_ywwl.png') },
{ id: 1, name: '业务往来', isShow: true, intro: [{ id: 101, name: '客户', val: 0, category: 'global', field: 'customerV1' }, { id: 102, name: '供应商', val: 0, category: 'global', field: 'supplierV1' }], ico: require('@/assets/images/detail/overview/company_ywwl.png') },
{ id: 2, name: '商机线索', isShow: true, intro: [{ id: 201, name: '专项债项目', val: 0, category: 'performance', field: 'specialDebt' }, { id: 202, name: '招标计划', val: 0, category: 'performance', field: 'bidPlan' }], ico: require('@/assets/images/detail/overview/company_sjxs.png') },
{ id: 3, name: '城投拿地', isShow: true, intro: [{ id: 301, name: '土地交易', val: 0, category: 'global', field: 'landInfo' }, { id: 302, name: '行政许可', val: 0, category: 'business', field: 'adminLicensing' }], ico: require('@/assets/images/detail/overview/company_ctnd.png') },
{ id: 4, name: '对外投资', isShow: true, intro: [{ id: 401, name: '企业经营实力展现' }], ico: require('@/assets/images/detail/overview/company_dwtz.png') },
......
......@@ -285,7 +285,7 @@ export default {
.el-table__body {
tr:first-child {
position: sticky;
top: 56px;
top: 0px;
z-index: 9;
}
}
......
......@@ -123,7 +123,7 @@
<div class="title-right">
<p>
<img src="@/assets/images/EXCEL.png" alt="">
<span class="excel" @click="$message({message: '功能正在开发中',type: 'warning'})">导出EXCEL</span>
<span class="excel" @click="clickDialog">导出EXCEL</span>
</p>
</div>
......@@ -463,6 +463,8 @@
<span class="dialog-footer-btn2" @click="dialogVisible2 = false">关闭</span>
</div>
</el-dialog>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
......@@ -471,10 +473,11 @@ import { encodeStr } from "@/assets/js/common.js";
import jsk_data from '../../../../../public/jsk.json';
import skeleton from '@/views/project/projectList/component/skeleton';
import api from '@/api/enterpriseData/enterpriseData.js';
import ExportDialog from "../../../component/export-dialog"
import "@/assets/styles/public.scss";
export default {
name: 'Owner',
components: { skeleton },
components: { skeleton,ExportDialog },
data() {
return {
encodeStr,
......@@ -521,25 +524,22 @@ export default {
fieldshow: false,
fieldText: '默认排序',
sort: '3', //查询结果排序方式
fieldOptions: [{
fieldOptions: [
{
key: "3",
value: "默认排序",
status: true,
},
{
key: "5",
value: "招标数量从多到少",
status: false,
},
{
key: "7",
value: "土地数量从多到少",
status: false,
},
],
companyId: '',
companyName: '',
......@@ -550,7 +550,69 @@ export default {
tableData: [],
total: 0,
pageNum: 1,
pageSize: 50
pageSize: 50,
dataEXCEL:{},
exportData:{
title:'查城投平台',
dialogExportVisible:false,
forData: [
{label: '公司名称', prop: 'companyName',slot: true,minWidth: '140'},
{label: '区域', prop: 'province', slot: true,minWidth: '160'},
{label: '招标数量', prop: 'biddingCount',slot: true,minWidth: '80'},
{label: '城投拿地', prop: 'landInfoCount', slot: true,minWidth: '80'},
{label: '供应商', prop: 'supplierCount',slot: true,minWidth: '100'},
{label: '债券余额(亿元)', prop: 'bondBalance',minWidth: '130'},
{label: '主体评级', prop: 'bratingSubjectLevel',minWidth: '80'},
{label: '行政级别', prop: 'uipExecutiveLevel',minWidth: '80'},
{label: '股东背景', prop: 'shareholderBg', slot: true,minWidth: '100'},
{label: '股权关系', prop: 'equityRelationship', slot: true,minWidth: '100'},
{label: '平台重要性', prop: 'platformImportance', slot: true,minWidth: '130'},
{label: '城投业务类型', prop: 'uipBusinessType', slot: true,minWidth: '130'},
{label: '实控人', prop: 'actualController', slot: true,minWidth: '140'},
{label: '最新报告期', prop: 'latestReportPeriod', slot: true,minWidth: '120'},
{label: '总资产(亿元)', prop: 'totalAssets', slot: true,minWidth: '120'},
{label: '归母净资产', prop: 'belongNetAssets', slot: true,minWidth: '120'},
],
exportTableData:[
{
companyName:'xxx有限公司',
province:'重庆-重庆市-永川区',
biddingCount:'64',
landInfoCount:'4',
supplierCount:'456',
bondBalance:'73',
bratingSubjectLevel:'AAA',
uipExecutiveLevel:'区县级',
shareholderBg:'城建',
equityRelationship:'直接控股',
platformImportance:'主要平台',
uipBusinessType:'综合性平台',
actualController:'xxx监督管理委员会',
latestReportPeriod:'2022-12-21',
totalAssets:'55.47',
belongNetAssets:'21.74',
},
{
companyName:'xxx有限公司',
province:'北京-北京市-大兴区',
biddingCount:'25',
landInfoCount:'2',
supplierCount:'465',
bondBalance:'61',
bratingSubjectLevel:'AAA',
uipExecutiveLevel:'区县级',
shareholderBg:'政府',
equityRelationship:'间接控股',
platformImportance:'一般平台',
uipBusinessType:'土地开发整理',
actualController:'xxx监督管理委员会',
latestReportPeriod:'2022-12-21',
totalAssets:'764.74',
belongNetAssets:'62.13',
},
],
exportEXCEL:{}
},
};
},
computed: {
......@@ -568,9 +630,6 @@ export default {
flag = true;
arr.push(data);
}
this.conditionsArr = arr;
return flag;
},
......@@ -633,9 +692,6 @@ export default {
this.jskBidQueryDto = obj;
this.search();
},
addressListfn() {
var str = [];
for (let x = 0; x < 3; x++) {
......@@ -680,19 +736,14 @@ export default {
}
this.addressList = str;
},
reset() {
Object.assign(this.$data, this.$options.data.call(this)); //重置data
this.init();
},
init() {
this.search();
this.addressListfn();
},
checkuipExecutivebtn(val) {
this.uipExecutiveText = [];
this.checkuipExecutive = true;
......@@ -932,6 +983,7 @@ export default {
delete params.equityRelationship;
}
this.isSkeleton = true;
this.dataEXCEL=JSON.parse(JSON.stringify(params));
api.uipSerach(params).then(res => {
this.isSkeleton = false;
this.tableData = res.rows;
......@@ -945,6 +997,30 @@ export default {
// this.$router.push({path:'/home',query: {id:'1'}})
// 跳转地址
},
clickDialog(){
this.exportData.dialogExportVisible=true;
},
clickEXCEL(value) {
if(value > 2000){
return
}
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.pageNum
api.uipSerachExport(this.dataEXCEL).then(res => {
if(res.code === 200){
this.exportData.exportEXCEL=true;
}
})
},
cancel(){
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
},
......
......@@ -296,7 +296,7 @@
</div>
<div>
<el-button size="mini" @click="cancel('注册资本')">取消</el-button>
<el-button size="mini" @click="handleCancel('注册资本')">取消</el-button>
<el-button type="primary" size="mini" @click="popperConfirm('注册资本')">确定
</el-button>
</div>
......@@ -336,7 +336,7 @@
</el-input>
</div>
<div>
<el-button size="mini" @click="cancel('实缴资本')">取消</el-button>
<el-button size="mini" @click="handleCancel('实缴资本')">取消</el-button>
<el-button type="primary" size="mini" @click="popperConfirm('实缴资本')">确定
</el-button>
</div>
......@@ -378,7 +378,7 @@
</el-input>
</div>
<div style="">
<el-button size="mini" @click="cancel('社保人数')">取消</el-button>
<el-button size="mini" @click="handleCancel('社保人数')">取消</el-button>
<el-button type="primary" size="mini" @click="popperConfirm('社保人数')">确定
</el-button>
</div>
......@@ -425,10 +425,14 @@
</div>
</div>
<div class="title-right">
<p>
<p class="p" @click="exportShow=true">
<img src="@/assets/images/EXCEL.png" alt="">
<span class="excel" @click="$message({message: '功能正在开发中',type: 'warning'})">导出EXCEL</span>
<span class="excel">导出EXCEL</span>
</p>
<div class="export" v-if="exportShow">
<p style="margin-bottom: 6px;" @click="clickDialog(1)">企业资质导出</p>
<p @click="clickDialog(2)">企业基本信息导出</p>
</div>
</div>
</div>
......@@ -577,6 +581,7 @@
</div>
</div>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
<script>
......@@ -588,10 +593,10 @@ import api from '@/api/enterpriseData/enterpriseData.js';
import { encodeStr } from "@/assets/js/common.js";
import skeleton from '@/views/project/projectList/component/skeleton';
import "@/assets/styles/public.scss";
import ExportDialog from "../../../component/export-dialog"
export default {
name: 'EnterpriseQuery',
components: { skeleton },
components: { skeleton,ExportDialog },
directives: {
numberOnly: {
bind: function (el) {
......@@ -612,7 +617,8 @@ export default {
encodeStr,
ename: '',
isSkeleton: true,
enameQueryTypeList: [{
enameQueryTypeList: [
{
key: 'and',
status: false,
value: '模糊搜索',
......@@ -626,9 +632,9 @@ export default {
},
],
enameQueryType: 'or',
optionss: [],
aptitudeDtoList: [{
aptitudeDtoList: [
{
nameStr: '',
codeStr: [],
queryTypelist: [{
......@@ -649,7 +655,8 @@ export default {
],
queryType: 'and'
}],
aptitudeDtoListOut: [{
aptitudeDtoListOut: [
{
nameStr: '',
codeStr: [],
queryTypelist: [{
......@@ -666,17 +673,16 @@ export default {
queryType: 'and'
}],
filePlaceCode: '',
props: {
multiple: true,
expandTrigger: "hover",
value: 'id'
},
filePlaceCodeList: [],
province_city: [],
province_citylist: [],
filePlaceTypeList: [{
filePlaceTypeList: [
{
text: '本省与进省企业',
value: '1'
},
......@@ -693,7 +699,8 @@ export default {
addressList: [],
addressType: [],
addresslength: 0,
qualifiedType: [{
qualifiedType: [
{
key: '',
status: true,
value: '不限'
......@@ -710,7 +717,8 @@ export default {
}
],
radioQuali: '',
hasPhoneType: [{
hasPhoneType: [
{
key: '',
status: true,
value: '不限'
......@@ -737,8 +745,8 @@ export default {
}
],
hasPhone: '',
hasLiceCertList: [{
hasLiceCertList: [
{
key: '',
status: true,
value: '不限'
......@@ -755,9 +763,9 @@ export default {
}
],
hasLiceCert: '',
systemCertishow: false,
systemCertification: [{
systemCertification: [
{
value: '质量管理体系认证(ISO9000)',
key: '1',
status: false,
......@@ -784,7 +792,8 @@ export default {
],
systemValue: [],
systemType: "",
isHighTechList: [{
isHighTechList: [
{
value: '',
label: '不限'
},
......@@ -799,7 +808,8 @@ export default {
],
isHighTechtext: '',
aTaxYearList: [{
aTaxYearList: [
{
value: '不限',
label: '不限'
},
......@@ -842,7 +852,8 @@ export default {
},
],
aTaxYeartext: ['不限'],
companyTypeList: [{
companyTypeList: [
{
label: '不限',
value: '不限'
},
......@@ -897,7 +908,8 @@ export default {
],
companyTypeText: ['不限'],
businessStatusList: [{
businessStatusList: [
{
label: '不限',
value: '不限'
},
......@@ -936,7 +948,8 @@ export default {
],
businessStatusText: ['不限'],
establishList: [{
establishList: [
{
value: '不限',
key: '不限',
status: true,
......@@ -985,7 +998,8 @@ export default {
establishText: '不限',
startTime: '',
endTime: '',
registeredAssets: [{
registeredAssets: [
{
label: '不限',
value: '不限',
status: false,
......@@ -1034,7 +1048,8 @@ export default {
actualCapi: '不限',
leftActualCapi: '',
rightActualCapi: '',
InsuredNumList: [{
InsuredNumList: [
{
label: '0-0',
value: '0人'
},
......@@ -1077,12 +1092,12 @@ export default {
InsuredNumText: '',
startInsuredNum: '',
endInsuredNum: '',
registeredCapital: '',
registerProvince: [],
registerCityList: [],
registerCity: [],
registerProvinceList: [{
registerProvinceList: [
{
key: '重庆',
status: false,
value: '重庆',
......@@ -1307,7 +1322,8 @@ export default {
}
],
aptitudeQueryType: 'and',
btnaptitude: [{
btnaptitude: [
{
key: 'and',
status: true,
value: '同时具备'
......@@ -1321,7 +1337,8 @@ export default {
aptitudelist: [],
regionWeb: [],
regionWebList: [],
hasPhoneList: [{
hasPhoneList: [
{
value: '1',
label: '有联系电话'
},
......@@ -1331,7 +1348,8 @@ export default {
}
],
hasPhonetext: '',
systemWay: [{
systemWay: [
{
key: 'and',
status: true,
value: '同时具备',
......@@ -1358,7 +1376,6 @@ export default {
},
startTimetext: '',
openDatePicker: false,
fieldshow: false,
fieldText: '默认排序',
field: '', //查询结果排序方式
......@@ -1408,12 +1425,79 @@ export default {
}
],
resultEname: '',
tableData: [],
total: 0,
page: 1,
limit: 20
limit: 20,
exportShow:false,
dataEXCEL:{},
exportData:{
title:'企业基本信息',
dialogExportVisible:false,
forData: [
{label: '企业名称', prop: 'text1',slot: true,minWidth: '120'},
{label: '企业性质', prop: 'text2', slot: true,minWidth: '120'},
{label: '资质情况', prop: 'text3',slot: true,minWidth: '160'},
{label: '经营状态', prop: 'text4', slot: true,minWidth: '160'},
{label: '经营范围', prop: 'text5',slot: true,minWidth: '250'},
{label: '统一社会信用代码', prop: 'text6',minWidth: '160'},
{label: '注册省/市/区', prop: 'text7',minWidth: '150'},
{label: '经营地址', prop: 'text8',minWidth: '140'},
{label: '法人代表', prop: 'text9', slot: true,minWidth: '100'},
{label: '注册资本(万元)', prop: 'text10', slot: true,minWidth: '150'},
{label: '成立时间', prop: 'text11', slot: true,minWidth: '130'},
{label: '曾用名', prop: 'text12', slot: true,minWidth: '100'},
{label: '企业类型', prop: 'text13', slot: true,minWidth: '140'},
{label: '参保人数', prop: 'text14', slot: true,minWidth: '120'},
{label: '税务评级', prop: 'text15', slot: true,minWidth: '120'},
{label: '安许证到期时间', prop: 'text16', slot: true,minWidth: '120'},
{label: '联系电话', prop: 'text17', slot: true,minWidth: '120'},
{label: '企业详情页(平台)', prop: 'text18', slot: true,minWidth: '150'},
],
exportTableData:[
{
text1:'xxx有限公司',
text2:'央企子公司',
text3:'地基基础工程专业承包一级',
text4:'存续(在营、开业、在册)',
text5:'承担国内外公用、民用房屋建筑工程的施工、安装、咨询...',
text6:'911100xxxx9351850',
text7:'北京-北京市-海淀区',
text8:'北京市XXXXX',
text9:'张XX',
text10:'3000000万元',
text11:'2007-12-10',
text12:'-',
text13:'有限责任公司',
text14:'1401',
text15:'A级',
text16:'2026-11-23',
text17:'6420xx11',
text18:'XXXXX',
},
{
text1:'xxx有限公司',
text2:'省属国企',
text3:'建筑装修装饰工程专业承包一级',
text4:'存续(在营、开业、在册)',
text5:'承担国内外公用、民用房屋建筑工程的施工、安装、咨询...',
text6:'911100xxxx9351850',
text7:'重庆-重庆市-渝北区',
text8:'重庆市XXXXX',
text9:'李XX',
text10:'200000万元',
text11:'2008-12-10',
text12:'-',
text13:'有限责任公司',
text14:'1101',
text15:'A级',
text16:'2027-11-23',
text17:'6430xx11',
text18:'XXXXX',
},
],
exportEXCEL:{}
},
};
},
......@@ -1462,8 +1546,6 @@ export default {
this.addressListbtn();
});
}
},
methods: {
......@@ -2436,7 +2518,7 @@ export default {
},
// 注册资本 实缴资本 社保人数 自定义输入取消
cancel(type) {
handleCancel(type) {
if (type == '注册资本') {
this.startNumMoney = '';
this.endNumMoney = '';
......@@ -2763,6 +2845,7 @@ export default {
data.aptitudeQueryDto['aptitudeSource'] = 'new';
}
this.isSkeleton = true;
this.dataEXCEL=JSON.parse(JSON.stringify(data));
api.enterprisePage(data).then(res => {
this.isSkeleton = false;
if (res.code == 200) {
......@@ -2774,7 +2857,6 @@ export default {
});
},
toEnterprise(id, html, type,name) {
this.$tab.openPage(name, '/company/' + encodeStr(id) + '/' + (html ? html + '/' : '') + (type ? '?flag=true&type=' + type : ''))
},
......@@ -2826,6 +2908,168 @@ export default {
}
return obj;
},
clickDialog(key){
if(key === 1){
this.exportData={
title:'企业资质',
dialogExportVisible:false,
forData: [
{label: '企业名称', prop: 'text1',slot: true,minWidth: '120'},
{label: '企业性质', prop: 'text2', slot: true,minWidth: '100'},
{label: '资质类别', prop: 'text3',slot: true,minWidth: '150'},
{label: '资质名称', prop: 'text4', slot: true,minWidth: '180'},
{label: '发证日期', prop: 'text5',slot: true,minWidth: '110'},
{label: '到期时间', prop: 'text6',minWidth: '110'},
{label: '发证机关', prop: 'text7',minWidth: '150'},
{label: '联系电话', prop: 'text8',minWidth: '140'},
{label: '地址', prop: 'text9', slot: true,minWidth: '150'},
{label: '备案情况', prop: 'text10', slot: true,minWidth: '150'},
{label: '法定代表人', prop: 'text11', slot: true,minWidth: '120'},
{label: '注册资本(万元)', prop: 'text12', slot: true,minWidth: '160'},
{label: '成立时间', prop: 'text13', slot: true,minWidth: '120'},
{label: '经营范围', prop: 'text14', slot: true,minWidth: '150'},
{label: '企业详情链接', prop: 'text15', slot: true,minWidth: '150'},
],
exportTableData:[
{
text1:'xxx有限公司',
text2:'国有企业',
text3:'建筑业企业资质',
text4:'建筑工程施工总承包特级',
text5:'2022-03-14',
text6:'2023-12-31',
text7:'住房和城乡建设部',
text8:'6420xx11',
text9:'重庆市渝中区XXX',
text10:'外地入渝(重庆市工程信息网)',
text11:'张XX',
text12:'100000.0万元',
text13:'1992-01-21',
text14:'房屋建筑工程、公路工程、市政工程...',
text15:'XXXXX',
},
{
text1:'xxx有限公司',
text2:'省属国企',
text3:'建筑业企业资质',
text4:'建筑工程施工总承包特级',
text5:'2022-03-14',
text6:'2023-12-31',
text7:'住房和城乡建设部',
text8:'6430xx11',
text9:'重庆市渝北区XXX',
text10:'重庆本地',
text11:'王XX',
text12:'120000.0万元',
text13:'2000-06-16',
text14:'房屋建筑工程、公路工程、市政工程...',
text15:'XXXXX',
},
],
exportEXCEL:{}
}
}
if(key === 2){
this.exportData={
title:'企业基本信息',
dialogExportVisible:false,
forData: [
{label: '企业名称', prop: 'text1',slot: true,minWidth: '120'},
{label: '企业性质', prop: 'text2', slot: true,minWidth: '120'},
{label: '资质情况', prop: 'text3',slot: true,minWidth: '160'},
{label: '经营状态', prop: 'text4', slot: true,minWidth: '160'},
{label: '经营范围', prop: 'text5',slot: true,minWidth: '250'},
{label: '统一社会信用代码', prop: 'text6',minWidth: '160'},
{label: '注册省/市/区', prop: 'text7',minWidth: '150'},
{label: '经营地址', prop: 'text8',minWidth: '140'},
{label: '法人代表', prop: 'text9', slot: true,minWidth: '100'},
{label: '注册资本(万元)', prop: 'text10', slot: true,minWidth: '150'},
{label: '成立时间', prop: 'text11', slot: true,minWidth: '130'},
{label: '曾用名', prop: 'text12', slot: true,minWidth: '100'},
{label: '企业类型', prop: 'text13', slot: true,minWidth: '140'},
{label: '参保人数', prop: 'text14', slot: true,minWidth: '120'},
{label: '税务评级', prop: 'text15', slot: true,minWidth: '120'},
{label: '安许证到期时间', prop: 'text16', slot: true,minWidth: '120'},
{label: '联系电话', prop: 'text17', slot: true,minWidth: '120'},
{label: '企业详情页(平台)', prop: 'text18', slot: true,minWidth: '150'},
],
exportTableData:[
{
text1:'xxx有限公司',
text2:'央企子公司',
text3:'地基基础工程专业承包一级',
text4:'存续(在营、开业、在册)',
text5:'承担国内外公用、民用房屋建筑工程的施工、安装、咨询...',
text6:'911100xxxx9351850',
text7:'北京-北京市-海淀区',
text8:'北京市XXXXX',
text9:'张XX',
text10:'3000000万元',
text11:'2007-12-10',
text12:'-',
text13:'有限责任公司',
text14:'1401',
text15:'A级',
text16:'2026-11-23',
text17:'6420xx11',
text18:'XXXXX',
},
{
text1:'xxx有限公司',
text2:'省属国企',
text3:'建筑装修装饰工程专业承包一级',
text4:'存续(在营、开业、在册)',
text5:'承担国内外公用、民用房屋建筑工程的施工、安装、咨询...',
text6:'911100xxxx9351850',
text7:'重庆-重庆市-渝北区',
text8:'重庆市XXXXX',
text9:'李XX',
text10:'200000万元',
text11:'2008-12-10',
text12:'-',
text13:'有限责任公司',
text14:'1101',
text15:'A级',
text16:'2027-11-23',
text17:'6430xx11',
text18:'XXXXX',
},
],
exportEXCEL:{}
}
}
this.exportData.dialogExportVisible=true;
},
clickEXCEL(value) {
if(value > 2000){
return
}
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.pageNum
if(this.exportData.title === '企业资质'){
api.aptitudeExport(this.dataEXCEL).then(res => {
if(res.code === 200){
this.exportData.exportEXCEL=true;
}
})
}
if(this.exportData.title === '企业基本信息'){
api.infoExport(this.dataEXCEL).then(res => {
if(res.code === 200){
this.exportData.exportEXCEL=true;
}
})
}
},
cancel(){
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
}
}
......@@ -2982,7 +3226,8 @@ export default {
.title-right {
display: flex;
align-items: center;
p:last-child {
position: relative;
.p{
display: flex;
align-items: center;
font-size: 14px;
......@@ -2996,6 +3241,26 @@ export default {
.excel {
cursor: pointer;
}
.export{
width: 135px;
position: absolute;
top: 30px;
align-items: center;
background: #ffffff;
z-index: 9;
left: -11px;
padding: 6px 10px;
box-shadow: 0px 2px 10px rgba(0,21,41,.08);
p{
font-size: 14px;
font-weight: 400;
color: rgba(35, 35, 35, 0.8);
cursor: pointer;
}
p:hover{
color:#0089ff;
}
}
}
}
.bottomlist-content {
......
......@@ -842,7 +842,7 @@ export default {
.el-checkbox-group {
.el-checkbox {
.el-checkbox__label {
color: #333333;
color: #606266;
}
&.is-checked {
.el-checkbox__label {
......
<template>
<el-dialog title="添加账号" :visible.sync="dialogStatus" width="800px" @close="dialogClose" @open="dialogOpen" class="enterprise-add-account"
custom-class="enterprise-add-account-dialog" :close-on-click-modal="false">
<div class="enterprise-add-account-inner">
<el-form :model="accountForm" ref="accountForm" :rules="rules">
<transition-group tag="div" class="enterprise-add-account-list" name="list" appear>
<div class="enterprise-add-account-item" v-for="(item,index) of accountForm.accountList" :key="item.uid">
<div class="account-nickname">
<el-form-item label="用户名称" :prop="`accountList[${index}].nickName`" :rules="rules.nickName">
<el-input v-model="accountForm.accountList[index].nickName" placeholder="请输入用户名称" size="normal" clearable></el-input>
</el-form-item>
</div>
<div class="account-phone">
<el-form-item label="手机号码" :prop="`accountList[${index}].phonenumber`" :rules="rules.phonenumber">
<el-input v-model="accountForm.accountList[index].phonenumber" placeholder="请输入手机号码" size="normal" clearable></el-input>
</el-form-item>
</div>
<div class="remove-account-item" @click="removeAccount(item.uid)" v-if="accountForm.accountList.length > 1"><i class="el-icon-delete"></i>
</div>
</div>
</transition-group>
<!-- 添加按钮 -->
<div class="add-account-btn" @click="addAccount">
<i class="el-icon-plus"></i>
<span>增加账号</span>
</div>
</el-form>
</div>
<template slot="footer">
<!-- 底部提交 取消按钮 -->
<div class="add-account-footer">
<el-button type="primary" size="medium" @click="submitAdd">确定</el-button>
<el-button size="medium" @click="dialogStatus = false">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script>
import { Loading } from 'element-ui';
import { enterpriseAddAccountApi } from "@/api/enterpriseManagement/enterpriseManagement";
import { phoneNumberValidator, requiredStrLengthValidator } from "@/utils/validate";
import { elementMessageSingleton, hasDuplicates } from "@/utils/";
import { v4 } from 'uuid';
export default {
name: "enterpriseAddAccount",
props: {
openStatus: {
type: Boolean,
default: false
},
enterpriseInfo: {
type: Object,
default: () => ({})
},
addAccountCount: {
type: [String, Number],
default: 1
}
},
watch: {
openStatus(newValue) {
this.dialogStatus = newValue;
},
addAccountCount(newValue) {
this.comAddAccountCount = newValue;
},
enterpriseInfo: {
handler(newValue) {
this.comEnterpriseInfo = newValue;
},
deep: true
}
},
data() {
return {
dialogStatus: this.openStatus,
comEnterpriseInfo: this.enterpriseInfo,
comAddAccountCount: this.addAccountCount,
accountForm: {
accountList: []
},
rules: {
nickName: [{ required: true, trigger: ["blur"], validator: requiredStrLengthValidator("用户名称") }],
phonenumber: [{ required: true, trigger: ["blur", "change"], validator: phoneNumberValidator }]
}
};
},
//可访问data属性
created() {
},
//计算集
computed: {
},
//方法集
methods: {
dialogOpen() {
this.addAccount();
},
dialogClose() {
this.accountForm = this.$options.data.call(this).accountForm;
this.$emit("dialogClose");
},
removeAccount(uid) {
const index = this.accountForm.accountList.findIndex(item => item.uid == uid);
if (index > -1) {
this.accountForm.accountList.splice(index, 1);
}
},
addAccount() {
if (this.comAddAccountCount >= 6) return elementMessageSingleton("warning", "该租户下已经添加了五个账号");
if (this.accountForm.accountList?.length >= 5) return elementMessageSingleton("warning", "最多添加五个账号");
const remaining = 6 - this.comAddAccountCount;
const len = this.accountForm?.accountList?.length;
if (len >= remaining) return elementMessageSingleton("warning", `该租户下剩余可添加账号个数为 ${remaining} 个,现已添加 ${len} 个`);
this.accountForm.accountList.push({
nickName: "",
phonenumber: "",
uid: v4()
});
},
submitAdd() {
this.$refs["accountForm"].validate(async flag => {
if (!flag) return;
const { hasRepeat, repeatKey } = hasDuplicates(JSON.parse(JSON.stringify(this.accountForm.accountList)), "phonenumber");
if (hasRepeat) return elementMessageSingleton("warning", `电话号码 ${repeatKey} 不允许重复创建`);
const loadingService = Loading.service({
target: ".enterprise-add-account-dialog",
lock: true,
text: "正在添加账号,请勿关闭窗口"
});
let successCount = 0;
try {
// 验证通过提交信息
const array = (JSON.parse(JSON.stringify(this.accountForm.accountList))).map(({ nickName, phonenumber }) => ({ nickName, phonenumber }));
let len = array.length;
let count = 0;
while (count < len) {
try {
const result = await enterpriseAddAccountApi({
tenantId: this.comEnterpriseInfo.tenantId,
packageId: this.comEnterpriseInfo.packageId,
nickName: array[count].nickName,
phonenumber: array[count].phonenumber,
});
if (result.code == 200) {
successCount++;
// 进度加载
} else {
elementMessageSingleton("error", result.msg);
}
} catch (error) {
console.log(error);
} finally {
count++;
}
}
this.dialogStatus = false;
} catch (error) {
console.log(error);
} finally {
loadingService.close();
successCount > 0 ? elementMessageSingleton("success", "添加账号成功") : null;
}
});
}
},
}
</script>
<style lang="scss" scoped>
.enterprise-add-account {
::v-deep .enterprise-add-account-dialog {
.el-dialog__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
.el-dialog__title {
font-size: 16px;
}
.el-dialog__headerbtn {
position: static;
display: flex;
align-items: center;
}
}
.el-dialog__body {
padding: 20px;
box-sizing: border-box;
.enterprise-add-account-inner {
.el-form {
display: flex;
justify-content: space-between;
.enterprise-add-account-list {
display: flex;
flex-direction: column;
position: relative;
& > .enterprise-add-account-item:first-of-type {
margin-top: 0px;
}
.enterprise-add-account-item {
display: flex;
align-items: center;
margin-top: 15px;
&:hover {
.remove-account-item {
opacity: 1;
& > i {
cursor: pointer;
}
}
}
.account-phone {
margin-left: 30px;
}
.el-form-item {
display: flex;
margin-bottom: 0px;
.el-form-item__content,
.el-form-item__label {
line-height: 32px;
}
.el-input {
.el-input__inner {
line-height: 32px;
height: 32px;
&::placeholder {
color: #c0c4cc !important;
font-weight: 400 !important;
font-size: 12px;
}
}
.el-input__suffix {
display: flex;
align-items: center;
.el-input__icon {
line-height: 32px;
}
}
}
.el-form-item__error {
padding-top: 2px;
}
}
.remove-account-item {
display: flex;
align-items: center;
margin-left: 15px;
opacity: 0;
transition: opacity 0.3s;
& > i {
font-size: 16px;
&:hover {
color: #f56c6c;
}
}
}
}
}
.add-account-btn {
line-height: 32px;
align-self: flex-start;
cursor: pointer;
color: #1890ff;
font-size: 14px;
span {
margin-left: 5px;
}
}
}
}
}
.el-dialog__footer {
padding: 0px;
.add-account-footer {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 20px;
border-top: 1px solid #eee;
box-sizing: border-box;
.el-button {
height: 32px;
line-height: 32px;
padding: 0px 20px;
box-sizing: border-box;
}
}
}
}
}
</style>
<template>
<div class="app-container">
<div class="app-container enterprise-management-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="企业名称" prop="companyName">
<el-input
v-model="queryParams.companyName"
placeholder="请输入企业名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.companyName" placeholder="请输入企业名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="用户名称" prop="contactUserName">
<el-input
v-model="queryParams.contactUserName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.contactUserName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="contactPhone">
<el-input
v-model="queryParams.contactPhone"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.contactPhone" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="账号状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_user_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.status" placeholder="角色状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_user_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
......@@ -51,23 +23,10 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>批量删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">批量删除</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
......@@ -87,7 +46,7 @@
<el-table-column label="续约结束时间" prop="expireTime" />
<el-table-column label="账号状态" align="center" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_user_status" :value="scope.row.status"/>
<dict-tag :options="dict.type.sys_user_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -95,100 +54,59 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="300">
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-button
size="mini"
type="text"
icon="el-icon-refresh"
@click="handleSync(scope.row)"
>同步</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-zoom-in"
@click="handleLook(scope.row)"
>查看</el-button>
<el-button size="mini" type="text" icon="el-icon-refresh" @click="handleSync(scope.row)">同步</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-user" @click="handleAddAccount(scope.row)">添加账号</el-button>
<el-button size="mini" type="text" icon="el-icon-zoom-in" @click="handleLook(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="企业名称" prop="companyName">
<el-input :disabled="disabled" v-model="form.companyName" placeholder="请输入企业名称"/>
<el-input :disabled="disabled" v-model="form.companyName" placeholder="请输入企业名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名称" prop="contactUserName">
<el-input :disabled="disabled" v-model="form.contactUserName" placeholder="请输入用户名称"/>
<el-input :disabled="disabled" v-model="form.contactUserName" placeholder="请输入用户名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="续约时间" prop="dateRange">
<el-date-picker :disabled="disabled"
v-model="form.dateRange"
style="width: 240px"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-date-picker :disabled="disabled" v-model="form.dateRange" style="width: 100%" value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码" prop="contactPhone">
<el-input :disabled="disabled" v-model="form.contactPhone" placeholder="请输手机号码"/>
<el-input :disabled="disabled" v-model="form.contactPhone" placeholder="请输手机号码" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="企业方案" prop="packageId">
<el-select :disabled="disabled"
v-model="form.packageId"
placeholder="企业方案"
clearable
style="width: 240px"
>
<el-option
v-for="dict in packageList"
:key="dict.packageId"
:label="dict.packageName"
:value="dict.packageId"
/>
<el-select :disabled="disabled" v-model="form.packageId" placeholder="企业方案" clearable style="width: 100%">
<el-option v-for="dict in packageList" :key="dict.packageId" :label="dict.packageName" :value="dict.packageId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="企业规模" prop="accountCount">
<el-input onkeyup="this.value=this.value.replace(/[^0-9]/g,'')" :disabled="disabled" v-model="form.accountCount" placeholder="请输入企业规模"/>
<el-input onkeyup="this.value=this.value.replace(/[^0-9]/g,'')" :disabled="disabled" v-model="form.accountCount"
placeholder="请输入企业规模" />
</el-form-item>
</el-col>
</el-row>
......@@ -196,11 +114,7 @@
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status" :disabled="disabled">
<el-radio
v-for="dict in dict.type.sys_user_status"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_user_status" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -212,11 +126,7 @@
</div>
</el-dialog>
<el-dialog
title="权限同步"
:visible.sync="dialogVisible1"
custom-class="sync"
width="400px">
<el-dialog title="权限同步" :visible.sync="dialogVisible1" custom-class="sync" width="400px">
<p style="font-size: 16px;"><i class="el-icon-warning-outline" style="margin-right: 8px;"></i>是否确认同步?</p>
<p>温馨提示:此操作可能会影响正在使用的用户,建议合理安排同步时间</p>
<div slot="footer" class="dialog-footer">
......@@ -224,26 +134,37 @@
<el-button type="primary" @click="handleConfirm()" :loading="state">同步</el-button>
</div>
</el-dialog>
<!-- 添加账号 -->
<enterprise-add-account :openStatus="addAccountDialog" :enterpriseInfo="addAccountEnterpriseInfo" @dialogClose="enterpriseDialogClose"
:addAccountCount="addAccountCount"></enterprise-add-account>
</div>
</template>
<script>
import {
import {
deleteTenant,
editTenant,
getTenant,
getTenantList,
saveTenant,
selectTenant,
syncTenantPackage
} from '@/api/enterpriseManagement/enterpriseManagement'
syncTenantPackage,
getEnterpriseAddAccountCountApi
} from '@/api/enterpriseManagement/enterpriseManagement';
import EnterpriseAddAccount from "./components/EnterpriseAddAccount";
export default {
export default {
name: "EnterpriseManagement",
dicts: ['sys_user_status'],
components: {
EnterpriseAddAccount
},
data() {
return {
disabled:false,
disabled: false,
// 遮罩层
loading: true,
// 选中数组
......@@ -276,7 +197,7 @@
form: {},
// 表单校验
rules: {
contactPhone : [
contactPhone: [
{ required: true, message: "手机号码不能为空", trigger: "blur" },
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
......@@ -304,20 +225,55 @@
],
},
//企业方案列表
packageList:[],
syncItem:{},
state:false,
packageList: [],
syncItem: {},
state: false,
// 添加账号弹窗
addAccountDialog: false,
// 企业信息
addAccountEnterpriseInfo: {},
// 该租户下已经创建账号数量 默认1个
addAccountCount: 1
};
},
created() {
this.getList();
},
methods: {
enterpriseDialogClose() {
this.addAccountDialog = false;
this.getAccountCount(this.addAccountEnterpriseInfo.tenantId);
this.addAccountEnterpriseInfo = this.$options.data.call(this).addAccountEnterpriseInfo;
},
async getAccountCount(tenantId) {
try {
const countResult = await getEnterpriseAddAccountCountApi(tenantId);
if (countResult.code == 200) {
this.addAccountCount = countResult.data;
}
} catch (error) {
console.log(error);
}
},
// 新增用户账号
async handleAddAccount(row) {
try {
if (!row.tenantId) return this.$message.warning("缺少租户ID");
await this.getAccountCount(row.tenantId);
if (this.addAccountCount >= 6) {
return this.$message.warning("该租户下已经添加过五个账号");
}
this.addAccountEnterpriseInfo = row;
this.addAccountDialog = true;
} catch (error) {
console.log(error);
}
},
//获取企业方案列表
getpack(){
selectTenant().then(res=>{
if(res.code = 200){
this.packageList = res.data
getpack() {
selectTenant().then(res => {
if (res.code = 200) {
this.packageList = res.data;
// this.packageList.forEach(item=>{
// if(item.status == '0'){
// item.disabled = false
......@@ -326,14 +282,14 @@
// }
// })
}
})
});
},
/** 查询角色列表 */
getList() {
this.loading = true;
getTenantList(this.queryParams).then(response => {
this.tenantList = response.rows;
this.total = response.total;
this.tenantList = response.rows ? response.rows : [];
this.total = response.total ? response.total : 0;
this.loading = false;
}
);
......@@ -371,99 +327,98 @@
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!=1
this.multiple = !selection.length
this.ids = selection.map(item => item.id);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.disabled = false
this.disabled = false;
this.reset();
this.open = true;
this.title = "添加企业";
this.getpack()
this.getpack();
},
/** 同步弹窗显示 */
handleSync(row) {
this.dialogVisible1=true;
this.syncItem=row;
this.dialogVisible1 = true;
this.syncItem = row;
},
/** 同步按钮操作 */
handleConfirm() {
let _this = this
this.state=true
syncTenantPackage({tenantId:this.syncItem.tenantId,packageId:this.syncItem.packageId}).then(res => {
if(res.code === 200){
this.state=false
let _this = this;
this.state = true;
syncTenantPackage({ tenantId: this.syncItem.tenantId, packageId: this.syncItem.packageId }).then(res => {
if (res.code === 200) {
this.state = false;
_this.$message.success(res.msg);
this.dialogVisible1=false;
this.dialogVisible1 = false;
}
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.disabled = false
this.disabled = false;
this.reset();
const id = row.id
this.getpack()
const id = row.id;
this.getpack();
getTenant(id).then(response => {
this.form = response.data;
this.form.dateRange = [response.data.startTime,response.data.expireTime]
this.form.dateRange = [response.data.startTime, response.data.expireTime];
this.open = true;
this.title = this.disabled == true?'查看企业':"修改企业";
this.title = this.disabled == true ? '查看企业' : "修改企业";
});
},
//查看
handleLook(row){
this.handleUpdate(row)
this.disabled = true
handleLook(row) {
this.handleUpdate(row);
this.disabled = true;
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.$refs["form"].validate(valid => {
if (valid) {
const text = this.form.id ? "正在修改企业数据,请耐心等待" : "正在添加企业数据,请耐心等待";
const loading = this.$loading({
lock: true,
text: '数据处理中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
text,
});
this.form.startTime = this.form.dateRange[0]
this.form.expireTime = this.form.dateRange[1]
let thistime = new Date(this.form.expireTime).getTime()
if(thistime < new Date().getTime()){
this.$message.error('不能选择过去时间!')
return false
this.form.startTime = this.form.dateRange[0];
this.form.expireTime = this.form.dateRange[1];
let thistime = new Date(this.form.expireTime).getTime();
if (thistime < new Date().getTime()) {
this.$message.error('不能选择过去时间!');
return false;
}
if (this.form.id != undefined) {
editTenant(this.form).then(response => {
if (response.code == 200) {
this.$modal.msgSuccess('修改成功')
this.open = false
this.getList()
loading.close()
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
loading.close();
} else {
this.$modal.msgError(response.msg)
this.$modal.msgError(response.msg);
loading.close();
}
}).catch(response => {
this.$modal.msgError(response.msg)
this.$modal.msgError(response.msg);
loading.close();
});
} else {
saveTenant(this.form).then(response => {
if (response.code == 200){
if (response.code == 200) {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
loading.close();
}else{
this.$modal.msgError(response.msg)
} else {
this.$modal.msgError(response.msg);
loading.close();
}
}).catch(response => {
this.$modal.msgError(response.msg)
this.$modal.msgError(response.msg);
loading.close();
});
}
......@@ -473,29 +428,41 @@
/** 删除按钮操作 */
handleDelete(row) {
const Ids = row.id || this.ids;
let _this = this
this.$modal.confirm('是否确认删除选中的企业数据项?').then(function() {
deleteTenant(Ids).then(res=>{
if(res.code == 200){
let _this = this;
this.$modal.confirm('是否确认删除选中的企业数据项?').then(function () {
deleteTenant(Ids).then(res => {
if (res.code == 200) {
_this.getList();
_this.$message.success("删除成功");
}else{
} else {
_this.$message.error(res.msg);
}
});
}).catch(() => {});
}).catch(() => { });
},
}
};
};
</script>
<style lang="scss" scoped>
::v-deep .sync{
.el-dialog__header{
::v-deep .sync {
.el-dialog__header {
border-bottom: 1px solid #eee;
}
.el-dialog__body{
padding: 15px 20px
}
.el-dialog__body {
padding: 15px 20px;
}
}
.enterprise-management-container {
width: 100%;
height: 100%;
margin: 0px;
padding: 16px 24px;
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
overflow: auto;
}
</style>
......@@ -2,13 +2,7 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="方案名称" prop="packageName">
<el-input
v-model="queryParams.packageName"
placeholder="请输入方案名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.packageName" placeholder="请输入方案名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
......@@ -18,23 +12,10 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>批量删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">批量删除</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
......@@ -49,13 +30,7 @@
<el-table-column label="方案名称" prop="packageName" :show-overflow-tooltip="true" width="150" />
<el-table-column label="备注" prop="remark" width="400">
<template slot-scope="scope">
<el-popover
title=""
:visible-arrow="false"
width="400"
trigger="hover"
popper-class="popovers"
:content="scope.row.remark">
<el-popover title="" :visible-arrow="false" width="400" trigger="hover" popper-class="popovers" :content="scope.row.remark">
<div class="over" slot="reference">{{scope.row.remark}}</div>
</el-popover>
......@@ -63,7 +38,7 @@
</el-table-column>
<el-table-column label="方案状态" align="center" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.ent_pro_status" :value="scope.row.status"/>
<dict-tag :options="dict.type.ent_pro_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -73,24 +48,9 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-zoom-in"
@click="handleLook(scope.row)"
>查看</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-zoom-in" @click="handleLook(scope.row)">查看</el-button>
<!--<el-button-->
<!--size="mini"-->
<!--type="text"-->
......@@ -101,13 +61,7 @@
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改租户套餐配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
......@@ -124,16 +78,8 @@
<el-checkbox :disabled="disabled" v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
<el-checkbox :disabled="disabled" v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
<el-checkbox :disabled="disabled" v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="menuOptions"
show-checkbox
ref="menu"
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候"
:props="defaultProps"
></el-tree>
<el-tree class="tree-border" :data="menuOptions" show-checkbox ref="menu" node-key="id" :check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候" :props="defaultProps"></el-tree>
</el-form-item>
<el-form-item label="备注">
<el-input :disabled="disabled" v-model="form.remark" maxlength="50" type="textarea" placeholder="请输入文字(50字以内)"></el-input>
......@@ -148,17 +94,17 @@
</template>
<script>
import { qytreeselect} from "@/api/system/menu";
import { qytreeselect } from "@/api/system/menu";
import { addTenantPackage ,getTenantPackage,detailTenantPackage,saveTenantPackage,deleteTenantPackage} from "@/api/enterpriseManagement/enterpriseManagement";
import { addTenantPackage, getTenantPackage, detailTenantPackage, saveTenantPackage, deleteTenantPackage } from "@/api/enterpriseManagement/enterpriseManagement";
export default {
export default {
name: "Programme",
dicts: ['ent_pro_status'],
data() {
return {
disabled:false,
disabled: false,
// 遮罩层
loading: true,
// 选中数组
......@@ -192,14 +138,14 @@
queryParams: {
pageNum: 1,
pageSize: 10,
packageName:'',
packageName: '',
},
// 表单参数
form: {},
defaultProps: {
children: "children",
label: "label",
disabled:this.disabledFn
disabled: this.disabledFn
},
// 表单校验
rules: {
......@@ -220,15 +166,15 @@
this.getMenuTreeselect();
},
methods: {
disabledFn(){
return this.disabled
disabledFn() {
return this.disabled;
},
/** 查询方案列表 */
getList() {
this.loading = true;
getTenantPackage(this.queryParams).then(response => {
this.packList = response.rows;
this.total = response.total;
this.packList = response.rows ? response.rows : [];
this.total = response.total ? response.total : 0;
this.loading = false;
}
);
......@@ -265,7 +211,7 @@
packageId: undefined,
packageName: undefined,
remark: undefined,
menuCheckStrictly:true,
menuCheckStrictly: true,
status: "0",
menuIds: [],
};
......@@ -284,9 +230,9 @@
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.packageId)
this.single = selection.length!=1
this.multiple = !selection.length
this.ids = selection.map(item => item.packageId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
// 树权限(展开/折叠)
handleCheckedTreeExpand(value, type) {
......@@ -297,79 +243,79 @@
},
// 树权限(全选/全不选)
handleCheckedTreeNodeAll(value, type) {
this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []);
this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
},
// 树权限(父子联动)
handleCheckedTreeConnect(value, type) {
if (type == 'menu') {
this.form.menuCheckStrictly = value ? true: false;
this.form.menuCheckStrictly = value ? true : false;
} else if (type == 'dept') {
this.form.deptCheckStrictly = value ? true: false;
this.form.deptCheckStrictly = value ? true : false;
}
},
/** 新增按钮操作 */
handleAdd() {
this.disabled = false
this.disabled = false;
this.reset();
this.open = true;
this.title = "添加方案";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.disabled = false
this.disabled = false;
this.reset();
const packageId = row.packageId
const packageId = row.packageId;
detailTenantPackage(packageId).then(response => {
response.data.menuIds = response.data.menuIds.split(',')
response.data.menuIds = response.data.menuIds.split(',');
this.form = response.data;
this.open = true;
this.$nextTick(() => {
let checkedKeys = response.data.menuIds
let checkedKeys = response.data.menuIds;
// menuOptions
checkedKeys.forEach((v) => {
v = v.trim()
let nodes = this.$refs.menu.getNode(v)
if(nodes&&nodes.isLeaf && nodes.isLeaf == true){
this.$refs.menu.setChecked(v,true,true);
}else{
this.$refs.menu.setChecked(v,true,false);
v = v.trim();
let nodes = this.$refs.menu.getNode(v);
if (nodes && nodes.isLeaf && nodes.isLeaf == true) {
this.$refs.menu.setChecked(v, true, true);
} else {
this.$refs.menu.setChecked(v, true, false);
}
})
})
this.title = this.disabled == true?'查看方案':"修改方案";
});
});
this.title = this.disabled == true ? '查看方案' : "修改方案";
});
},
//查看
handleLook(row){
this.handleUpdate(row)
this.disabled = true
handleLook(row) {
this.handleUpdate(row);
this.disabled = true;
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.form.menuIds = this.getMenuAllCheckedKeys();
this.$refs["form"].validate(valid => {
if (valid) {
// return false
if (this.form.packageId != undefined) {
saveTenantPackage(this.form).then(response => {
if(response.code == 200){
if (response.code == 200) {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}else{
this.$message.error(response.msg)
} else {
this.$message.error(response.msg);
}
});
} else {
// this.form.menuIds = this.getMenuAllCheckedKeys();
addTenantPackage(this.form).then(response => {
if(response.code == 200){
if (response.code == 200) {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}else{
this.$message.error(response.msg)
} else {
this.$message.error(response.msg);
}
});
}
......@@ -379,34 +325,34 @@
/** 删除按钮操作 */
handleDelete(row) {
const packageIds = row.packageId || this.ids;
let _this = this
this.$modal.confirm('是否确认删除选中的方案数据项?').then(function() {
deleteTenantPackage(packageIds).then(res=>{
if(res.code == 200){
let _this = this;
this.$modal.confirm('是否确认删除选中的方案数据项?').then(function () {
deleteTenantPackage(packageIds).then(res => {
if (res.code == 200) {
_this.getList();
_this.$message.success("删除成功");
}else{
} else {
_this.$message.error(res.msg);
}
});
}).catch(() => {});
}).catch(() => { });
},
}
};
};
</script>
<style scoped lang="scss">
.over{
.over {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
</style>
<style lang="scss">
.popovers {
.popovers {
padding: 6px 12px !important;
line-height: 20px;
color: rgba(35, 35, 35, 0.80);
color: rgba(35, 35, 35, 0.8);
font-size: 12px;
}
}
</style>
......@@ -24,7 +24,6 @@
<el-form-item prop="captchaCode" v-if="captchaEnabled">
<el-input
v-model="dxform.captchaCode"
@focus="getCode"
auto-complete="off"
placeholder="请输入图形验证码"
style="width: 196px;float: left;"
......@@ -93,7 +92,6 @@
v-model="loginForm.code"
auto-complete="off"
placeholder="请输入图形验证码"
@focus="getCode"
style="width: 196px;float: left;"
@keyup.enter.native="handleLogin"
>
......
......@@ -13,7 +13,7 @@
</div>
<div class="flex-box query-ability">
<!--<span class="flex-box"><img src="@/assets/images/ability_vs.png">地区经济对比</span>-->
<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<!--<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>-->
</div>
</div>
<div class="table-item" ref="regionalStyle" id="regionalStyle">
......
......@@ -12,7 +12,7 @@
</el-form>
</div>
<div class="flex-box query-ability">
<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<!--<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>-->
</div>
</div>
<skeleton v-if="isSkeleton" style="padding: 16px"></skeleton>
......
......@@ -14,7 +14,7 @@
</el-form>
</div>
<div class="flex-box query-ability">
<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<!--<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>-->
</div>
</div>
<div class="table-item">
......
......@@ -41,7 +41,7 @@
<span class="total">{{tableDataTotal}}</span>
</div>
<div class="flex-box query-ability">
<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<!--<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>-->
</div>
</div>
<div class="table-item">
......
......@@ -26,7 +26,7 @@
</div>
<div class="flex-box query-ability">
<router-link to="/macro/economies?activeName=four" tag="a" class="a-link"><span class="flex-box"><img src="@/assets/images/ability_vs.png">地区经济对比</span></router-link>
<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<!--<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>-->
</div>
</div>
<skeleton v-if="isSkeleton" style="padding: 16px"></skeleton>
......
......@@ -142,7 +142,7 @@
</div>
<div class="flex-box query-ability">
<!--<span class="total">共{{tableDataTotal}}条</span>-->
<span class="flex-box" @click="handleMessage"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
<span class="flex-box" @click="clickDialog"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
</div>
</div>
<div class="table-item">
......@@ -281,6 +281,7 @@
<span class="dialog-footer-btn2" @click="dialogVisible1 = false">关闭</span>
</div>
</el-dialog>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
......@@ -288,15 +289,15 @@
import {encodeStr} from "@/assets/js/common.js"
import skeleton from '../component/skeleton'
import dataRegion from '@/assets/json/dataRegion'
import { uipGroupData,urbanInvestmentPage,urbanInvestmentStatistics,claim,location,customerStatus,historyClaim,urbanInvestmentExport } from '@/api/macro/macro'
import api from '@/api/enterpriseData/enterpriseData.js';
import elementResizeDetectorMaker from "element-resize-detector"
import { uipGroupData,urbanInvestmentPage,urbanInvestmentStatistics,claim,location,customerStatus,historyClaim } from '@/api/macro/macro'
import { infoHeader } from '@/api/detail/party-a/index'
import Region from '../component/region'
import ExportDialog from "../../component/export-dialog"
export default {
name: 'Urban',
components: {
Region,skeleton
Region,skeleton,ExportDialog
},
data() {
return {
......@@ -341,7 +342,69 @@ export default {
dataQuery:{},
province:'',
provinceId:[],
isSkeleton:true
isSkeleton:true,
dataEXCEL:{},
exportData:{
title:'城投平台',
dialogExportVisible:false,
forData: [
{label: '公司名称', prop: 'companyName',slot: true,minWidth: '140'},
{label: '区域', prop: 'province', slot: true,minWidth: '160'},
{label: '招标数量', prop: 'biddingCount',slot: true,minWidth: '80'},
{label: '城投拿地', prop: 'landInfoCount', slot: true,minWidth: '80'},
{label: '供应商', prop: 'supplierCount',slot: true,minWidth: '100'},
{label: '债券余额(亿元)', prop: 'bondBalance',minWidth: '130'},
{label: '主体评级', prop: 'bratingSubjectLevel',minWidth: '80'},
{label: '行政级别', prop: 'uipExecutiveLevel',minWidth: '80'},
{label: '股东背景', prop: 'shareholderBg', slot: true,minWidth: '100'},
{label: '股权关系', prop: 'equityRelationship', slot: true,minWidth: '100'},
{label: '平台重要性', prop: 'platformImportance', slot: true,minWidth: '130'},
{label: '城投业务类型', prop: 'uipBusinessType', slot: true,minWidth: '130'},
{label: '实控人', prop: 'actualController', slot: true,minWidth: '140'},
{label: '最新报告期', prop: 'latestReportPeriod', slot: true,minWidth: '120'},
{label: '总资产(亿元)', prop: 'totalAssets', slot: true,minWidth: '120'},
{label: '归母净资产', prop: 'belongNetAssets', slot: true,minWidth: '120'},
],
exportTableData:[
{
companyName:'xxx有限公司',
province:'重庆-重庆市-永川区',
biddingCount:'64',
landInfoCount:'4',
supplierCount:'456',
bondBalance:'73',
bratingSubjectLevel:'AAA',
uipExecutiveLevel:'区县级',
shareholderBg:'城建',
equityRelationship:'直接控股',
platformImportance:'主要平台',
uipBusinessType:'综合性平台',
actualController:'xxx监督管理委员会',
latestReportPeriod:'2022-12-21',
totalAssets:'55.47',
belongNetAssets:'21.74',
},
{
companyName:'xxx有限公司',
province:'北京-北京市-大兴区',
biddingCount:'25',
landInfoCount:'2',
supplierCount:'465',
bondBalance:'61',
bratingSubjectLevel:'AAA',
uipExecutiveLevel:'区县级',
shareholderBg:'政府',
equityRelationship:'间接控股',
platformImportance:'一般平台',
uipBusinessType:'土地开发整理',
actualController:'xxx监督管理委员会',
latestReportPeriod:'2022-12-21',
totalAssets:'764.74',
belongNetAssets:'62.13',
},
],
exportEXCEL:{}
},
}
},
watch:{
......@@ -462,33 +525,6 @@ export default {
// this.isSkeleton = true
const params = { pageNum: this.pageIndex, pageSize: this.pageSize,type:Number(this.queryParams.radio)}
const param={}
// if(this.queryParams.address.length > 0){
// let arr = this.$refs.address.getCheckedNodes();
// let provinceCode = [],cityCode = [],countyCode = [];
// for (var i in arr) {
// if (arr[i].parent) {
// if (!arr[i].parent.checked) {
// arr[i].hasChildren && cityCode.push(arr[i].value);
// !arr[i].hasChildren && countyCode.push(arr[i].value);
// }
// } else {
// provinceCode.push(arr[i].value)
// }
// }
// if(provinceCode.length > 0){
// params.provinceIds=provinceCode
// param.provinceIds=provinceCode
// }
// if(cityCode.length > 0){
// params.cityIds=cityCode
// param.cityIds=cityCode
// }
// if(countyCode.length > 0){
// params.areaIds=countyCode
// param.areaIds=countyCode
// }
// }
if(this.provinceId.length > 0){
params.provinceIds=[this.provinceId[0]]
}
......@@ -534,7 +570,7 @@ export default {
if(this.queryParams.keyword){
params.keyword=this.queryParams.keyword
}
this.dataEXCEL=JSON.parse(JSON.stringify(params));
urbanInvestmentPage(params).then(res => {
this.isSkeleton = false;
this.tableLoading = false;
......@@ -807,7 +843,31 @@ export default {
// })
}
})
},
clickDialog(){
this.exportData.dialogExportVisible=true;
},
clickEXCEL(value) {
if(value > 2000){
return
}
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.pageNum
urbanInvestmentExport(this.dataEXCEL).then(res=>{
if(res.code === 200){
this.exportData.exportEXCEL=true;
}
})
},
cancel(){
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
},
}
</script>
......
......@@ -57,7 +57,8 @@ export default {
},
methods: {
linkListener(event) {
let { data } = event;
let { data, origin } = event;
if (origin != this.domain) return;
if (data.id) {
getUipIdByCid([data.id]).then(res => {
if (res.code == 200) {
......@@ -73,9 +74,7 @@ export default {
});
} else {
if (data.url) {
this.$tab.openPage(data.title, data.url).then(() => {
// 执行结束的逻辑
});
this.$tab.openPage(data.title, data.url);
}
}
},
......
......@@ -24,8 +24,8 @@
<!-- 列表 -->
<div class="table-data-list-container" v-else-if="!isLoadingData || !tableDataList.length">
<table-list-com :formColum="formColum" :queryParams="queryParams" :tableData="tableDataList" :tableDataTotal="tableDataTotal"
:needSelection="needSelection" :stickyHeader="{offsetTop:'48px',offsetBottom : '10px'}" @selectionChange="selectionChange"
@handle-current-change="pageCurrentChange" ref="tableListComParent">
:needSelection="needSelection" :cellClassName="cellClassName" :stickyHeader="{offsetTop:'48px',offsetBottom : '10px'}"
@selectionChange="selectionChange" @handle-current-change="pageCurrentChange" ref="tableListComParent">
<template slot="tenderAmountHeader">
<div class="tender-amount-header">
<span>投标金额(万元)</span>
......@@ -161,7 +161,8 @@ export default {
],
needSelection: {
flag: true,
width: "39px",
width: "46px",
align: "center"
},
// 查询参数
queryParams: {
......@@ -224,6 +225,12 @@ export default {
},
//方法集
methods: {
cellClassName({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0) {
return "need-selection-column";
}
return "";
},
async dataInit() {
try {
if (!this.notHasPermission) {
......@@ -517,6 +524,15 @@ export default {
}
}
}
::v-deep .el-table {
.need-selection-column {
.cell {
white-space: nowrap;
overflow: visible;
}
}
}
}
}
}
......
......@@ -93,8 +93,8 @@
<el-checkbox v-if="index<showNum" :label="item" :key="index">{{item}}</el-checkbox>
</template>
</el-checkbox-group>
<span class="more" v-if="showNum==10" @click="showNum=99">更多<img src="@/assets/images/more.png" alt=""></span>
<span class="more more1" v-if="showNum==99" @click="showNum=10">收起<img src="@/assets/images/more.png" alt=""></span>
<!--<span class="more" v-if="showNum==10" @click="showNum=99">更多<img src="@/assets/images/more.png" alt=""></span>-->
<!--<span class="more more1" v-if="showNum==99" @click="showNum=10">收起<img src="@/assets/images/more.png" alt=""></span>-->
</div>
</div>
<div class="content_item content_item_padding0">
......@@ -225,53 +225,7 @@
</el-pagination>
</div>
</div>
<el-dialog :visible.sync="dialogExportVisible" width="640px" append-to-body class="dialogExport">
<template slot="title">
<img class="tip-img" src="@/assets/images/icon.png" />数据导出
</template>
<div class="table-item">
<el-table :data="exportTableData">
<el-table-column prop="buildingProjectType" label="项目类型" width="80"></el-table-column>
<el-table-column prop="projectName" label="项目名称" width="220"></el-table-column>
<el-table-column prop="chargeDepartment" label="主管部门" min-width="170"></el-table-column>
<el-table-column prop="constructUnit" label="项目法人" min-width="170"></el-table-column>
<el-table-column prop="projectTotalInvestment" label="项目投资额" min-width="100"></el-table-column>
<el-table-column prop="domicile" label="项目地区" min-width="80"></el-table-column>
<el-table-column prop="projectScale" label="建设规模" min-width="430"></el-table-column>
<el-table-column prop="fileTitle" label="附件名称" min-width="200"></el-table-column>
<el-table-column prop="fileUrl" label="附件链接" min-width="360"></el-table-column>
</el-table>
</div>
<div class="input">
导出数量:
<el-input placeholder="" v-model="value" oninput="value=value.replace(/[^\d]/g,'')">
<template slot="append"></template>
</el-input>
<p v-if="value > 2000"><i class="el-icon-error"></i>最多支持导出2000条,如需更多联系大司空客服人员</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="clickEXCEL">确认导出</el-button>
<el-button @click="cancel">取消</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogExportVisible1" width="640px" append-to-body class="dialogExport">
<template slot="title">
<img class="tip-img" src="@/assets/images/icon.png" />
数据导出
</template>
<div class="content">
<img class="success" src="@/assets/images/success.png" />
<p class="p1">导出成功</p>
<p class="p2">
可在个人中心查看导出表格
<span @click="toUrl">前往个人中心</span>
</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="downloadFile(exportData.url,exportData.originalName)">下载表格</el-button>
<el-button @click="dialogExportVisible1 = false">取消</el-button>
</div>
</el-dialog>
<ExportDialog :data="exportData" v-if="exportData.dialogExportVisible" @clickEXCEL="clickEXCEL"></ExportDialog>
</div>
</template>
......@@ -280,41 +234,18 @@ import jsk_data from '../../../../../public/jsk.json';
import { encodeStr } from "@/assets/js/common.js";
import skeleton from '@/views/project/projectList/component/skeleton';
import api from '@/api/radar/radar.js';
import ExportDialog from "../../../component/export-dialog"
export default {
name: 'MajorProject',
components: { skeleton },
components: { skeleton,ExportDialog },
data() {
return {
encodeStr,
dialogExportVisible1: false,
exportTableData: [
{
"domicile": "江津区",
"chargeDepartment": "兴庆区商合局",
"constructUnit": '鞍钢股份有限公司',
"projectScale": "项目建设规划总面积约3000亩,其中商住用地面积2000亩,文化旅游综合用地约1000亩,打造集“市井民俗文化体验、休闲度假、亲子研学等”为一体的复合型文化旅游目的地,企业已完成项目规划方案。",
"fileTitle": "宁夏回族自治区银川市2023年度重点项目清单.pdf",
"fileUrl": "http://file.jiansheku.com/key_project/b9e22fbf2e409642aa97f8238e934272.pdf",
"buildingProjectType": "房建工程",
"projectTotalInvestment": "70000万元",
"projectName": "'上河堡'文旅综合体项目",
},
{
"domicile": "江津区",
"chargeDepartment": "国网重庆江津区供电公司",
"constructUnit": '国网重庆江津区供电公司',
"projectScale": "新建110kV变电站1座,主变容量2*50MVA,新建110kV线路20km",
"fileTitle": "重庆市江津区2023年度重点项目清单.xlsx",
"fileUrl": "http://file.jiansheku.com/key_project/4080bef69da03056d1db953698f4d807.xlsx",
"buildingProjectType": "电力工程",
"projectTotalInvestment": "5500万元",
"projectName": "重庆江津李市110kV输变电工程",
}],
exportData: {},
fieldshow: false,
fieldText: '默认排序',
field: 'year', //查询结果排序方式
fieldOptions: [{
fieldOptions: [
{
key: "year",
value: "默认排序",
status: true,
......@@ -415,17 +346,6 @@ export default {
},
],
showNum: 10,
importantProjectDto: {
province: [],
city: [],
area: [],
year: [],
fileTitle: [],
buildingProjectType: [],
keywordStr: ['projectName'],
keyword: '',
projectLevel: [],
},
provinceText: [],
pageFlag: true,
conditionsArr: [],
......@@ -436,7 +356,47 @@ export default {
limit: 20,
dataEXCEL: {},
dialogExportVisible: false,
value: ''
value: '',
exportData:{
title:'重点项目清单',
dialogExportVisible:false,
forData: [
{label: '项目类型', prop: 'buildingProjectType',slot: true,minWidth: '100'},
{label: '项目名称', prop: 'projectName', slot: true,minWidth: '200'},
{label: '主管部门', prop: 'chargeDepartment',slot: true,minWidth: '200'},
{label: '项目法人', prop: 'constructUnit', slot: true,minWidth: '150'},
{label: '项目投资额', prop: 'projectTotalInvestment',slot: true,minWidth: '100'},
{label: '项目地区', prop: 'domicile',minWidth: '100'},
{label: '建设规模', prop: 'projectScale',minWidth: '400'},
{label: '重点项目清单', prop: 'fileTitle',minWidth: '200'},
{label: '附件链接', prop: 'fileUrl', slot: true,minWidth: '300'},
],
exportTableData:[
{
"domicile": "广州",
"chargeDepartment": "广州市商合局",
"constructUnit": '鞍钢股份有限公司',
"projectScale": "项目建设规划总面积约3000亩,其中商住用地面积2000亩,文化旅游综合用地约1000亩,打造集“市井民俗文化体验、休闲度假、亲子研学等”为一体的复合型文化旅游目的地,企业已完成项目规划方案。",
"fileTitle": "广州2023年度重点项目清单.pdf",
"fileUrl": "http://file.jiansheku.com/key_project/b9e22fbf2e409642aa97f8238e934272.pdf",
"buildingProjectType": "房建工程",
"projectTotalInvestment": "1355万元",
"projectName": "广州市产业园区配套基础设施建设",
},
{
"domicile": "重庆",
"chargeDepartment": "国网重庆江津区供电公司",
"constructUnit": '国网重庆江津区供电公司',
"projectScale": "新建110kV变电站1座,主变容量2*50MVA,新建110kV线路20km",
"fileTitle": "重庆市2023年度重点项目清单.xlsx",
"fileUrl": "http://file.jiansheku.com/key_project/b9e22fbf2e409642aa97f8238e934272.pdf",
"buildingProjectType": "电力工程",
"projectTotalInvestment": "5056万元",
"projectName": "重庆江津市110kV输变电工程...",
},
],
exportEXCEL:{}
},
};
},
mounted() {
......@@ -523,7 +483,7 @@ export default {
},
importantProjectDto: data,
};
this.dataEXCEL = params;
this.dataEXCEL = JSON.parse(JSON.stringify(params));;
api.getImportantPage(params).then(res => {
this.isSkeleton = false;
if (res.code == 200) {
......@@ -658,23 +618,6 @@ export default {
this.importantProjectDto = obj;
this.$refs.transactionPriceShowPopper.hide();
},
transactionPricehandleCommand(command) {
if (command) {
this.$refs.transactionPriceShowPopper.hide();
var obj = JSON.parse(JSON.stringify(this.importantProjectDto));
this.startMoney = "";
this.endMoney = "";
if (command == "不限") {
obj.startMoney = "";
obj.endMoney = "";
} else {
obj.startMoney = command[0];
obj.endMoney = command[1];
}
this.importantProjectDto = obj;
}
},
addressListfn() {
var str = [];
for (let x = 0; x < 3; x++) {
......@@ -719,9 +662,6 @@ export default {
}
this.addressList = str;
},
reset() {
Object.assign(this.$data, this.$options.data.call(this)); //重置data
this.init();
......@@ -742,51 +682,29 @@ export default {
this.fieldOptions[index].status = true;
this.search();
},
clickDialog() {
this.dialogExportVisible = true;
clickDialog(){
this.exportData.dialogExportVisible=true;
},
clickEXCEL() {
if (this.value > 2000) {
return;
clickEXCEL(value) {
if(value > 2000){
return
}
this.dialogExportVisible = false;
if (this.value) {
this.dataEXCEL.page.limit = this.value;
} else {
this.dataEXCEL.page.limit = this.total > 2000 ? 2000 : this.total;
this.dataEXCEL.exportExeclName=this.exportData.title;
if(value){
this.dataEXCEL.pageSize=value
}else {
this.dataEXCEL.pageSize=2000;
}
delete this.dataEXCEL.page.page;
delete this.dataEXCEL.pageNum
api.radarExport(this.dataEXCEL).then(res => {
if (res.code === 200) {
this.dialogExportVisible1 = true;
this.value = '';
this.exportData = res.data;
if(res.code === 200){
this.exportData.exportEXCEL=true;
}
});
})
},
cancel() {
this.dialogExportVisible = false;
this.value = '';
},
downloadFile(url, fileName) {
const x = new XMLHttpRequest();
x.open("GET", url, true);
x.responseType = 'blob';
x.onload = function (e) {
const url = window.URL.createObjectURL(x.response);
const a = document.createElement('a');
a.href = url;
a.download = fileName;
a.click();
a.remove();
};
x.send();
},
toUrl() {
this.dialogExportVisible1 = false;
this.$router.push({
path: '/user/profile',
});
cancel(){
this.exportData.dialogExportVisible=false;
this.exportData.exportEXCEL={}
},
},
};
......@@ -811,6 +729,9 @@ export default {
.ename_input {
width: 240px;
margin-right: 20px;
::v-deep .el-input__inner::placeholder {
color: rgba(35, 35, 35, 0.2) !important;
}
}
.keyword_checkbox {
margin-top: 6px;
......@@ -819,7 +740,7 @@ export default {
display: inline-block;
}
.checkbox_1122 {
width: 1122px;
/*width: 1122px;*/
margin-right: 6px;
}
.el-checkbox {
......
<template>
<div class="iframe-com-ins" :style="stylesTransform(containerStyles)">
<iframe class="iframe-subsystem-ins" :src="url" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" width="100%"
:style="stylesTransform(iframeInsStyles)"></iframe>
</div>
</template>
<script>
export default {
name: "iframeComIns",
props: {
// 容器样式
styles: {
type: [Object, String],
default: () => ("")
},
// iframe样式
iframeStyles: {
type: [Object, String],
default: () => ("")
},
// 子系统链接地址
url: {
type: String,
default: ""
}
},
watch: {
"styles": {
handler(newValue) {
this.containerStyles = newValue;
},
deep: true
},
"iframeStyles": {
handler(newValue) {
console.log(newValue);
this.iframeInsStyles = newValue;
},
deep: true
},
},
data() {
return {
containerStyles: this.styles,
iframeInsStyles: this.iframeStyles
};
},
//可访问data属性
created() {
},
//计算集
computed: {
},
//方法集
methods: {
stylesTransform(stylesStr) {
try {
const styles = typeof stylesStr == "string" ? JSON.parse(stylesStr) : stylesStr;
return styles ? styles : {};
} catch (error) {
return {};
}
}
},
}
</script>
<style lang="scss" scoped>
.iframe-com-ins {
width: 100%;
height: 100%;
box-sizing: border-box;
.iframe-subsystem-ins {
width: 100%;
height: 100%;
}
}
</style>
<template>
<div class="subsystem-iframe-container">
<div @click="$router.push({path : '/subsystem',query : ({id:1})})">11</div>
<iframe-com-ins ref="subsystemIframeContainer" :iframeStyles="urlQueryParams.iframeStyles" :styles="urlQueryParams.styles"
:url="urlQueryParams.url"></iframe-com-ins>
</div>
</template>
<script>
import { getUrlSearchQuery } from "@/utils/";
import IframeComIns from "./components/IframeComIns";
import IframeTools from "@/utils/iframeTools";
export default {
name: "subsystemIframeContainer",
components: {
IframeComIns
},
data() {
return {
urlQueryParams: {},
iframeToolsIns: {}
};
},
//可访问data属性
created() {
console.log(this.$route);
console.log(getUrlSearchQuery());
this.Init();
},
beforeDestroy() {
if (this.iframeToolsIns) {
this.iframeToolsIns.clearRefreshTimer ? this.iframeToolsIns.clearRefreshTimer() : null;
}
},
//计算集
computed: {
......@@ -23,12 +33,15 @@ export default {
},
//方法集
methods: {
},
// 渲染方法
render(createElement) {
async Init() {
await this.$nextTick();
const dom = this.$refs["subsystemIframeContainer"].$el.querySelector("iframe");
const iframeTools = new IframeTools(dom);
this.iframeToolsIns = iframeTools;
this.urlQueryParams = iframeTools.queryParams;
console.log(this.urlQueryParams);
}
},
}
</script>
<style lang="scss" scoped>
......@@ -38,7 +51,6 @@ export default {
left: 0;
width: 100%;
height: 100%;
padding: 16px 24px;
box-sizing: border-box;
}
</style>
<template>
<div class="app-container">
<div class="app-container menu-manage-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="菜单名称" prop="menuName">
<el-input
v-model="queryParams.menuName"
placeholder="请输入菜单名称"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
......@@ -27,35 +17,16 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:menu:add']"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:menu:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-sort"
size="mini"
@click="toggleExpandAll"
>展开/折叠</el-button>
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">展开/折叠</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="menuList"
row-key="menuId"
:default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
<el-table v-if="refreshTable" v-loading="loading" :data="menuList" row-key="menuId" :default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100">
<template slot-scope="scope">
......@@ -67,7 +38,7 @@
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
......@@ -77,27 +48,9 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:menu:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
v-hasPermi="['system:menu:add']"
>新增</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:menu:remove']"
>删除</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:menu:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)" v-hasPermi="['system:menu:add']">新增</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:menu:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
......@@ -108,13 +61,7 @@
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单" prop="parentId">
<treeselect
v-model="form.parentId"
:options="menuOptions"
:normalizer="normalizer"
:show-count="true"
placeholder="选择上级菜单"
/>
<treeselect v-model="form.parentId" :options="menuOptions" :normalizer="normalizer" :show-count="true" placeholder="选择上级菜单" />
</el-form-item>
</el-col>
<el-col :span="24">
......@@ -128,20 +75,10 @@
</el-col>
<el-col :span="24" v-if="form.menuType != 'F'">
<el-form-item label="菜单图标" prop="icon">
<el-popover
placement="bottom-start"
width="460"
trigger="click"
@show="$refs['iconSelect'].reset()"
>
<el-popover placement="bottom-start" width="460" trigger="click" @show="$refs['iconSelect'].reset()">
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
<svg-icon
v-if="form.icon"
slot="prefix"
:icon-class="form.icon"
style="width: 25px;"
/>
<svg-icon v-if="form.icon" slot="prefix" :icon-class="form.icon" style="width: 25px;" />
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
</el-input>
</el-popover>
......@@ -206,7 +143,8 @@
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="queryParam">
<el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" />
<!-- <el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" /> -->
<el-button type="primary" size="mini" @click="editJsonValue">编辑路由参数</el-button>
<span slot="label">
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
<i class="el-icon-question"></i>
......@@ -238,11 +176,7 @@
显示状态
</span>
<el-radio-group v-model="form.visible">
<el-radio
v-for="dict in dict.type.sys_show_hide"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_show_hide" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -255,11 +189,7 @@
菜单状态
</span>
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -270,6 +200,20 @@
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- json编辑器 -->
<el-dialog title="路由参数编辑" :visible.sync="jsonDialog" width="700px" custom-class="json-editor-dialog" :close-on-click-modal="false"
@close="jsonDialogClose" :destroy-on-close="true">
<div class="json-editor-dialog-inner">
<dsk-json-editor :jsonValue="jsonValue" :defaultMode="defaultMode" :jsonReadOnly="jsonReadOnly" ref="dskJsonEditorContainer"
@jsonChange="jsonChange"></dsk-json-editor>
</div>
<div class="tool-bar">
<el-button type="primary" size="small" @click="saveJson">保存</el-button>
<el-button type="info" size="small" @click="jsonDialog = false">取消</el-button>
</div>
</el-dialog>
</div>
</template>
......@@ -278,11 +222,13 @@ import { listMenu, getMenu, delMenu, addMenu, updateMenu } from "@/api/system/me
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import IconSelect from "@/components/IconSelect";
import DskJsonEditor from "@/components/DskJsonEditor/";
import { jsonTraversal } from "@/utils";
export default {
name: "Menu",
dicts: ['sys_show_hide', 'sys_normal_disable'],
components: { Treeselect, IconSelect },
components: { Treeselect, IconSelect, DskJsonEditor },
data() {
return {
// 遮罩层
......@@ -306,7 +252,7 @@ export default {
menuName: undefined,
visible: undefined
},
// 表单参数
// 表单参数 查询参数字段值 保持 json编码转义后的字符串
form: {},
// 表单校验
rules: {
......@@ -319,13 +265,49 @@ export default {
path: [
{ required: true, message: "路由地址不能为空", trigger: "blur" }
]
}
},
// json编辑器值
jsonValue: {},
// 默认展示模式
defaultMode: "text",
// 是否只读
jsonReadOnly: false,
// json编辑器弹窗
jsonDialog: false,
};
},
created() {
this.getList();
},
methods: {
editJsonValue() {
this.jsonValue = this.form.queryParam ? jsonTraversal(JSON.parse(this.form.queryParam), true) : {};
this.jsonDialog = true;
},
// json编辑器弹窗关闭
jsonDialogClose() {
// 重置jsonValue值
this.jsonValue = this.$options.data.call(this).jsonValue;
},
// json编辑器值改变
jsonChange(value) {
this.jsonValue = value;
},
// 保存json数据
async saveJson() {
try {
// 验证格式是否正确
const validatorResult = await this.$refs["dskJsonEditorContainer"].validateJson();
// 通过验证
if (validatorResult.isPass) {
this.form.queryParam = validatorResult.value;
// 关闭弹窗
this.jsonDialog = false;
}
} catch (error) {
console.log(error);
}
},
// 选择图标
selected(name) {
this.form.icon = name;
......@@ -413,23 +395,37 @@ export default {
this.reset();
this.getTreeselect();
getMenu(row.menuId).then(response => {
this.form = response.data;
const data = response.data;
if (data.queryParam) {
const query = JSON.parse(data.queryParam);
// 转换为对象
const queryResult = jsonTraversal(JSON.parse(JSON.stringify(query)), true);
this.jsonValue = queryResult;
}
this.form = data;
this.open = true;
this.title = "修改菜单";
});
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.menuId != undefined) {
updateMenu(this.form).then(response => {
const params = JSON.parse(JSON.stringify(this.form));
if (params.queryParam) {
const query = JSON.parse(params.queryParam);
let queryResult = jsonTraversal(JSON.parse(JSON.stringify(query)), true);
queryResult = jsonTraversal(JSON.parse(JSON.stringify(queryResult)));
params.queryParam = JSON.stringify(queryResult);
}
if (params.menuId != undefined) {
updateMenu(params).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addMenu(this.form).then(response => {
addMenu(params).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
......@@ -440,13 +436,39 @@ export default {
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() {
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function () {
return delMenu(row.menuId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}).catch(() => { });
}
}
};
</script>
<style lang="scss" scoped>
.menu-manage-container {
::v-deep .json-editor-dialog {
height: 80%;
.el-dialog__header,
.el-dialog__body {
padding: 16px;
box-sizing: border-box;
}
.el-dialog__body {
height: calc(100% - 56px);
}
.json-editor-dialog-inner {
width: 100%;
height: calc(100% - 44px);
}
.tool-bar {
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 12px;
}
}
}
</style>
......@@ -2,22 +2,10 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
......@@ -27,47 +15,29 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="openSelectUser"
v-hasPermi="['system:role:add']"
>添加用户</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openSelectUser" v-hasPermi="['system:role:add']">添加用户</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-circle-close"
size="mini"
:disabled="multiple"
@click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']"
>批量取消授权</el-button>
<el-button type="danger" plain icon="el-icon-circle-close" size="mini" :disabled="multiple" @click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']">批量取消授权</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-close"
size="mini"
@click="handleClose"
>关闭</el-button>
<el-button type="warning" plain icon="el-icon-close" size="mini" @click="handleClose">关闭</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="用户编号" align="center" prop="userId" />
<!-- <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> -->
<el-table-column label="用户名称" prop="nickName" align="center" :show-overflow-tooltip="true" />
<el-table-column label="组织" align="center" prop="dept.deptName" :show-overflow-tooltip="true" />
<!-- <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> -->
<el-table-column label="手机" prop="phonenumber" align="center" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -77,24 +47,13 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-circle-close"
@click="cancelAuthUser(scope.row)"
v-hasPermi="['system:role:remove']"
>取消授权</el-button>
<el-button size="mini" type="text" icon="el-icon-circle-close" @click="cancelAuthUser(scope.row)"
v-hasPermi="['system:role:remove']">取消授权</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" />
</div>
</template>
......@@ -166,8 +125,8 @@ export default {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.userIds = selection.map(item => item.userId)
this.multiple = !selection.length
this.userIds = selection.map(item => item.userId);
this.multiple = !selection.length;
},
/** 打开授权用户表弹窗 */
openSelectUser() {
......@@ -176,23 +135,37 @@ export default {
/** 取消授权按钮操作 */
cancelAuthUser(row) {
const roleId = this.queryParams.roleId;
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function() {
return authUserCancel({ userId: row.userId, roleId: roleId });
}).then(() => {
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(async () => {
try {
const result = await authUserCancel({ userId: row.userId, roleId: roleId });
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {});
} else {
this.$message.error(result.msg);
}
} catch (error) {
}
}).catch(() => { });
},
/** 批量取消授权按钮操作 */
cancelAuthUserAll(row) {
const roleId = this.queryParams.roleId;
const userIds = this.userIds.join(",");
this.$modal.confirm('是否取消选中用户授权数据项?').then(function() {
return authUserCancelAll({ roleId: roleId, userIds: userIds });
}).then(() => {
this.$modal.confirm('是否取消选中用户授权数据项?').then(async () => {
try {
const result = await authUserCancelAll({ roleId: roleId, userIds: userIds });
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {});
} else {
this.$message.error(`${result.msg}账号下仅有一个角色,取消授权失败`);
}
} catch (error) {
}
}).catch(() => { });
}
}
};
......
......@@ -2,48 +2,19 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model="queryParams.roleName"
placeholder="请输入角色名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="权限字符" prop="roleKey">
<el-input
v-model="queryParams.roleKey"
placeholder="请输入权限字符"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.roleKey" placeholder="请输入权限字符" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.status" placeholder="角色状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
......@@ -53,64 +24,31 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:role:add']"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:role:edit']"
>修改</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['system:role:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:role:remove']"
>删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['system:role:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:role:export']"
>导出</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:role:export']">导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="角色编号" prop="roleId" width="120" />
<!-- <el-table-column label="角色编号" prop="roleId" width="120" /> -->
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
<el-table-column label="显示顺序" prop="roleSort" width="100" />
<el-table-column label="显示顺序" align="center" prop="roleSort" width="100" />
<el-table-column label="状态" align="center" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -120,34 +58,12 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:role:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:role:remove']"
>删除</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-check"
@click="handleDataScope(scope.row)"
v-hasPermi="['system:role:edit']"
>数据权限</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-user"
@click="handleAuthUser(scope.row)"
v-hasPermi="['system:role:edit']"
>分配用户</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-if="canDelete(scope.row.roleKey)"
v-hasPermi="['system:role:remove']">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-check" @click="handleDataScope(scope.row)"
v-hasPermi="['system:role:edit']">数据权限</el-button>
<el-button size="mini" type="text" icon="el-icon-user" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']">分配用户</el-button>
<!--<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']">-->
<!--<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>-->
<!--<el-dropdown-menu slot="dropdown">-->
......@@ -161,13 +77,7 @@
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改角色配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
......@@ -175,41 +85,30 @@
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
</el-form-item>
<el-form-item prop="roleKey">
<el-form-item prop="roleKey" :rules="!roleArray.includes('superadmin') ? {} : rules.roleKey">
<span slot="label">
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
权限字符
</span>
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
<el-input v-model="form.roleKey" :placeholder="!roleArray.includes('superadmin') ? '权限字符自动生成' : '请输入权限字符'"
:disabled="!roleArray.includes('superadmin')" />
</el-form-item>
<el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="menuOptions"
show-checkbox
ref="menu"
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候"
:props="defaultProps"
></el-tree>
<el-tree class="tree-border" :data="menuOptions" show-checkbox ref="menu" node-key="id" :check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候" :props="defaultProps"></el-tree>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
......@@ -232,29 +131,15 @@
</el-form-item>
<el-form-item label="权限范围">
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
<el-option
v-for="item in dataScopeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据权限" v-show="form.dataScope == 2">
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="deptOptions"
show-checkbox
default-expand-all
ref="dept"
node-key="id"
:check-strictly="!form.deptCheckStrictly"
empty-text="加载中,请稍候"
:props="defaultProps"
></el-tree>
<el-tree class="tree-border" :data="deptOptions" show-checkbox default-expand-all ref="dept" node-key="id"
:check-strictly="!form.deptCheckStrictly" empty-text="加载中,请稍候" :props="defaultProps"></el-tree>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
......@@ -268,6 +153,7 @@
<script>
import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role";
import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
import { mapGetters } from 'vuex';
export default {
name: "Role",
......@@ -358,7 +244,15 @@ export default {
created() {
this.getList();
},
computed: {
...mapGetters({
roleArray: "roles"
}),
},
methods: {
canDelete(role) {
return role != "tenantSuperAdmin" || (this.roleArray.includes("superadmin") && role == "tenantSuperAdmin");
},
/** 查询角色列表 */
getList() {
this.loading = true;
......@@ -403,18 +297,18 @@ export default {
/** 根据角色ID查询组织树结构 */
getDeptTree(roleId) {
return deptTreeSelect(roleId).then(response => {
this.deptOptions = response.depts;
this.deptOptions = response.data?.depts ? response.data?.depts : [];
return response;
});
},
// 角色状态修改
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用";
this.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function() {
this.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function () {
return changeRoleStatus(row.roleId, row.status);
}).then(() => {
this.$modal.msgSuccess(text + "成功");
}).catch(function() {
}).catch(function () {
row.status = row.status === "0" ? "1" : "0";
});
},
......@@ -464,9 +358,9 @@ export default {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.roleId)
this.single = selection.length!=1
this.multiple = !selection.length
this.ids = selection.map(item => item.roleId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
// 更多操作触发
handleCommand(command, row) {
......@@ -498,17 +392,17 @@ export default {
// 树权限(全选/全不选)
handleCheckedTreeNodeAll(value, type) {
if (type == 'menu') {
this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []);
this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
} else if (type == 'dept') {
this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []);
this.$refs.dept.setCheckedNodes(value ? this.deptOptions : []);
}
},
// 树权限(父子联动)
handleCheckedTreeConnect(value, type) {
if (type == 'menu') {
this.form.menuCheckStrictly = value ? true: false;
this.form.menuCheckStrictly = value ? true : false;
} else if (type == 'dept') {
this.form.deptCheckStrictly = value ? true: false;
this.form.deptCheckStrictly = value ? true : false;
}
},
/** 新增按钮操作 */
......@@ -521,19 +415,19 @@ export default {
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const roleId = row.roleId || this.ids
const roleId = row.roleId || this.ids;
const roleMenu = this.getRoleMenuTreeselect(roleId);
getRole(roleId).then(response => {
this.form = response.data;
this.open = true;
this.$nextTick(() => {
roleMenu.then(res => {
let checkedKeys = res.checkedKeys
let checkedKeys = res.checkedKeys;
checkedKeys.forEach((v) => {
this.$nextTick(()=>{
this.$refs.menu.setChecked(v, true ,false);
})
})
this.$nextTick(() => {
this.$refs.menu.setChecked(v, true, false);
});
});
});
});
this.title = "修改角色";
......@@ -541,32 +435,32 @@ export default {
},
/** 选择角色权限范围触发 */
dataScopeSelectChange(value) {
if(value !== '2') {
if (value !== '2') {
this.$refs.dept.setCheckedKeys([]);
}
},
/** 分配数据权限操作 */
handleDataScope(row) {
async handleDataScope(row) {
try {
this.reset();
const deptTreeSelect = this.getDeptTree(row.roleId);
getRole(row.roleId).then(response => {
this.form = response.data;
const res = await this.getDeptTree(row.roleId);
const result = await getRole(row.roleId);
this.form = result.data;
this.openDataScope = true;
this.$nextTick(() => {
deptTreeSelect.then(res => {
this.$refs.dept.setCheckedKeys(res.checkedKeys);
});
});
this.title = "分配数据权限";
});
await this.$nextTick();
this.$refs.dept.setCheckedKeys(res.checkedKeys ? res.checkedKeys : []);
} catch (error) {
console.log(error);
}
},
/** 分配用户操作 */
handleAuthUser: function(row) {
handleAuthUser: function (row) {
const roleId = row.roleId;
this.$router.push("/system/role-auth/user/" + roleId);
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.roleId != undefined) {
......@@ -588,7 +482,7 @@ export default {
});
},
/** 提交按钮(数据权限) */
submitDataScope: function() {
submitDataScope: function () {
if (this.form.roleId != undefined) {
this.form.deptIds = this.getDeptAllCheckedKeys();
dataScope(this.form).then(response => {
......@@ -601,18 +495,25 @@ export default {
/** 删除按钮操作 */
handleDelete(row) {
const roleIds = row.roleId || this.ids;
this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function() {
return delRole(roleIds);
}).then(() => {
this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(async () => {
try {
const result = await delRole(roleIds);
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
} else {
this.$message.error(result.msg);
}
} catch (error) {
}
}).catch(() => { });
},
/** 导出按钮操作 */
handleExport() {
this.download('system/role/export', {
...this.queryParams
}, `role_${new Date().getTime()}.xlsx`)
}, `role_${new Date().getTime()}.xlsx`);
}
}
};
......
......@@ -26,9 +26,11 @@
<el-row>
<el-table @row-click="clickRow" ref="table" :data="userList" @selection-change="handleSelectionChange" height="260px">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<!-- <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> -->
<el-table-column label="用户编号" align="center" prop="userId" />
<el-table-column label="用户名称" prop="nickName" align="center" :show-overflow-tooltip="true" />
<el-table-column label="组织" align="center" prop="dept.deptName" :show-overflow-tooltip="true" />
<!-- <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> -->
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
......
'use strict'
const path = require('path')
'use strict';
const path = require('path');
function resolve(dir) {
return path.join(__dirname, dir)
return path.join(__dirname, dir);
}
const CompressionPlugin = require('compression-webpack-plugin')
const CompressionPlugin = require('compression-webpack-plugin');
const name = process.env.VUE_APP_TITLE || '数字化经营履约全生命链路管理系统' // 网页标题
const name = process.env.VUE_APP_TITLE || '数字化经营履约全生命链路管理系统'; // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口
const port = process.env.port || process.env.npm_config_port || 80; // 端口
// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档
module.exports = {
transpileDependencies: ['json-editor-vue'],
// 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
......@@ -74,14 +75,14 @@ module.exports = {
],
},
chainWebpack(config) {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
config.plugins.delete('preload'); // TODO: need test
config.plugins.delete('prefetch'); // TODO: need test
// set svg-sprite-loader
config.module
.rule('svg')
.exclude.add(resolve('src/assets/icons'))
.end()
.end();
config.module
.rule('icons')
.test(/\.svg$/)
......@@ -92,7 +93,15 @@ module.exports = {
.options({
symbolId: 'icon-[name]'
})
.end();
config.module
.rule("mjs")
.test(/\.mjs$/)
.include.add(/node_modules/)
.end()
.type("javascript/auto");
config
.when(process.env.NODE_ENV !== 'development',
......@@ -104,7 +113,7 @@ module.exports = {
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}])
.end()
.end();
config
.optimization.splitChunks({
chunks: 'all',
......@@ -128,13 +137,13 @@ module.exports = {
reuseExistingChunk: true
}
}
})
});
config.optimization.runtimeChunk('single'),
{
from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件
to: './' //到根目录下
};
}
);
}
)
}
}
};
\ No newline at end of file
package com.dsk.system.domain.bo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.TableName;
import com.dsk.common.annotation.Sensitive;
import com.dsk.common.core.validate.AddGroup;
import com.dsk.common.core.validate.EditGroup;
import com.dsk.common.enums.SensitiveStrategy;
import com.dsk.common.tenant.core.TenantEntity;
import com.dsk.common.xss.Xss;
import com.dsk.system.domain.SysDept;
import com.dsk.system.domain.SysRole;
import com.dsk.system.domain.SysUser;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
/**
* 用户对象 sys_user
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class SysTenantAdminBo extends TenantEntity {
/**
* 租户ID
*/
@NotNull(message = "租户ID不能为空", groups = AddGroup.class)
private String tenantId;
/**
* 用户昵称
*/
@Xss(message = "用户昵称不能包含脚本字符")
@NotBlank(message = "用户昵称不能为空")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
private String nickName;
/**
* 手机号码
*/
@Xss(message = "用户昵称不能包含脚本字符")
@NotBlank(message = "手机号码不能为空", groups = AddGroup.class)
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phonenumber;
/**
* 租户套餐编号
*/
@NotNull(message = "租户套餐不能为空", groups = AddGroup.class)
private Long packageId;
}
......@@ -2,6 +2,7 @@ package com.dsk.system.service;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.system.domain.bo.SysTenantAdminBo;
import com.dsk.system.domain.bo.SysTenantBo;
import com.dsk.system.domain.vo.SysTenantVo;
......@@ -44,6 +45,14 @@ public interface ISysTenantService {
*/
Boolean insertByBo(SysTenantBo bo);
/**
* 新增企业普通管理员账号
*
* @param tenantAdminBo 用户信息
* @return 结果
*/
Boolean addTenantAdmin(SysTenantAdminBo tenantAdminBo);
/**
* 校验租户是否允许操作
*/
......
......@@ -3,6 +3,7 @@ package com.dsk.system.service;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.system.domain.SysUser;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.system.domain.bo.SysTenantAdminBo;
import com.dsk.system.domain.vo.SysUserImportVo;
import java.util.List;
......@@ -13,7 +14,13 @@ import java.util.List;
* @author Lion Li
*/
public interface ISysUserService {
/**
* 根据租户ID查询大司空超管or租户管理员为其创建的企业管理员和管理员账号数量
*
* @param tenantId 租户ID
* @return 该企业下企业管理员和管理员账号数量
*/
Long queryTenantAdminNumCreatedByDSK(Long tenantId);
TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery);
......@@ -97,6 +104,14 @@ public interface ISysUserService {
*/
boolean checkPhoneUnique(SysUser user);
/**
* 校验企业普通管理员手机号码是否唯一
*
* @param tenantAdminBo 用户信息
* @return 结果
*/
boolean checkTenantAdminPhoneUnique(SysTenantAdminBo tenantAdminBo);
/**
* 校验email是否唯一
*
......
......@@ -112,13 +112,8 @@ public class SysLoginService {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
} else if (sysUsers.size() > 1) {
//处理存在多个用户的情况,且不存在正常账号, 取一个最新租户
SysUser sysUser = null;
for (SysUser user : sysUsers) {
}
sysUsers.get(0);
//处理存在多个用户的情况,取一个最新租户
SysUser sysUser = sysUsers.get(0);
if (ObjectUtil.isEmpty(sysUser)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
......@@ -561,17 +556,19 @@ public class SysLoginService {
List<SysUser> sysUsers = null;
if (ReUtil.isMatch(RegexPool.MOBILE, username)) {
// LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<SysUser>()
// .select(SysUser::getUserName, SysUser::getStatus, SysUser::getTenantId)
// .eq(SysUser::getPhonenumber, username)
// .orderByDesc(SysUser::getUserId);
sysUsers = userMapper.selectUserByTenantPhone(username);
LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserName, SysUser::getStatus, SysUser::getTenantId,SysUser::getDelFlag)
.eq(SysUser::getPhonenumber, username)
.orderByDesc(SysUser::getUserId);
// sysUsers = userMapper.selectUserByTenantPhone(username);
sysUsers = userMapper.selectList(lqw);
} else {
// LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<SysUser>()
// .select(SysUser::getUserName, SysUser::getStatus, SysUser::getTenantId)
// .eq(SysUser::getUserName, username)
// .orderByDesc(SysUser::getUserId);
sysUsers = userMapper.selectUserByTenantUsername(username);
LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserName, SysUser::getStatus, SysUser::getTenantId)
.eq(SysUser::getUserName, username)
.orderByDesc(SysUser::getUserId);
// sysUsers = userMapper.selectUserByTenantUsername(username);
sysUsers = userMapper.selectList(lqw);
}
return sysUsers;
});
......
......@@ -16,6 +16,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsk.common.constant.CacheNames;
import com.dsk.common.constant.Constants;
import com.dsk.common.constant.TenantConstants;
import com.dsk.common.constant.UserConstants;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.domain.entity.SysDictData;
import com.dsk.common.core.domain.entity.SysDictType;
......@@ -26,6 +27,7 @@ import com.dsk.common.utils.PasswordUtils;
import com.dsk.common.utils.StringUtils;
import com.dsk.common.utils.redis.RedisUtils;
import com.dsk.system.domain.*;
import com.dsk.system.domain.bo.SysTenantAdminBo;
import com.dsk.system.domain.bo.SysTenantBo;
import com.dsk.system.domain.vo.SysTenantVo;
import com.dsk.system.mapper.*;
......@@ -180,7 +182,9 @@ public class ISysTenantServiceImpl implements ISysTenantService {
bo.setId(add.getId());
// 根据套餐创建角色
Long roleId = createTenantRole(tenantId, bo.getPackageId());
Long roleId = createTenantRole(tenantId, bo.getPackageId(),
TenantConstants.TENANT_SUPER_ADMIN_ROLE_NAME,
TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY);
// 创建部门: 公司名是部门名称
SysDept dept = new SysDept();
......@@ -268,6 +272,86 @@ public class ISysTenantServiceImpl implements ISysTenantService {
return true;
}
/**
* 新增企业普通管理员账号
*
* @param tenantAdminBo 用户信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean addTenantAdmin(SysTenantAdminBo tenantAdminBo) {
String tenantId = tenantAdminBo.getTenantId();
//获取部门ID
Long deptId = deptMapper.selectOne(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getTenantId, tenantId)).getDeptId();
SysRole sysRole = roleMapper.selectOne(new LambdaQueryWrapper<SysRole>()
.eq(SysRole::getStatus, UserConstants.ROLE_NORMAL)
.eq(SysRole::getDelFlag, UserConstants.ROLE_NORMAL)
.eq(SysRole::getTenantId, tenantId)
.eq(SysRole::getRoleKey, TenantConstants.TENANT_ADMIN_ROLE_KEY));
Long roleId = null;
//校验当前企业是否已存在普通管理员角色
if (ObjectUtil.isNull(sysRole)) {
//不存在,则根据套餐创建角色
roleId = createTenantRole(tenantId, tenantAdminBo.getPackageId(),
TenantConstants.TENANT_ADMIN_ROLE_NAME,
TenantConstants.TENANT_ADMIN_ROLE_KEY);
// 角色和部门关联表
SysRoleDept roleDept = new SysRoleDept();
roleDept.setRoleId(roleId);
roleDept.setDeptId(deptId);
roleDeptMapper.insert(roleDept);
} else {
roleId = sysRole.getRoleId();
}
// 创建系统用户
SysUser user = new SysUser();
user.setTenantId(tenantId);
user.setPhonenumber(tenantAdminBo.getPhonenumber());
//默认新增用户名为手机号
user.setUserName(tenantAdminBo.getPhonenumber());
user.setNickName(tenantAdminBo.getNickName());
//生成8位随机密码
String password = PasswordUtils.generatePwd(8);
user.setPassword(BCrypt.hashpw(password));
user.setDeptId(deptId);
user.setCreateTime(new DateTime());
userMapper.insert(user);
// 用户和角色关联表
SysUserRole userRole = new SysUserRole();
userRole.setUserId(user.getUserId());
userRole.setRoleId(roleId);
userRoleMapper.insert(userRole);
List<SysConfig> sysConfigList = configMapper.selectList(
new LambdaQueryWrapper<SysConfig>()
.eq(SysConfig::getTenantId, TenantConstants.DEFAULT_TENANT_ID)
.eq(SysConfig::getConfigType, "Y"));
for (SysConfig config : sysConfigList) {
config.setConfigId(null);
config.setTenantId(tenantId);
}
configMapper.insertBatch(sysConfigList);
//管理员新增成功,发送短信通知用户
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("company", tenantAdminBo.getNickName());
map.put("pwd", password);
SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
SmsResponse smsResponse = smsBlend.sendMessage(tenantAdminBo.getPhonenumber(), "SMS_463175230", map);
if (!"OK".equals(smsResponse.getCode())) {
log.error("新增租户通知短信发送异常 => {}", smsResponse);
}
return true;
}
/**
* 生成租户id
*
......@@ -291,7 +375,7 @@ public class ISysTenantServiceImpl implements ISysTenantService {
* @param packageId 租户套餐id
* @return 角色id
*/
private Long createTenantRole(String tenantId, Long packageId) {
private Long createTenantRole(String tenantId, Long packageId, String roleName, String roleKey) {
// 获取租户套餐
SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId);
if (ObjectUtil.isNull(tenantPackage)) {
......@@ -303,8 +387,8 @@ public class ISysTenantServiceImpl implements ISysTenantService {
// 创建角色
SysRole role = new SysRole();
role.setTenantId(tenantId);
role.setRoleName(TenantConstants.TENANT_ADMIN_ROLE_NAME);
role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY);
role.setRoleName(roleName);
role.setRoleKey(roleKey);
role.setRoleSort(1);
role.setStatus(TenantConstants.NORMAL);
roleMapper.insert(role);
......@@ -386,7 +470,7 @@ public class ISysTenantServiceImpl implements ISysTenantService {
List<Long> roleIds = new ArrayList<>(roles.size() - 1);
List<Long> menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong);
roles.forEach(item -> {
if (TenantConstants.TENANT_ADMIN_ROLE_KEY.equals(item.getRoleKey())) {
if (TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY.equals(item.getRoleKey())) {
List<SysRoleMenu> roleMenus = new ArrayList<>(menuIds.size());
menuIds.forEach(menuId -> {
SysRoleMenu roleMenu = new SysRoleMenu();
......
......@@ -199,7 +199,7 @@ public class SysRoleServiceImpl implements ISysRoleService {
// 新增不允许使用 管理员标识符
if (ObjectUtil.isNull(role.getRoleId())
&& StringUtils.equalsAny(role.getRoleKey(),
TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.TENANT_ADMIN_ROLE_KEY)) {
TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY)) {
throw new ServiceException("不允许使用系统内置管理员角色标识符!");
}
// 修改不允许修改 管理员标识符
......@@ -208,7 +208,7 @@ public class SysRoleServiceImpl implements ISysRoleService {
// 如果标识符不相等 判断为修改了管理员标识符
if (!StringUtils.equals(sysRole.getRoleKey(), role.getRoleKey())
&& StringUtils.equalsAny(sysRole.getRoleKey(),
TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.TENANT_ADMIN_ROLE_KEY)) {
TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY)) {
throw new ServiceException("不允许修改系统内置管理员角色标识符!");
}
}
......@@ -381,7 +381,7 @@ public class SysRoleServiceImpl implements ISysRoleService {
public int deleteRoleByIds(Long[] roleIds) {
for (Long roleId : roleIds) {
SysRole role = selectRoleById(roleId);
if ("admin".equals(role.getRoleKey())) {
if (TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY.equals(role.getRoleKey())) {
throw new ServiceException("不允许删除企业管理员角色!");
}
checkRoleAllowed(role);
......@@ -475,7 +475,7 @@ public class SysRoleServiceImpl implements ISysRoleService {
//查询企业管理员角色ID
List<SysRole> sysRoles = selectRoleAll();
for (SysRole role : sysRoles) {
if ("admin".equals(role.getRoleKey())) {
if (TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY.equals(role.getRoleKey())) {
adminRoleId = role.getRoleId();
break;
}
......
......@@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsk.common.constant.CacheNames;
import com.dsk.common.constant.TenantConstants;
import com.dsk.common.constant.UserConstants;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.page.TableDataInfo;
......@@ -25,6 +26,7 @@ import com.dsk.common.utils.StreamUtils;
import com.dsk.common.utils.StringUtils;
import com.dsk.common.utils.ValidatorUtils;
import com.dsk.system.domain.*;
import com.dsk.system.domain.bo.SysTenantAdminBo;
import com.dsk.system.domain.vo.SysUserImportVo;
import com.dsk.system.mapper.*;
import com.dsk.system.service.ISysUserService;
......@@ -57,6 +59,23 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
private final SysUserRoleMapper userRoleMapper;
private final SysUserPostMapper userPostMapper;
/**
* 根据租户ID查询大司空超管or租户管理员为其创建的企业管理员和管理员账号数量
*
* @param tenantId 租户ID
* @return 该企业下企业管理员和管理员账号数量
*/
@Override
public Long queryTenantAdminNumCreatedByDSK(Long tenantId) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserId)
.eq(SysUser::getStatus, UserConstants.NORMAL)
.eq(SysUser::getDelFlag, UserConstants.NORMAL)
.eq(SysUser::getTenantId, tenantId);
//.eq(SysUser::getCreateBy, "suadmin");
return baseMapper.selectCount(queryWrapper);
}
@Override
public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) {
Page<SysUser> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user));
......@@ -109,10 +128,15 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
QueryWrapper<SysUser> wrapper = Wrappers.query();
wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
.eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId())
.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
.like(StringUtils.isNotBlank(user.getUserName()), "u.nick_name", user.getUserName())
.eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
.like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
Page<SysUser> page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper);
List<SysUser> userList = page.getRecords();
for (SysUser sysUser : userList) {
sysUser.setDept(deptMapper.selectOne(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getDeptId, sysUser.getDeptId())));
}
return TableDataInfo.build(page);
}
......@@ -129,9 +153,14 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
.and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id"))
.notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds)
.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
.like(StringUtils.isNotBlank(user.getUserName()), "u.nick_name", user.getUserName())
.like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
Page<SysUser> page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper);
List<SysUser> userList = page.getRecords();
for (SysUser sysUser : userList) {
sysUser.setDept(deptMapper.selectOne(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getDeptId, sysUser.getDeptId())));
}
return TableDataInfo.build(page);
}
......@@ -225,6 +254,20 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
return !exist;
}
/**
* 校验企业普通管理员手机号码是否唯一
*
* @param tenantAdminBo 用户信息
* @return 结果
*/
@Override
public boolean checkTenantAdminPhoneUnique(SysTenantAdminBo tenantAdminBo) {
return baseMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getTenantId, tenantAdminBo.getTenantId())
.eq(SysUser::getPhonenumber, tenantAdminBo.getPhonenumber())
.eq(SysUser::getStatus, UserConstants.NORMAL));
}
/**
* 校验email是否唯一
*
......@@ -397,9 +440,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
@Transactional(rollbackFor = Exception.class)
public int updateUser(SysUser user) {
Long userId = user.getUserId();
if (LoginHelper.isTenantAdmin(LoginHelper.getLoginUser().getRolePermission())) {
//校验企业管理员角色下是否至少有一个账号
checkAdminHasUsers(user);
}
// 删除用户与角色关联
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
// 新增用户与角色管理
......@@ -422,8 +466,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
.select(SysRole::getRoleId)
.eq(SysRole::getStatus, UserConstants.USER_NORMAL)
.eq(SysRole::getDelFlag, UserConstants.USER_NORMAL)
.eq(SysRole::getRoleKey, "admin"));
.eq(SysRole::getRoleKey, TenantConstants.TENANT_SUPER_ADMIN_ROLE_KEY));
//如果目前企业管理员角色下仅有1个账号
List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(adminRole.getRoleId());
int enableAccount = 0;
......
......@@ -334,6 +334,12 @@
<version>${pinyin4j.version}</version>
</dependency>
<dependency>
<groupId>com.dsk</groupId>
<artifactId>dsk-biz-bi</artifactId>
<version>${dsk-operate-sys.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment