u
This commit is contained in:
1 parent
7cd7bbd166
commit
ff327ba2fd
47 files changed
+4362
-1230
No files matched your search
+1
-1
@@ -23,7 +23,7 @@ public class AuthRegisterDTO {
|
||||
@NotBlank(message = "所属行业不能为空")
|
||||
private String industry;
|
||||
@NotBlank(message = "公司地址不能为空")
|
||||
private String address;
|
||||
private String area;
|
||||
private String phone;
|
||||
private String email;
|
||||
private String profile;
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class AuthIdentityService {
|
||||
.setId(companyId)
|
||||
.setName(company.getName())
|
||||
.setIndustry(company.getIndustry())
|
||||
.setAddress(company.getAddress())
|
||||
.setArea(company.getArea())
|
||||
.setPhone(company.getPhone())
|
||||
.setEmail(company.getEmail())
|
||||
.setProfile(company.getProfile())
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package cn.link56.base.controller;
|
||||
|
||||
import cn.link56.base.model.dto.AddFileDTO;
|
||||
import cn.link56.base.model.vo.AliyunKeyVO;
|
||||
import cn.link56.base.service.FileService;
|
||||
import cn.link56.common.Result;
|
||||
import cn.link56.common.utils.HttpUtils;
|
||||
import cn.link56.common.utils.JsonUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/base/file")
|
||||
public class FileController {
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@PostMapping("/getAliyunKey")
|
||||
public Result<AliyunKeyVO> getAliyunKey() {
|
||||
String requestUrl = "http://g3oss.g3soft.cn:8082/upload?orgid=link56&bucket=g3hdzjsj";
|
||||
String s = HttpUtils.sendGet(requestUrl);
|
||||
AliyunKeyVO aliyunKeyVO = (AliyunKeyVO) JsonUtils.toBean(s, AliyunKeyVO.class);
|
||||
|
||||
assert aliyunKeyVO != null;
|
||||
|
||||
return Result.success(aliyunKeyVO);
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
public Result<Void> insertFile(@RequestBody @Validated AddFileDTO addFileDTO) {
|
||||
fileService.addFile(addFileDTO);
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.link56.base.mapper;
|
||||
|
||||
import cn.link56.base.model.po.FilePO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface FileMapper extends BaseMapper<FilePO> {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.link56.base.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AddFileDTO {
|
||||
@NotBlank(
|
||||
message = "文件名称不能为空"
|
||||
)
|
||||
private String fileName;
|
||||
|
||||
@NotBlank(
|
||||
message = "文件大小不能为空"
|
||||
)
|
||||
private String fileSize;
|
||||
|
||||
@NotBlank(
|
||||
message = "文件全路径oss不能为空"
|
||||
)
|
||||
private String fileMapName;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.link56.base.model.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName("b_file")
|
||||
@Accessors(chain = true)
|
||||
public class FilePO {
|
||||
@TableId(value = "b_id")
|
||||
private String id;
|
||||
|
||||
@TableField("mx_filename")
|
||||
private String name;
|
||||
|
||||
@TableField("mx_filesize")
|
||||
private String size;
|
||||
|
||||
@TableField("mx_fileext")
|
||||
private String ext;
|
||||
|
||||
@TableField("mx_mapfilename")
|
||||
private String mapName;
|
||||
|
||||
@TableField(
|
||||
value = "b_create_time",
|
||||
fill = FieldFill.INSERT
|
||||
)
|
||||
private String createTime;
|
||||
|
||||
@TableField(
|
||||
value = "b_create_by",
|
||||
fill = FieldFill.INSERT
|
||||
)
|
||||
private String createBy;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.link56.base.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AliyunKeyVO {
|
||||
private String accessid;
|
||||
private String policy;
|
||||
private String signature;
|
||||
private String dir;
|
||||
private String host;
|
||||
private String expire;
|
||||
private String callback;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.link56.base.service;
|
||||
|
||||
import cn.link56.base.mapper.FileMapper;
|
||||
import cn.link56.base.model.dto.AddFileDTO;
|
||||
import cn.link56.base.model.po.FilePO;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class FileService extends ServiceImpl<FileMapper, FilePO> {
|
||||
@Resource
|
||||
private FileMapper fileMapper;
|
||||
|
||||
@Transactional
|
||||
public void addFile(AddFileDTO addFileDTO){
|
||||
String fileName = addFileDTO.getFileName();
|
||||
String fileSize = addFileDTO.getFileSize();
|
||||
String fileMapName = addFileDTO.getFileMapName();
|
||||
|
||||
String suffix = "";
|
||||
if (StringUtils.isNotEmpty(fileName)) {
|
||||
int lastDotIndex = fileName.lastIndexOf(46);
|
||||
if (lastDotIndex != -1 && lastDotIndex < fileName.length() - 1) {
|
||||
suffix = fileName.substring(lastDotIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
FilePO filePO = new FilePO();
|
||||
filePO.setExt(suffix).setName(fileName).setMapName(fileMapName).setSize(fileSize);
|
||||
fileMapper.insert(filePO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.link56.common;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Accessors(chain = true)
|
||||
public class BasePageVO<T> {
|
||||
private long total;
|
||||
private List<T> records;
|
||||
}
|
||||
@@ -19,8 +19,8 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns(
|
||||
"/auth/**",
|
||||
"/company/getCompanyPage",
|
||||
"/company/getPublicDetail",
|
||||
"/company/query",
|
||||
"/company/detail/**",
|
||||
"/company/recommend",
|
||||
"/company/recommend/hot",
|
||||
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
package cn.link56.common.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
@Slf4j
|
||||
public class HttpUtils {
|
||||
|
||||
public static String sendGet(String url) {
|
||||
return sendGet(url, "");
|
||||
}
|
||||
|
||||
public static String sendGet(String url, String param) {
|
||||
return sendGet(url, param, "UTF-8");
|
||||
}
|
||||
|
||||
public static String sendGet(String url, String param, String contentType) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
BufferedReader in = null;
|
||||
|
||||
try {
|
||||
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
|
||||
URL realUrl = new URL(urlNameString);
|
||||
URLConnection connection = realUrl.openConnection();
|
||||
connection.setRequestProperty("accept", "*/*");
|
||||
connection.setRequestProperty("connection", "Keep-Alive");
|
||||
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
connection.connect();
|
||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
|
||||
|
||||
String line;
|
||||
while((line = in.readLine()) != null) {
|
||||
result.append(line);
|
||||
}
|
||||
} catch (ConnectException e) {
|
||||
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
|
||||
} catch (SocketTimeoutException e) {
|
||||
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||
} catch (IOException e) {
|
||||
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
|
||||
} catch (Exception e) {
|
||||
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String sendPost(String url, String param) {
|
||||
return sendPost(url, param, "application/x-www-form-urlencoded");
|
||||
}
|
||||
|
||||
public static String sendPost(String url, String param, String contentType) {
|
||||
PrintWriter out = null;
|
||||
BufferedReader in = null;
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
try {
|
||||
log.info("sendPost - {}", url);
|
||||
URL realUrl = new URL(url);
|
||||
URLConnection conn = realUrl.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("Content-Type", contentType);
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
out = new PrintWriter(conn.getOutputStream());
|
||||
out.print(param);
|
||||
out.flush();
|
||||
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||
|
||||
String line;
|
||||
while((line = in.readLine()) != null) {
|
||||
result.append(line);
|
||||
}
|
||||
|
||||
log.info("recv - {}", result);
|
||||
} catch (ConnectException e) {
|
||||
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
||||
} catch (SocketTimeoutException e) {
|
||||
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||
} catch (IOException e) {
|
||||
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
||||
} catch (Exception e) {
|
||||
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String sendSSLPost(String url, String param) {
|
||||
return sendSSLPost(url, param, "application/x-www-form-urlencoded");
|
||||
}
|
||||
|
||||
public static String sendSSLPost(String url, String param, String contentType) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
String urlNameString = url + "?" + param;
|
||||
|
||||
try {
|
||||
log.info("sendSSLPost - {}", urlNameString);
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init((KeyManager[])null, new TrustManager[]{new TrustAnyTrustManager()}, new SecureRandom());
|
||||
URL console = new URL(urlNameString);
|
||||
HttpsURLConnection conn = (HttpsURLConnection)console.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("Content-Type", contentType);
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
conn.setSSLSocketFactory(sc.getSocketFactory());
|
||||
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
|
||||
conn.connect();
|
||||
InputStream is = conn.getInputStream();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
String ret = "";
|
||||
|
||||
while((ret = br.readLine()) != null) {
|
||||
if (ret != null && !"".equals(ret.trim())) {
|
||||
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
log.info("recv - {}", result);
|
||||
conn.disconnect();
|
||||
br.close();
|
||||
} catch (ConnectException e) {
|
||||
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
|
||||
} catch (SocketTimeoutException e) {
|
||||
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||
} catch (IOException e) {
|
||||
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
|
||||
} catch (Exception e) {
|
||||
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static class TrustAnyTrustManager implements X509TrustManager {
|
||||
private TrustAnyTrustManager() {
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
}
|
||||
|
||||
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
|
||||
private TrustAnyHostnameVerifier() {
|
||||
}
|
||||
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
-3
@@ -1,12 +1,16 @@
|
||||
package cn.link56.company.controller;
|
||||
|
||||
import cn.link56.common.BasePageVO;
|
||||
import cn.link56.common.Result;
|
||||
import cn.link56.company.model.dto.PageCompanyDTO;
|
||||
import cn.link56.company.model.vo.CompanyDetailVO;
|
||||
import cn.link56.company.model.vo.PageCompanyVO;
|
||||
import cn.link56.company.model.vo.RecommendCompanyVO;
|
||||
import cn.link56.company.model.vo.RecommendHotCompanyVO;
|
||||
import cn.link56.company.service.CompanyService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
@@ -17,15 +21,32 @@ public class CompanyController {
|
||||
@Resource
|
||||
private CompanyService companyService;
|
||||
|
||||
// 公司分页
|
||||
@PostMapping("/query")
|
||||
public Result<BasePageVO<PageCompanyVO>> query(@RequestBody PageCompanyDTO pageCompanyDTO){
|
||||
BasePageVO<PageCompanyVO> data = companyService.queryCompany(pageCompanyDTO);
|
||||
return Result.success(data);
|
||||
}
|
||||
|
||||
// 企业名录
|
||||
@GetMapping("/recommend")
|
||||
public Result<List<RecommendCompanyVO>> listRecommend(){
|
||||
List<RecommendCompanyVO> list = companyService.listRecommend();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
// 热门推荐
|
||||
@GetMapping("/recommend/hot")
|
||||
public Result<List<RecommendHotCompanyVO>> listHot(){
|
||||
List<RecommendHotCompanyVO> list = companyService.listHot();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
// 公司详细
|
||||
@GetMapping("/detail/{id}")
|
||||
public Result<CompanyDetailVO> getCompanyDetail(@PathVariable Long id){
|
||||
CompanyDetailVO companyDetailVO = companyService.getCompanyDetail(id);
|
||||
return Result.success(companyDetailVO);
|
||||
}
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package cn.link56.company.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PageCompanyDTO {
|
||||
private Integer currentPage;
|
||||
private Integer pageSize;
|
||||
|
||||
private List<String> areas;
|
||||
private List<String> industries;
|
||||
private String name;
|
||||
}
|
||||
@@ -30,8 +30,8 @@ public class CompanyPO {
|
||||
@TableField("b_phone")
|
||||
private String phone;
|
||||
|
||||
@TableField("b_address")
|
||||
private String address;
|
||||
@TableField("b_area")
|
||||
private String area;
|
||||
|
||||
@TableField("b_industry")
|
||||
private String industry;
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package cn.link56.company.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CompanyDetailVO {
|
||||
private Long id;
|
||||
private String name;
|
||||
private List<String> areas;
|
||||
private List<String> industries;
|
||||
private String logo;
|
||||
private String profile;
|
||||
private String email;
|
||||
private String phone;
|
||||
private String description;
|
||||
private List<User> users;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class User{
|
||||
private Long id;
|
||||
private Long companyId;
|
||||
private String email;
|
||||
private String phone;
|
||||
private Integer role;
|
||||
private String position;
|
||||
private String name;
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package cn.link56.company.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class PageCompanyVO {
|
||||
private Long id;
|
||||
private String name;
|
||||
private List<String> areas;
|
||||
private List<String> industries;
|
||||
private String logo;
|
||||
private String profile;
|
||||
private String phone;
|
||||
private String email;
|
||||
}
|
||||
+93
@@ -1,15 +1,26 @@
|
||||
package cn.link56.company.service;
|
||||
|
||||
import cn.link56.common.BasePageVO;
|
||||
import cn.link56.company.mapper.CompanyMapper;
|
||||
import cn.link56.company.mapper.CompanyUserMapper;
|
||||
import cn.link56.company.model.dto.PageCompanyDTO;
|
||||
import cn.link56.company.model.middle.RecommendCompanyRow;
|
||||
import cn.link56.company.model.po.CompanyPO;
|
||||
import cn.link56.company.model.po.CompanyUserPO;
|
||||
import cn.link56.company.model.vo.CompanyDetailVO;
|
||||
import cn.link56.company.model.vo.PageCompanyVO;
|
||||
import cn.link56.company.model.vo.RecommendCompanyVO;
|
||||
import cn.link56.company.model.vo.RecommendHotCompanyVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -17,6 +28,8 @@ import java.util.stream.Collectors;
|
||||
public class CompanyService extends ServiceImpl<CompanyMapper,CompanyPO> {
|
||||
@Resource
|
||||
private CompanyMapper companyMapper;
|
||||
@Resource
|
||||
private CompanyUserService companyUserService;
|
||||
|
||||
public List<RecommendCompanyVO> listRecommend() {
|
||||
List<RecommendCompanyRow> rows = companyMapper.listRecommend();
|
||||
@@ -86,4 +99,84 @@ public class CompanyService extends ServiceImpl<CompanyMapper,CompanyPO> {
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
public BasePageVO<PageCompanyVO> queryCompany(PageCompanyDTO pageCompanyDTO) {
|
||||
Integer currentPage = pageCompanyDTO.getCurrentPage();
|
||||
Integer pageSize = pageCompanyDTO.getPageSize();
|
||||
|
||||
String name = pageCompanyDTO.getName();
|
||||
List<String> areas = pageCompanyDTO.getAreas();
|
||||
List<String> industries = pageCompanyDTO.getIndustries();
|
||||
|
||||
// 分页
|
||||
Page<CompanyPO> companyPage = new Page<>(currentPage,pageSize);
|
||||
LambdaQueryWrapper<CompanyPO> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 名称
|
||||
if (StringUtils.isNotBlank(name)){
|
||||
queryWrapper.like(CompanyPO::getName,name);
|
||||
}
|
||||
|
||||
// 地区
|
||||
if (areas != null && !areas.isEmpty()){
|
||||
queryWrapper.and(wrapper -> {
|
||||
for (String area : areas) {
|
||||
wrapper.or(w -> w.like(CompanyPO::getArea, area));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 行业
|
||||
if (industries != null && !industries.isEmpty()) {
|
||||
queryWrapper.and(wrapper -> {
|
||||
for (String industry : industries) {
|
||||
wrapper.or(w -> w.like(CompanyPO::getIndustry, industry));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
queryWrapper.eq(CompanyPO::getCanuse,"1");
|
||||
|
||||
List<PageCompanyVO> result = companyMapper.selectList(companyPage, queryWrapper).stream().map(item -> {
|
||||
PageCompanyVO pageCompanyVO = new PageCompanyVO();
|
||||
|
||||
pageCompanyVO.setId(item.getId());
|
||||
pageCompanyVO.setName(item.getName());
|
||||
pageCompanyVO.setProfile(item.getProfile());
|
||||
pageCompanyVO.setLogo(item.getLogo());
|
||||
pageCompanyVO.setAreas(Arrays.stream(item.getArea().split(","))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
pageCompanyVO.setIndustries(Arrays.stream(item.getIndustry().split(","))
|
||||
.collect(Collectors.toList()));
|
||||
return pageCompanyVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
return new BasePageVO<PageCompanyVO>()
|
||||
.setRecords(result)
|
||||
.setTotal(companyPage.getTotal());
|
||||
}
|
||||
|
||||
public CompanyDetailVO getCompanyDetail(Long companyId) {
|
||||
CompanyPO companyPO = companyMapper.selectById(companyId);
|
||||
List<CompanyUserPO> companyUserPOS = companyUserService.listByCompanyId(companyId);
|
||||
|
||||
CompanyDetailVO companyDetailVO = new CompanyDetailVO();
|
||||
|
||||
BeanUtils.copyProperties(companyPO,companyDetailVO);
|
||||
companyDetailVO.setAreas(Arrays.stream(companyPO.getArea().split(","))
|
||||
.collect(Collectors.toList()));
|
||||
companyDetailVO.setIndustries(Arrays.stream(companyPO.getIndustry().split(","))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
companyDetailVO.setUsers(companyUserPOS.stream()
|
||||
.map(item -> {
|
||||
CompanyDetailVO.User user = new CompanyDetailVO.User();
|
||||
BeanUtils.copyProperties(item, user); // 复制属性
|
||||
return user;
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
return companyDetailVO;
|
||||
}
|
||||
}
|
||||
+7
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CompanyUserService extends ServiceImpl<CompanyUserMapper, CompanyUserPO> {
|
||||
@@ -56,4 +57,10 @@ public class CompanyUserService extends ServiceImpl<CompanyUserMapper, CompanyUs
|
||||
return companyUserMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
public List<CompanyUserPO> listByCompanyId(Long companyId){
|
||||
LambdaQueryWrapper<CompanyUserPO> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(CompanyUserPO::getCompanyId,companyId);
|
||||
|
||||
return companyUserMapper.selectList(queryWrapper);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
LEFT JOIN b_company c
|
||||
ON c.b_canuse = '1'
|
||||
AND c.b_recommend = '1'
|
||||
AND c.b_address LIKE '%' + shi.b_name + '%'
|
||||
AND c.b_area LIKE '%' + shi.b_name + '%'
|
||||
|
||||
WHERE
|
||||
shi.b_canuse = '1'
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.13.2",
|
||||
"dayjs": "^1.11.19",
|
||||
"element-plus": "^2.12.0",
|
||||
|
||||
+488
@@ -11,6 +11,12 @@ importers:
|
||||
'@element-plus/icons-vue':
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2(vue@3.5.25(typescript@5.9.3))
|
||||
'@wangeditor/editor':
|
||||
specifier: ^5.1.23
|
||||
version: 5.1.23
|
||||
'@wangeditor/editor-for-vue':
|
||||
specifier: ^5.1.12
|
||||
version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.25(typescript@5.9.3))
|
||||
axios:
|
||||
specifier: ^1.13.2
|
||||
version: 1.13.2
|
||||
@@ -149,6 +155,10 @@ packages:
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@babel/runtime@7.28.4':
|
||||
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.28.5':
|
||||
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -686,12 +696,18 @@ packages:
|
||||
'@sxzz/popperjs-es@2.11.7':
|
||||
resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
|
||||
|
||||
'@transloadit/prettier-bytes@0.0.7':
|
||||
resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/event-emitter@0.3.5':
|
||||
resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==}
|
||||
|
||||
'@types/json-schema@7.0.15':
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
|
||||
@@ -775,6 +791,23 @@ packages:
|
||||
resolution: {integrity: sha512-LlKaciDe3GmZFphXIc79THF/YYBugZ7FS1pO581E/edlVVNbZKDy93evqmrfQ9/Y4uN0vVhX4iuchq26mK/iiA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@uppy/companion-client@2.2.2':
|
||||
resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==}
|
||||
|
||||
'@uppy/core@2.3.4':
|
||||
resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==}
|
||||
|
||||
'@uppy/store-default@2.1.1':
|
||||
resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==}
|
||||
|
||||
'@uppy/utils@4.1.3':
|
||||
resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==}
|
||||
|
||||
'@uppy/xhr-upload@2.1.3':
|
||||
resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.3.3
|
||||
|
||||
'@vitejs/plugin-vue@6.0.2':
|
||||
resolution: {integrity: sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -873,6 +906,93 @@ packages:
|
||||
'@vueuse/shared@9.13.0':
|
||||
resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
|
||||
|
||||
'@wangeditor/basic-modules@1.1.7':
|
||||
resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
lodash.throttle: ^4.1.1
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/code-highlight@1.0.3':
|
||||
resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/core@1.1.19':
|
||||
resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.1.1
|
||||
'@uppy/xhr-upload': ^2.0.3
|
||||
dom7: ^3.0.0
|
||||
is-hotkey: ^0.2.0
|
||||
lodash.camelcase: ^4.3.0
|
||||
lodash.clonedeep: ^4.5.0
|
||||
lodash.debounce: ^4.0.8
|
||||
lodash.foreach: ^4.5.0
|
||||
lodash.isequal: ^4.5.0
|
||||
lodash.throttle: ^4.1.1
|
||||
lodash.toarray: ^4.4.0
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/editor-for-vue@5.1.12':
|
||||
resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==}
|
||||
peerDependencies:
|
||||
'@wangeditor/editor': '>=5.1.0'
|
||||
vue: ^3.0.5
|
||||
|
||||
'@wangeditor/editor@5.1.23':
|
||||
resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==}
|
||||
|
||||
'@wangeditor/list-module@1.0.5':
|
||||
resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/table-module@1.1.4':
|
||||
resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
lodash.isequal: ^4.5.0
|
||||
lodash.throttle: ^4.1.1
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/upload-image-module@1.0.2':
|
||||
resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.0.3
|
||||
'@uppy/xhr-upload': ^2.0.3
|
||||
'@wangeditor/basic-modules': 1.x
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
lodash.foreach: ^4.5.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/video-module@1.1.4':
|
||||
resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.1.4
|
||||
'@uppy/xhr-upload': ^2.0.7
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
@@ -1000,6 +1120,9 @@ packages:
|
||||
resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
compute-scroll-into-view@1.0.20:
|
||||
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
|
||||
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
@@ -1028,6 +1151,10 @@ packages:
|
||||
csstype@3.2.3:
|
||||
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||
|
||||
d@1.0.2:
|
||||
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
dayjs@1.11.19:
|
||||
resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==}
|
||||
|
||||
@@ -1069,6 +1196,9 @@ packages:
|
||||
resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==}
|
||||
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
|
||||
|
||||
dom7@3.0.0:
|
||||
resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1109,6 +1239,17 @@ packages:
|
||||
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
esbuild@0.25.12:
|
||||
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1313,6 +1454,10 @@ packages:
|
||||
jiti:
|
||||
optional: true
|
||||
|
||||
esniff@2.0.1:
|
||||
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
espree@10.4.0:
|
||||
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@@ -1340,9 +1485,15 @@ packages:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
|
||||
|
||||
exsolve@1.0.8:
|
||||
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
|
||||
|
||||
ext@1.7.0:
|
||||
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
|
||||
|
||||
fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
|
||||
@@ -1480,6 +1631,12 @@ packages:
|
||||
html-entities@2.6.0:
|
||||
resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==}
|
||||
|
||||
html-void-elements@2.0.1:
|
||||
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
|
||||
|
||||
i18next@20.6.1:
|
||||
resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==}
|
||||
|
||||
ignore@5.3.2:
|
||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
engines: {node: '>= 4'}
|
||||
@@ -1488,6 +1645,9 @@ packages:
|
||||
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
immer@9.0.21:
|
||||
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
|
||||
|
||||
immutable@5.1.4:
|
||||
resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==}
|
||||
|
||||
@@ -1515,10 +1675,20 @@ packages:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-hotkey@0.2.0:
|
||||
resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==}
|
||||
|
||||
is-number@7.0.0:
|
||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
|
||||
is-plain-object@5.0.0:
|
||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-url@1.2.4:
|
||||
resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==}
|
||||
|
||||
is-what@5.5.0:
|
||||
resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1585,9 +1755,31 @@ packages:
|
||||
lodash: '*'
|
||||
lodash-es: '*'
|
||||
|
||||
lodash.camelcase@4.3.0:
|
||||
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
||||
|
||||
lodash.clonedeep@4.5.0:
|
||||
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
|
||||
|
||||
lodash.debounce@4.0.8:
|
||||
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
|
||||
|
||||
lodash.foreach@4.5.0:
|
||||
resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==}
|
||||
|
||||
lodash.isequal@4.5.0:
|
||||
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
|
||||
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
|
||||
|
||||
lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
|
||||
lodash.throttle@4.1.1:
|
||||
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
|
||||
|
||||
lodash.toarray@4.4.0:
|
||||
resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==}
|
||||
|
||||
lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
|
||||
@@ -1738,6 +1930,9 @@ packages:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-match@1.0.2:
|
||||
resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==}
|
||||
|
||||
mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@@ -1761,6 +1956,9 @@ packages:
|
||||
muggle-string@0.4.1:
|
||||
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
|
||||
|
||||
namespace-emitter@2.0.1:
|
||||
resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==}
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
@@ -1773,6 +1971,9 @@ packages:
|
||||
resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
next-tick@1.1.0:
|
||||
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
@@ -1889,6 +2090,9 @@ packages:
|
||||
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
preact@10.28.0:
|
||||
resolution: {integrity: sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==}
|
||||
|
||||
prelude-ls@1.2.1:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -1902,6 +2106,10 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
prismjs@1.30.0:
|
||||
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
|
||||
@@ -1956,6 +2164,9 @@ packages:
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
||||
scroll-into-view-if-needed@2.2.31:
|
||||
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
|
||||
|
||||
scslre@0.3.0:
|
||||
resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==}
|
||||
engines: {node: ^14.0.0 || >=16.0.0}
|
||||
@@ -1976,6 +2187,18 @@ packages:
|
||||
sisteransi@1.0.5:
|
||||
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
||||
|
||||
slate-history@0.66.0:
|
||||
resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==}
|
||||
peerDependencies:
|
||||
slate: '>=0.65.3'
|
||||
|
||||
slate@0.72.8:
|
||||
resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==}
|
||||
|
||||
snabbdom@3.6.3:
|
||||
resolution: {integrity: sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg==}
|
||||
engines: {node: '>=12.17.0'}
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1993,6 +2216,9 @@ packages:
|
||||
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
ssr-window@3.0.0:
|
||||
resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==}
|
||||
|
||||
strip-indent@4.1.1:
|
||||
resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2017,6 +2243,9 @@ packages:
|
||||
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
tiny-warning@1.0.3:
|
||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||
|
||||
tinyexec@1.0.2:
|
||||
resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2052,6 +2281,9 @@ packages:
|
||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
type@2.7.3:
|
||||
resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
|
||||
|
||||
typescript@5.9.3:
|
||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||
engines: {node: '>=14.17'}
|
||||
@@ -2218,6 +2450,9 @@ packages:
|
||||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
wildcard@1.1.2:
|
||||
resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==}
|
||||
|
||||
word-wrap@1.2.5:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -2305,6 +2540,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/types': 7.28.5
|
||||
|
||||
'@babel/runtime@7.28.4': {}
|
||||
|
||||
'@babel/types@7.28.5':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
@@ -2705,12 +2942,16 @@ snapshots:
|
||||
|
||||
'@sxzz/popperjs-es@2.11.7': {}
|
||||
|
||||
'@transloadit/prettier-bytes@0.0.7': {}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/event-emitter@0.3.5': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/lodash-es@4.17.12':
|
||||
@@ -2824,6 +3065,35 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.49.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
'@uppy/companion-client@2.2.2':
|
||||
dependencies:
|
||||
'@uppy/utils': 4.1.3
|
||||
namespace-emitter: 2.0.1
|
||||
|
||||
'@uppy/core@2.3.4':
|
||||
dependencies:
|
||||
'@transloadit/prettier-bytes': 0.0.7
|
||||
'@uppy/store-default': 2.1.1
|
||||
'@uppy/utils': 4.1.3
|
||||
lodash.throttle: 4.1.1
|
||||
mime-match: 1.0.2
|
||||
namespace-emitter: 2.0.1
|
||||
nanoid: 3.3.11
|
||||
preact: 10.28.0
|
||||
|
||||
'@uppy/store-default@2.1.1': {}
|
||||
|
||||
'@uppy/utils@4.1.3':
|
||||
dependencies:
|
||||
lodash.throttle: 4.1.1
|
||||
|
||||
'@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4)':
|
||||
dependencies:
|
||||
'@uppy/companion-client': 2.2.2
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/utils': 4.1.3
|
||||
nanoid: 3.3.11
|
||||
|
||||
'@vitejs/plugin-vue@6.0.2(vite@7.2.7(@types/node@24.10.3)(sass@1.96.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-beta.50
|
||||
@@ -2962,6 +3232,114 @@ snapshots:
|
||||
- '@vue/composition-api'
|
||||
- vue
|
||||
|
||||
'@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
is-url: 1.2.4
|
||||
lodash.throttle: 4.1.1
|
||||
nanoid: 3.3.11
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
prismjs: 1.30.0
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@types/event-emitter': 0.3.5
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
dom7: 3.0.0
|
||||
event-emitter: 0.3.5
|
||||
html-void-elements: 2.0.1
|
||||
i18next: 20.6.1
|
||||
is-hotkey: 0.2.0
|
||||
lodash.camelcase: 4.3.0
|
||||
lodash.clonedeep: 4.5.0
|
||||
lodash.debounce: 4.0.8
|
||||
lodash.foreach: 4.5.0
|
||||
lodash.isequal: 4.5.0
|
||||
lodash.throttle: 4.1.1
|
||||
lodash.toarray: 4.4.0
|
||||
nanoid: 3.3.11
|
||||
scroll-into-view-if-needed: 2.2.31
|
||||
slate: 0.72.8
|
||||
slate-history: 0.66.0(slate@0.72.8)
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.25(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@wangeditor/editor': 5.1.23
|
||||
vue: 3.5.25(typescript@5.9.3)
|
||||
|
||||
'@wangeditor/editor@5.1.23':
|
||||
dependencies:
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
is-hotkey: 0.2.0
|
||||
lodash.camelcase: 4.3.0
|
||||
lodash.clonedeep: 4.5.0
|
||||
lodash.debounce: 4.0.8
|
||||
lodash.foreach: 4.5.0
|
||||
lodash.isequal: 4.5.0
|
||||
lodash.throttle: 4.1.1
|
||||
lodash.toarray: 4.4.0
|
||||
nanoid: 3.3.11
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
lodash.isequal: 4.5.0
|
||||
lodash.throttle: 4.1.1
|
||||
nanoid: 3.3.11
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
lodash.foreach: 4.5.0
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
nanoid: 3.3.11
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
@@ -3075,6 +3453,8 @@ snapshots:
|
||||
|
||||
comment-parser@1.4.1: {}
|
||||
|
||||
compute-scroll-into-view@1.0.20: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
confbox@0.1.8: {}
|
||||
@@ -3099,6 +3479,11 @@ snapshots:
|
||||
|
||||
csstype@3.2.3: {}
|
||||
|
||||
d@1.0.2:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
type: 2.7.3
|
||||
|
||||
dayjs@1.11.19: {}
|
||||
|
||||
debug@4.4.3:
|
||||
@@ -3126,6 +3511,10 @@ snapshots:
|
||||
|
||||
diff-sequences@27.5.1: {}
|
||||
|
||||
dom7@3.0.0:
|
||||
dependencies:
|
||||
ssr-window: 3.0.0
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -3178,6 +3567,24 @@ snapshots:
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
es5-ext@0.10.64:
|
||||
dependencies:
|
||||
es6-iterator: 2.0.3
|
||||
es6-symbol: 3.1.4
|
||||
esniff: 2.0.1
|
||||
next-tick: 1.1.0
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-symbol: 3.1.4
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
ext: 1.7.0
|
||||
|
||||
esbuild@0.25.12:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.12
|
||||
@@ -3487,6 +3894,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
esniff@2.0.1:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
event-emitter: 0.3.5
|
||||
type: 2.7.3
|
||||
|
||||
espree@10.4.0:
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
@@ -3513,8 +3927,17 @@ snapshots:
|
||||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
|
||||
exsolve@1.0.8: {}
|
||||
|
||||
ext@1.7.0:
|
||||
dependencies:
|
||||
type: 2.7.3
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
fast-diff@1.3.0: {}
|
||||
@@ -3629,10 +4052,18 @@ snapshots:
|
||||
|
||||
html-entities@2.6.0: {}
|
||||
|
||||
html-void-elements@2.0.1: {}
|
||||
|
||||
i18next@20.6.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
ignore@7.0.5: {}
|
||||
|
||||
immer@9.0.21: {}
|
||||
|
||||
immutable@5.1.4: {}
|
||||
|
||||
import-fresh@3.3.1:
|
||||
@@ -3654,9 +4085,15 @@ snapshots:
|
||||
dependencies:
|
||||
is-extglob: 2.1.1
|
||||
|
||||
is-hotkey@0.2.0: {}
|
||||
|
||||
is-number@7.0.0:
|
||||
optional: true
|
||||
|
||||
is-plain-object@5.0.0: {}
|
||||
|
||||
is-url@1.2.4: {}
|
||||
|
||||
is-what@5.5.0: {}
|
||||
|
||||
isexe@2.0.0: {}
|
||||
@@ -3713,8 +4150,22 @@ snapshots:
|
||||
lodash: 4.17.21
|
||||
lodash-es: 4.17.21
|
||||
|
||||
lodash.camelcase@4.3.0: {}
|
||||
|
||||
lodash.clonedeep@4.5.0: {}
|
||||
|
||||
lodash.debounce@4.0.8: {}
|
||||
|
||||
lodash.foreach@4.5.0: {}
|
||||
|
||||
lodash.isequal@4.5.0: {}
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
|
||||
lodash.throttle@4.1.1: {}
|
||||
|
||||
lodash.toarray@4.4.0: {}
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
||||
longest-streak@3.1.0: {}
|
||||
@@ -4048,6 +4499,10 @@ snapshots:
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-match@1.0.2:
|
||||
dependencies:
|
||||
wildcard: 1.1.2
|
||||
|
||||
mime-types@2.1.35:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
@@ -4073,12 +4528,16 @@ snapshots:
|
||||
|
||||
muggle-string@0.4.1: {}
|
||||
|
||||
namespace-emitter@2.0.1: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
natural-orderby@5.0.0: {}
|
||||
|
||||
next-tick@1.1.0: {}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
optional: true
|
||||
|
||||
@@ -4182,6 +4641,8 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
preact@10.28.0: {}
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
prettier-linter-helpers@1.0.0:
|
||||
@@ -4190,6 +4651,8 @@ snapshots:
|
||||
|
||||
prettier@3.7.4: {}
|
||||
|
||||
prismjs@1.30.0: {}
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
||||
punycode@2.3.1: {}
|
||||
@@ -4257,6 +4720,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@parcel/watcher': 2.5.1
|
||||
|
||||
scroll-into-view-if-needed@2.2.31:
|
||||
dependencies:
|
||||
compute-scroll-into-view: 1.0.20
|
||||
|
||||
scslre@0.3.0:
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
@@ -4273,6 +4740,19 @@ snapshots:
|
||||
|
||||
sisteransi@1.0.5: {}
|
||||
|
||||
slate-history@0.66.0(slate@0.72.8):
|
||||
dependencies:
|
||||
is-plain-object: 5.0.0
|
||||
slate: 0.72.8
|
||||
|
||||
slate@0.72.8:
|
||||
dependencies:
|
||||
immer: 9.0.21
|
||||
is-plain-object: 5.0.0
|
||||
tiny-warning: 1.0.3
|
||||
|
||||
snabbdom@3.6.3: {}
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
spdx-exceptions@2.5.0: {}
|
||||
@@ -4286,6 +4766,8 @@ snapshots:
|
||||
|
||||
speakingurl@14.0.1: {}
|
||||
|
||||
ssr-window@3.0.0: {}
|
||||
|
||||
strip-indent@4.1.1: {}
|
||||
|
||||
strip-json-comments@3.1.1: {}
|
||||
@@ -4304,6 +4786,8 @@ snapshots:
|
||||
|
||||
tapable@2.3.0: {}
|
||||
|
||||
tiny-warning@1.0.3: {}
|
||||
|
||||
tinyexec@1.0.2: {}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
@@ -4338,6 +4822,8 @@ snapshots:
|
||||
dependencies:
|
||||
prelude-ls: 1.2.1
|
||||
|
||||
type@2.7.3: {}
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
ufo@1.6.1: {}
|
||||
@@ -4474,6 +4960,8 @@ snapshots:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
wildcard@1.1.2: {}
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
xml-name-validator@4.0.0: {}
|
||||
|
||||
@@ -3,7 +3,15 @@ import { useCommonStore } from '@/store/common'
|
||||
import AreaSelect from './AreaSelect.vue'
|
||||
import IndustrySelect from './IndustrySelect.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void
|
||||
}>()
|
||||
|
||||
const commonStore = useCommonStore()
|
||||
|
||||
function onSearch() {
|
||||
emit('search')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -28,7 +36,7 @@ const commonStore = useCommonStore()
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="search">
|
||||
<div class="search" @click="onSearch">
|
||||
<i-tdesign:search />
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +52,7 @@ const commonStore = useCommonStore()
|
||||
border: 0;
|
||||
color: #000;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
|
||||
background-color: #f4f4f4;
|
||||
.query-item {
|
||||
flex: 1;
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { createApp } from 'vue'
|
||||
import UploadProgress from './index.vue'
|
||||
|
||||
let app: ReturnType<typeof createApp> | null = null
|
||||
let instance: any = null
|
||||
|
||||
export function showUploadProgress(status: ProgressStatus = 'uploading') {
|
||||
if (!app) {
|
||||
const container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
|
||||
app = createApp(UploadProgress)
|
||||
instance = app.mount(container)
|
||||
}
|
||||
instance.open()
|
||||
instance.setStatus(status) // 外部传入状态
|
||||
}
|
||||
|
||||
export function updateUploadProgress(percent: number, status: ProgressStatus = 'uploading') {
|
||||
if (instance) {
|
||||
instance.setPercent(percent)
|
||||
instance.setStatus(status) // 外部传入状态
|
||||
|
||||
if (percent >= 100) {
|
||||
setTimeout(() => {
|
||||
closeUploadProgress()
|
||||
}, 800) // 100%后等一下再关闭,显得自然
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function closeUploadProgress() {
|
||||
if (instance) {
|
||||
instance.close()
|
||||
}
|
||||
}
|
||||
|
||||
export type ProgressStatus = 'uploading' | 'completed' | 'failed'
|
||||
@@ -0,0 +1,128 @@
|
||||
<script setup lang="ts">
|
||||
import type { ProgressStatus } from '.'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
|
||||
// 状态变量
|
||||
const visible = ref(false)
|
||||
const percent = ref(0)
|
||||
const statusText = ref('正在上传,请稍候')
|
||||
const status = ref<ProgressStatus>('uploading')
|
||||
|
||||
// 监听 percent 变化,更新状态文本
|
||||
watch(percent, (newPercent) => {
|
||||
const clampedPercent = Math.min(newPercent, 1)
|
||||
percent.value = clampedPercent
|
||||
|
||||
if (clampedPercent === 1) {
|
||||
status.value = 'completed'
|
||||
}
|
||||
else if (clampedPercent < 1 && status.value !== 'failed') {
|
||||
status.value = 'uploading'
|
||||
}
|
||||
})
|
||||
|
||||
// 监听上传状态变化,更新状态文本
|
||||
watch(status, (newStatus) => {
|
||||
if (newStatus === 'completed') {
|
||||
statusText.value = '上传完毕'
|
||||
}
|
||||
else if (newStatus === 'uploading') {
|
||||
statusText.value = '正在上传,请稍候 . . .'
|
||||
}
|
||||
else if (newStatus === 'failed') {
|
||||
statusText.value = '上传失败,请稍后再试 . . .'
|
||||
}
|
||||
})
|
||||
|
||||
// 获取进度条状态,上传失败时显示为 "exception"
|
||||
const getProgressStatus = computed(() => {
|
||||
if (status.value === 'failed') {
|
||||
return 'exception'
|
||||
}
|
||||
return percent.value < 1 ? '' : 'success'
|
||||
})
|
||||
|
||||
// 控制上传进度的函数
|
||||
function open() {
|
||||
percent.value = 0
|
||||
visible.value = true
|
||||
status.value = 'uploading' // 开始上传时重置状态
|
||||
statusText.value = '正在上传,请稍候 . . .'
|
||||
}
|
||||
|
||||
function close() {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
function setPercent(p: number) {
|
||||
percent.value = Number.parseFloat((p / 100).toFixed(2)) // 保留两位小数
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
setPercent,
|
||||
setStatus: (newStatus: ProgressStatus) => {
|
||||
status.value = newStatus // 使用 ProgressStatus 类型
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<transition name="fade">
|
||||
<div v-if="visible" class="upload-progress-mask">
|
||||
<div class="upload-progress-card">
|
||||
<div class="upload-progress-title" :class="[status === 'failed' ? 'error' : '']">
|
||||
{{ statusText }}
|
||||
</div>
|
||||
<el-progress :percentage="percent" :stroke-width="10" :status="getProgressStatus" />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.upload-progress-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 3000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.upload-progress-card {
|
||||
background: #ffffff;
|
||||
padding: 40px 50px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
|
||||
text-align: center;
|
||||
min-width: 320px;
|
||||
}
|
||||
|
||||
.upload-progress-title {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 30px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.upload-progress-title.error {
|
||||
color: red; /* 上传失败时,字体颜色变为红色 */
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { IButtonMenu, IDomEditor } from '@wangeditor/editor'
|
||||
import { Boot } from '@wangeditor/editor'
|
||||
|
||||
// 当前的点击处理器,始终指向最新传入的函数
|
||||
let currentClickHandler: (() => void) | null = null
|
||||
|
||||
// 是否已经注册过菜单
|
||||
let hasRegistered = false
|
||||
|
||||
class PreviewButtonMenu implements IButtonMenu {
|
||||
title = '预览'
|
||||
iconSvg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M12 4.57a.5.5 0 0 0-.024-.235l-.013-.063a1.5 1.5 0 0 0-.18-.434c-.092-.15-.222-.28-.482-.54L8.711.707c-.259-.26-.389-.39-.54-.483a1.5 1.5 0 0 0-.496-.193a.5.5 0 0 0-.235-.024C7.329.004 7.194.004 7.015.004h-2.21c-1.68 0-2.52 0-3.16.327a3.02 3.02 0 0 0-1.31 1.31C.008 2.283.008 3.12.008 4.8v6.4c0 1.68 0 2.52.327 3.16a3.02 3.02 0 0 0 1.31 1.31c.642.327 1.48.327 3.16.327h2.423c.401 0 .602-.523.347-.832a.45.45 0 0 0-.345-.168H4.8c-.857 0-1.44-.001-1.89-.038c-.438-.036-.663-.1-.819-.18a2 2 0 0 1-.874-.874c-.08-.156-.145-.38-.18-.819c-.036-.45-.037-1.03-.037-1.89v-6.4c0-.857 0-1.44.037-1.89c.036-.438.101-.663.18-.819c.192-.376.498-.682.874-.874c.156-.08.381-.145.82-.18C3.36.997 3.94.997 4.8.997H7v3.5a.5.5 0 0 0 .5.5H11v.547c0 .25.207.45.456.473c.285.025.543-.188.543-.474V4.99c0-.178 0-.313-.005-.425zM8 1.41L10.59 4H8z" clip-rule="evenodd"/>
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M11 15c.834 0 1.61-.255 2.25-.691l1.47 1.47a.749.749 0 1 0 1.06-1.06l-1.47-1.47c.436-.641.691-1.41.691-2.25c0-2.21-1.79-4-4-4s-4 1.79-4 4s1.79 4 4 4zm0-1c1.66 0 3-1.34 3-3s-1.34-3-3-3s-3 1.34-3 3s1.34 3 3 3" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
`
|
||||
tag = 'button'
|
||||
|
||||
getValue(): string | boolean {
|
||||
return ''
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
isDisabled(): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
exec(editor: IDomEditor): void {
|
||||
if (this.isDisabled())
|
||||
return
|
||||
currentClickHandler?.() // 始终执行最新的回调
|
||||
}
|
||||
}
|
||||
|
||||
// 提供注册函数,允许多次调用,但只注册一次菜单
|
||||
export function registerPreviewMenu(handleClick: () => void) {
|
||||
currentClickHandler = handleClick
|
||||
|
||||
if (hasRegistered)
|
||||
return
|
||||
|
||||
try {
|
||||
Boot.registerMenu({
|
||||
key: 'preview',
|
||||
factory: () => new PreviewButtonMenu(),
|
||||
})
|
||||
hasRegistered = true
|
||||
}
|
||||
catch (e) {
|
||||
if (!/duplicate/i.test(String(e))) {
|
||||
console.warn('注册预览菜单失败:', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单插入配置
|
||||
export const toolbarConfig = {
|
||||
excludeKeys: ['codeBlock', 'fullScreen', 'code'],
|
||||
insertKeys: {
|
||||
index: 32,
|
||||
keys: ['preview'],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'
|
||||
import { uploadImage, uploadToAliyun, uploadVideo } from '@/utils/file'
|
||||
import { registerPreviewMenu, toolbarConfig } from './config'
|
||||
import Directory from './modules/directory.vue'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
type: String as PropType<'edit' | 'view'>,
|
||||
default: 'edit',
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
showDirecotry: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
// 内容 HTML
|
||||
const valueHtml = ref('')
|
||||
|
||||
// 只读副本
|
||||
const previewHtml = ref('')
|
||||
|
||||
const showPreview = ref(false)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
valueHtml.value = newVal ?? ''
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
registerPreviewMenu(() => {
|
||||
previewHtml.value = valueHtml.value
|
||||
showPreview.value = true
|
||||
})
|
||||
})
|
||||
|
||||
const toolbarClass = computed(() => {
|
||||
return props.mode === 'view' ? 'toolbar-view' : 'toolbar-edit'
|
||||
})
|
||||
|
||||
const editorClass = computed(() => {
|
||||
return props.mode === 'view' ? 'editor-view' : 'editor-edit'
|
||||
})
|
||||
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef()
|
||||
defineExpose({
|
||||
getText: () => {
|
||||
if (editorRef.value) {
|
||||
return editorRef.value.getText()
|
||||
}
|
||||
else {
|
||||
console.error('Editor not initialized')
|
||||
return ''
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
function handleChange() {
|
||||
emit('update:modelValue', valueHtml.value)
|
||||
}
|
||||
|
||||
const editorConfig: any = {
|
||||
placeholder: props.mode === 'edit' ? '请输入内容...' : '',
|
||||
readOnly: props.mode === 'view',
|
||||
MENU_CONF: {}, // ✅ 这一步不能漏!
|
||||
}
|
||||
|
||||
editorConfig.MENU_CONF.uploadImage = {
|
||||
// 自定义选择图片
|
||||
customBrowseAndUpload(insertFn: any) {
|
||||
uploadImage().then((data) => {
|
||||
if (data) {
|
||||
uploadToAliyun(data.blob, data.name, data.size).then((res) => {
|
||||
insertFn(res.url, res.fileName, '')
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
editorConfig.MENU_CONF.uploadVideo = {
|
||||
customBrowseAndUpload(insertFn: any) {
|
||||
uploadVideo().then((data) => {
|
||||
if (data) {
|
||||
uploadToAliyun(data.blob, data.name, data.size).then((res) => {
|
||||
insertFn(res.url, res.fileName, '')
|
||||
})
|
||||
}
|
||||
else {
|
||||
ElMessage.error('上传失败,请稍后再试!')
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
// 组件销毁时,也及时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value
|
||||
if (editor == null)
|
||||
return
|
||||
editor.destroy()
|
||||
})
|
||||
|
||||
function handleCreated(editor: any) {
|
||||
editorRef.value = editor
|
||||
|
||||
nextTick(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="editor-container">
|
||||
<div class="main">
|
||||
<Toolbar v-if="props.mode === 'edit'" :class="toolbarClass" class="toolbar" :editor="editorRef" :default-config="toolbarConfig" />
|
||||
<Editor key="main" v-model="valueHtml" :class="editorClass" class="editor" :default-config="editorConfig" @on-change="handleChange" @on-created="handleCreated" />
|
||||
</div>
|
||||
<Directory v-if="showDirecotry" v-model:content="valueHtml" class="directory" />
|
||||
</div>
|
||||
<!-- <Preview v-model:visible="showPreview" :content="previewHtml" /> -->
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.toolbar {
|
||||
}
|
||||
.toolbar-view {
|
||||
}
|
||||
.toolbar-edit {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.editor {
|
||||
overflow-y: hidden;
|
||||
:deep(.w-e-text-container video) {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
.editor-view {
|
||||
height: auto;
|
||||
:deep(.w-e-text-container) {
|
||||
background-color: transparent;
|
||||
}
|
||||
:deep(.w-e-text-container .w-e-scroll [data-slate-editor]) {
|
||||
overflow-y: auto;
|
||||
padding: 0 0px !important;
|
||||
}
|
||||
}
|
||||
.editor-edit {
|
||||
height: 500px !important;
|
||||
border: 1px solid #ccc;
|
||||
border-top: transparent;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.directory {
|
||||
width: 200px;
|
||||
height: 450px;
|
||||
}
|
||||
.main {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,176 @@
|
||||
<script setup lang="ts">
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'WangEditorDirecotry',
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
},
|
||||
top: {
|
||||
type: Number,
|
||||
},
|
||||
})
|
||||
|
||||
const directory = ref<any[]>([])
|
||||
const collapsed = ref(false)
|
||||
|
||||
function toggleCollapse() {
|
||||
collapsed.value = !collapsed.value
|
||||
}
|
||||
|
||||
function scrollTo(id: any) {
|
||||
const el = document.getElementById(id)
|
||||
if (el) {
|
||||
if (props.top) {
|
||||
const rect = el.getBoundingClientRect()
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
|
||||
const top = rect.top + scrollTop - props.top
|
||||
|
||||
window.scrollTo({
|
||||
top,
|
||||
behavior: 'smooth',
|
||||
})
|
||||
}
|
||||
else {
|
||||
el.scrollIntoView({
|
||||
behavior: 'smooth', // 平滑滚动
|
||||
block: 'start', // 元素滚动到视口顶部
|
||||
inline: 'nearest', // 元素在水平方向上的滚动对齐方式
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function throttle(fn: any) {
|
||||
let isRunning = false
|
||||
return function (...args: any) {
|
||||
if (!isRunning) {
|
||||
isRunning = true
|
||||
requestAnimationFrame(() => {
|
||||
fn(...args)
|
||||
isRunning = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
function doGenerateDirectory() {
|
||||
const root = document.querySelector('.editor')
|
||||
|
||||
if (!root)
|
||||
return
|
||||
const headings = Array.from(root.querySelectorAll('h1, h2, h3'))
|
||||
const toc = headings.map((heading, idx) => {
|
||||
if (!heading.id)
|
||||
heading.id = `section-${idx + 1}`
|
||||
return {
|
||||
id: heading.id,
|
||||
text: heading.textContent || '',
|
||||
level: +heading.tagName[1], // 1 => h1, 2 => h2, 3 => h3
|
||||
index: idx,
|
||||
}
|
||||
})
|
||||
|
||||
directory.value = toc
|
||||
}
|
||||
|
||||
const updateDirectory = throttle(doGenerateDirectory)
|
||||
|
||||
watch(
|
||||
() => props.content,
|
||||
(newContent) => {
|
||||
if (newContent) {
|
||||
nextTick(() => {
|
||||
updateDirectory()
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="directory-card" :class="{ collapsed }">
|
||||
<div class="directory-header" @click="toggleCollapse">
|
||||
<div class="directory-header-left">
|
||||
<i-material-symbols:folder-copy-outline />
|
||||
<span>目录</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="!collapsed" class="directory-content">
|
||||
<div v-for="item in directory" :key="item.id" class="directory-item" :class="`level-${item.level}`" @click="scrollTo(item.id)">
|
||||
{{ item.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.directory-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
|
||||
&.collapsed {
|
||||
height: 44px !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.directory-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 1rem;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
.directory-header-left {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.directory-content {
|
||||
flex: 1;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
word-break: break-all;
|
||||
.directory-item {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
&.level-1 {
|
||||
font-weight: 600;
|
||||
padding-left: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.level-2 {
|
||||
padding-left: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&.level-3 {
|
||||
padding-left: 40px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #007aff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
<script setup lang="ts">
|
||||
import { Editor } from '@wangeditor/editor-for-vue'
|
||||
import { ref, shallowRef, watch } from 'vue'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
|
||||
// Props 定义
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
content?: string
|
||||
visible?: boolean
|
||||
}>(),
|
||||
{
|
||||
content: '',
|
||||
visible: false,
|
||||
},
|
||||
)
|
||||
|
||||
const emit = defineEmits(['update:visible'])
|
||||
|
||||
// 编辑器配置
|
||||
const editorConfig = {
|
||||
placeholder: '暂无内容',
|
||||
readOnly: true,
|
||||
MENU_CONF: {},
|
||||
}
|
||||
|
||||
const fullscreen = ref(false)
|
||||
const localVisible = ref(props.visible)
|
||||
const editorRef = shallowRef()
|
||||
|
||||
// 同步 props.visible 到 localVisible
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
localVisible.value = val
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
watch(
|
||||
() => props.content,
|
||||
(val) => {
|
||||
if (editorRef.value) {
|
||||
editorRef.value.setHtml(val)
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// 编辑器创建回调
|
||||
function handleCreated(editor: any) {
|
||||
editorRef.value = editor
|
||||
}
|
||||
|
||||
// 更新 visible 的统一方法
|
||||
function handleVisibleChange(val: boolean) {
|
||||
localVisible.value = val
|
||||
emit('update:visible', val)
|
||||
}
|
||||
|
||||
// 关闭操作
|
||||
function closeModal() {
|
||||
fullscreen.value = false
|
||||
emit('update:visible', false)
|
||||
handleVisibleChange(false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal v-bind="$attrs" :visible="localVisible" :footer="false" :closable="false" :fullscreen="fullscreen" :width="1100" modal-class="custom-modal" @update:visible="handleVisibleChange">
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<div />
|
||||
<div class="title">
|
||||
预览
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="action" @click="fullscreen = !fullscreen">
|
||||
<i-material-symbols:fullscreen-exit v-if="fullscreen" />
|
||||
<i-material-symbols:fullscreen v-else />
|
||||
</div>
|
||||
<div class="action" @click="closeModal">
|
||||
<i i-material-symbols:close-rounded />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div :class="fullscreen ? '' : 'editor'">
|
||||
<Editor key="preview" class="editorView" :default-config="editorConfig" @on-created="handleCreated" />
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
font-size: 18px;
|
||||
.action {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.editor {
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
.editor-view {
|
||||
overflow-y: hidden;
|
||||
height: auto;
|
||||
:deep(.w-e-text-container .w-e-scroll [data-slate-editor]) {
|
||||
padding: 0 0px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
CircleClose,
|
||||
User,
|
||||
} from '@element-plus/icons-vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
@@ -20,8 +24,6 @@ function navigateTo(path: string) {
|
||||
|
||||
function exitLogin() {
|
||||
userStore.clearUserInfo()
|
||||
|
||||
navigateTo('/auth/login')
|
||||
}
|
||||
|
||||
function isActive(path: string) {
|
||||
@@ -68,8 +70,10 @@ function isActive(path: string) {
|
||||
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||
<el-dropdown-item @click="exitLogin()">
|
||||
<el-dropdown-item :icon="User" @click="navigateTo('/settings')">
|
||||
个人中心
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :icon="CircleClose" @click="exitLogin()">
|
||||
退出登录
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import Header from './components/header.vue'
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -9,26 +8,25 @@ import Header from './components/header.vue'
|
||||
<div class="content">
|
||||
<RouterView />
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<!-- <footer class="footer">
|
||||
footer
|
||||
</footer>
|
||||
</footer> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app {
|
||||
position: relative;
|
||||
background-color: #eff2f6;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 60px;
|
||||
height: 1800px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 32px;
|
||||
height: 100px;
|
||||
background-color: #ccc;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import type { InitBaseDataResult } from '@/types/base'
|
||||
import { httpGet } from '@/request/utils'
|
||||
import type { AddFileParams, GetAliyunKeyResult, InitBaseDataResult } from '@/types/base'
|
||||
import { httpGet, httpPostJson } from '@/request/utils'
|
||||
|
||||
export function initBaseApi() {
|
||||
return httpGet<InitBaseDataResult>(`/base/init`)
|
||||
}
|
||||
|
||||
export function getAliyunKeyApi() {
|
||||
return httpGet<GetAliyunKeyResult>(`/base/file/getAliyunKey`)
|
||||
}
|
||||
|
||||
export function addFileApi(params: AddFileParams) {
|
||||
return httpPostJson<void>(`/base/file/add`, params)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { RecommendCompany, RecommendHotCompany } from '@/types/company'
|
||||
import { httpGet } from '@/request/utils'
|
||||
import type { CompanyDetail, CompanyListItem, QueryCompanyParams, RecommendCompany, RecommendHotCompany } from '@/types/company'
|
||||
import { httpGet, httpPostJson } from '@/request/utils'
|
||||
|
||||
export function getRecommendCompanyApi() {
|
||||
return httpGet<RecommendCompany[]>('/company/recommend')
|
||||
@@ -8,3 +8,11 @@ export function getRecommendCompanyApi() {
|
||||
export function getRecommendHotCompanyApi() {
|
||||
return httpGet<RecommendHotCompany[]>('/company/recommend/hot')
|
||||
}
|
||||
|
||||
export function queryCompanyApi(params: QueryCompanyParams) {
|
||||
return httpPostJson<BasePageResult<CompanyListItem>>('/company/query', params)
|
||||
}
|
||||
|
||||
export function getCompanyDetailApi(id: number) {
|
||||
return httpGet<CompanyDetail>(`/company/detail/${id}`)
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { App } from 'vue'
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Layout from '@/layout/index.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
history: createWebHistory(),
|
||||
strict: true,
|
||||
routes: [
|
||||
{
|
||||
@@ -18,6 +18,10 @@ const router = createRouter({
|
||||
path: '/company',
|
||||
component: () => import('@/views/company/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/company/detail',
|
||||
component: () => import('@/views/company/detail/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -14,63 +14,10 @@ export const useCommonStore = defineStore(
|
||||
name: '',
|
||||
})
|
||||
|
||||
/**
|
||||
* 根据 Area id 获取完整路径,例如 "天津市/滨海新区/塘沽"
|
||||
*/
|
||||
function getAreaFullPathById(id: string): string {
|
||||
// 递归查找节点
|
||||
function findNode(id: string, nodes: Area[]): Area | null {
|
||||
for (const node of nodes) {
|
||||
if (node.id === id)
|
||||
return node
|
||||
if (node.children && node.children.length) {
|
||||
const found = findNode(id, node.children)
|
||||
if (found)
|
||||
return found
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const node = findNode(id, areaOptions)
|
||||
if (!node)
|
||||
return ''
|
||||
|
||||
// 构建完整路径
|
||||
const names: string[] = []
|
||||
let current: Area | undefined | null = node
|
||||
while (current) {
|
||||
names.unshift(current.name)
|
||||
current = current.fatherId ? findNode(current.fatherId, areaOptions) || undefined : undefined
|
||||
}
|
||||
|
||||
return names.join(',')
|
||||
}
|
||||
|
||||
function getAreaIdByFullPath(fullPath: string): string | null {
|
||||
const names = fullPath.split(',').map(s => s.trim())
|
||||
if (!names.length)
|
||||
return null
|
||||
|
||||
let currentNodes = areaOptions
|
||||
let foundNode: Area | null = null
|
||||
|
||||
for (const name of names) {
|
||||
foundNode = currentNodes.find(n => n.name === name) || null
|
||||
if (!foundNode)
|
||||
return null
|
||||
currentNodes = foundNode.children || []
|
||||
}
|
||||
|
||||
return foundNode?.id || null
|
||||
}
|
||||
|
||||
return {
|
||||
areaOptions,
|
||||
industryOptions,
|
||||
companyQuery,
|
||||
getAreaFullPathById,
|
||||
getAreaIdByFullPath,
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -1,3 +1,7 @@
|
||||
html, body {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -12,25 +12,45 @@ export {}
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AreaSelect: typeof import('./../components/AreaSelect.vue')['default']
|
||||
Directory: typeof import('./../components/wang-editor/modules/directory.vue')['default']
|
||||
HelloWorld: typeof import('./../components/HelloWorld.vue')['default']
|
||||
ICarbonAccessibility: typeof import('~icons/carbon/accessibility')['default']
|
||||
'IFa7Solid:userShield': typeof import('~icons/fa7-solid/user-shield')['default']
|
||||
'IIc:twotoneHeadphones': typeof import('~icons/ic/twotone-headphones')['default']
|
||||
'IIconoir:infoCircleSolid': typeof import('~icons/iconoir/info-circle-solid')['default']
|
||||
'IMaterialSymbols:call': typeof import('~icons/material-symbols/call')['default']
|
||||
'IMaterialSymbols:chatBubbleOutline': typeof import('~icons/material-symbols/chat-bubble-outline')['default']
|
||||
'IMaterialSymbols:folderCopyOutline': typeof import('~icons/material-symbols/folder-copy-outline')['default']
|
||||
'IMaterialSymbols:fullscreen': typeof import('~icons/material-symbols/fullscreen')['default']
|
||||
'IMaterialSymbols:fullscreenExit': typeof import('~icons/material-symbols/fullscreen-exit')['default']
|
||||
'IMaterialSymbols:locationOn': typeof import('~icons/material-symbols/location-on')['default']
|
||||
'IMaterialSymbols:locationOnOutlineRounded': typeof import('~icons/material-symbols/location-on-outline-rounded')['default']
|
||||
'IMaterialSymbols:lockOpenRightSharp': typeof import('~icons/material-symbols/lock-open-right-sharp')['default']
|
||||
'IMaterialSymbols:mail': typeof import('~icons/material-symbols/mail')['default']
|
||||
IMdiAccountBox: typeof import('~icons/mdi/account-box')['default']
|
||||
'IMingcute:chat1Fill': typeof import('~icons/mingcute/chat1-fill')['default']
|
||||
'IMingcute:eye2Line': typeof import('~icons/mingcute/eye2-line')['default']
|
||||
Industry: typeof import('../components/IndustrySelect.vue')['default']
|
||||
IndustrySelect: typeof import('./../components/IndustrySelect.vue')['default']
|
||||
'INrk:show': typeof import('~icons/nrk/show')['default']
|
||||
'IRi:buildingFill': typeof import('~icons/ri/building-fill')['default']
|
||||
'IRi:buildingLine': typeof import('~icons/ri/building-line')['default']
|
||||
'IRi:information2Line': typeof import('~icons/ri/information2-line')['default']
|
||||
'IRi:informationFill': typeof import('~icons/ri/information-fill')['default']
|
||||
'IRi:message3Fill': typeof import('~icons/ri/message3-fill')['default']
|
||||
'ISolar:chatRoundBold': typeof import('~icons/solar/chat-round-bold')['default']
|
||||
'ISolar:chatRoundCallBroken': typeof import('~icons/solar/chat-round-call-broken')['default']
|
||||
'ISolar:eyeBroken': typeof import('~icons/solar/eye-broken')['default']
|
||||
'ISolar:eyeClosedBroken': typeof import('~icons/solar/eye-closed-broken')['default']
|
||||
'IStreamlineUltimate:informationCircleBold': typeof import('~icons/streamline-ultimate/information-circle-bold')['default']
|
||||
'ITdesign:notification': typeof import('~icons/tdesign/notification')['default']
|
||||
'ITdesign:search': typeof import('~icons/tdesign/search')['default']
|
||||
Preview: typeof import('./../components/wang-editor/modules/preview.vue')['default']
|
||||
QueryCompany: typeof import('./../components/QueryCompany.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SafeImage: typeof import('./../components/SafeImage.vue')['default']
|
||||
UploadProgress: typeof import('./../components/upload-progress/index.vue')['default']
|
||||
WangEditor: typeof import('./../components/wang-editor/index.vue')['default']
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,22 @@ export interface InitBaseDataResult {
|
||||
|
||||
export interface CompanyQuery {
|
||||
industries: string[]
|
||||
areas: string[]
|
||||
areas: string[][]
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface GetAliyunKeyResult {
|
||||
accessid: string
|
||||
policy: string
|
||||
signature: string
|
||||
dir: string
|
||||
host: string
|
||||
expire: string
|
||||
callback: string
|
||||
}
|
||||
|
||||
export interface AddFileParams {
|
||||
fileName: string
|
||||
fileSize: string
|
||||
fileMapName: string
|
||||
}
|
||||
@@ -12,3 +12,44 @@ export interface RecommendHotCompany {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface QueryCompanyParams {
|
||||
currentPage: number
|
||||
pageSize: number
|
||||
|
||||
areas: string[]
|
||||
industries: string[]
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface CompanyListItem {
|
||||
id: number
|
||||
name: string
|
||||
areas: string[]
|
||||
industries: string[]
|
||||
logo: string
|
||||
profile: string
|
||||
phone: string
|
||||
email: string
|
||||
}
|
||||
|
||||
export interface CompanyDetail {
|
||||
id: number
|
||||
name: string
|
||||
areas: string[]
|
||||
industries: string[]
|
||||
logo: string
|
||||
profile: string
|
||||
phone: string
|
||||
email: string
|
||||
description: string
|
||||
users: {
|
||||
id: number
|
||||
companyId: number
|
||||
phone: string
|
||||
email: string
|
||||
role: number
|
||||
position: string
|
||||
name: string
|
||||
}[]
|
||||
}
|
||||
@@ -7,4 +7,15 @@ declare global {
|
||||
message: string
|
||||
data: T
|
||||
}
|
||||
|
||||
interface BasePageResult<T> {
|
||||
total: number
|
||||
records: T[]
|
||||
}
|
||||
|
||||
interface Pagination {
|
||||
total: number
|
||||
current: number
|
||||
pageSize: number
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { closeUploadProgress, showUploadProgress, updateUploadProgress } from '@/components/upload-progress/index'
|
||||
import { addFileApi, getAliyunKeyApi } from '@/request/api/base'
|
||||
|
||||
export interface UploadImageResponse {
|
||||
name: string
|
||||
size: string
|
||||
url: string
|
||||
blob: Blob
|
||||
}
|
||||
|
||||
export function uploadImage(options: {
|
||||
quality?: number
|
||||
mimeType?: string
|
||||
} = {}): Promise<UploadImageResponse> {
|
||||
const { quality = 0.8, mimeType = 'image/webp' } = options
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof document === 'undefined') {
|
||||
reject(new Error('Require browser environment'))
|
||||
return
|
||||
}
|
||||
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = 'image/*'
|
||||
input.style.display = 'none'
|
||||
|
||||
const processImage = (file: File): Promise<UploadImageResponse> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
const objectURL = URL.createObjectURL(file)
|
||||
|
||||
img.onload = () => {
|
||||
try {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx)
|
||||
throw new Error('Canvas init failed')
|
||||
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
|
||||
|
||||
URL.revokeObjectURL(objectURL)
|
||||
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
if (!blob) {
|
||||
reject(new Error('Compression failed'))
|
||||
return
|
||||
}
|
||||
resolve({ name: file.name, size: blob.size.toString(), url: URL.createObjectURL(blob), blob })
|
||||
},
|
||||
mimeType,
|
||||
quality,
|
||||
)
|
||||
}
|
||||
catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
img.onerror = () => {
|
||||
URL.revokeObjectURL(objectURL)
|
||||
reject(new Error('Image load failed'))
|
||||
}
|
||||
|
||||
img.src = objectURL
|
||||
})
|
||||
}
|
||||
|
||||
input.onchange = async (event) => {
|
||||
const file = (event.target as HTMLInputElement).files?.[0]
|
||||
if (!file) {
|
||||
reject(new Error('No file selected'))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
throw new Error('Invalid image file')
|
||||
}
|
||||
|
||||
const result = await processImage(file)
|
||||
resolve(result)
|
||||
}
|
||||
catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
finally {
|
||||
document.body.removeChild(input)
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(input)
|
||||
input.click()
|
||||
})
|
||||
}
|
||||
export interface UploadVideoResponse {
|
||||
name: string
|
||||
size: string
|
||||
url: string
|
||||
blob: Blob
|
||||
}
|
||||
|
||||
export function uploadVideo(): Promise<UploadVideoResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof document === 'undefined') {
|
||||
reject(new Error('Require browser environment'))
|
||||
return
|
||||
}
|
||||
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = 'video/*'
|
||||
input.style.display = 'none'
|
||||
|
||||
input.onchange = (event) => {
|
||||
const file = (event.target as HTMLInputElement).files?.[0]
|
||||
if (!file) {
|
||||
reject(new Error('No file selected'))
|
||||
return
|
||||
}
|
||||
|
||||
if (!file.type.startsWith('video/')) {
|
||||
reject(new Error('Invalid video file'))
|
||||
return
|
||||
}
|
||||
|
||||
resolve({
|
||||
name: file.name,
|
||||
size: file.size.toString(),
|
||||
url: URL.createObjectURL(file),
|
||||
blob: file,
|
||||
})
|
||||
|
||||
document.body.removeChild(input)
|
||||
}
|
||||
|
||||
document.body.appendChild(input)
|
||||
input.click()
|
||||
})
|
||||
}
|
||||
|
||||
export interface UploadToAliyunResponse {
|
||||
url: string
|
||||
fileName: string
|
||||
fileSize: string
|
||||
}
|
||||
|
||||
export function uploadToAliyun(blob: Blob, fileName: string, fileSize: string, onProgress?: (percent: number) => void): Promise<UploadToAliyunResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 在开始上传时显示上传进度
|
||||
showUploadProgress('uploading')
|
||||
|
||||
getAliyunKeyApi()
|
||||
.then(async (res) => {
|
||||
try {
|
||||
const aliyunKey = res.data
|
||||
const formData = new FormData()
|
||||
|
||||
const fileExt = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : ''
|
||||
const uniqueName = `sl_${Date.now()}_${Math.random().toString(36).slice(2)}${fileExt}`
|
||||
|
||||
formData.append('key', `${aliyunKey.dir}${uniqueName}`)
|
||||
formData.append('OSSAccessKeyId', aliyunKey.accessid)
|
||||
formData.append('policy', aliyunKey.policy)
|
||||
formData.append('Signature', aliyunKey.signature)
|
||||
formData.append('file', blob, uniqueName)
|
||||
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.open('POST', aliyunKey.host, true)
|
||||
|
||||
// 监听上传进度
|
||||
xhr.upload.onprogress = (event) => {
|
||||
if (event.lengthComputable && onProgress) {
|
||||
const percent = (event.loaded / event.total) * 100
|
||||
onProgress(Number.parseFloat(percent.toFixed(2))) // 保留两位小数
|
||||
updateUploadProgress(percent) // 更新进度条
|
||||
}
|
||||
}
|
||||
|
||||
xhr.onload = async () => {
|
||||
if (xhr.status === 204 || xhr.status === 200) {
|
||||
const allFilePath = `${aliyunKey.host}/${aliyunKey.dir}${uniqueName}`
|
||||
|
||||
await addFileApi({
|
||||
fileName,
|
||||
fileSize,
|
||||
fileMapName: allFilePath,
|
||||
})
|
||||
|
||||
updateUploadProgress(100) // 上传完毕
|
||||
ElMessage.success('上传成功')
|
||||
|
||||
setTimeout(() => {
|
||||
closeUploadProgress() // 关闭上传进度条
|
||||
}, 500)
|
||||
|
||||
resolve({
|
||||
url: allFilePath,
|
||||
fileName,
|
||||
fileSize,
|
||||
})
|
||||
}
|
||||
else {
|
||||
updateUploadProgress(0, 'failed') // 上传失败
|
||||
ElMessage.error('上传失败,请稍后再试')
|
||||
|
||||
setTimeout(() => {
|
||||
closeUploadProgress() // 关闭上传进度条
|
||||
}, 500)
|
||||
|
||||
reject(new Error(`OSS上传失败: ${xhr.responseText}`))
|
||||
}
|
||||
}
|
||||
|
||||
xhr.onerror = () => {
|
||||
updateUploadProgress(0, 'failed') // 上传失败
|
||||
ElMessage.error('上传失败,请稍后再试')
|
||||
|
||||
setTimeout(() => {
|
||||
closeUploadProgress() // 关闭上传进度条
|
||||
}, 500)
|
||||
reject(new Error(`OSS上传异常: ${xhr.responseText}`))
|
||||
}
|
||||
|
||||
xhr.send(formData)
|
||||
}
|
||||
catch (error) {
|
||||
updateUploadProgress(0, 'failed') // 上传失败
|
||||
ElMessage.error('上传失败,请稍后再试')
|
||||
|
||||
setTimeout(() => {
|
||||
closeUploadProgress() // 关闭上传进度条
|
||||
}, 500)
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
.catch(reject)
|
||||
})
|
||||
}
|
||||
@@ -134,6 +134,7 @@ function onSubmit() {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
|
||||
.auth-bg {
|
||||
width: 70%;
|
||||
|
||||
@@ -351,7 +351,7 @@ function navigateTo(path: string) {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: #fff;
|
||||
.auth-bg {
|
||||
width: 70%;
|
||||
height: 100%;
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CompanyDetail } from '@/types/company'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import WangEditor from '@/components/wang-editor/index.vue'
|
||||
import { getCompanyDetailApi } from '@/request/api/company'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const companyId = ref<number>(0)
|
||||
|
||||
const companyDetail = ref<CompanyDetail>({
|
||||
id: 0,
|
||||
name: '',
|
||||
areas: [],
|
||||
industries: [],
|
||||
logo: '',
|
||||
profile: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
description: '',
|
||||
users: [],
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
companyId.value = Number(route.query.id) || 0
|
||||
|
||||
if (!companyId.value) {
|
||||
router.push('/')
|
||||
return
|
||||
}
|
||||
|
||||
getCompanyDetailApi(companyId.value).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
companyDetail.value = res.data
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '加载公司信息失败,请稍后再试')
|
||||
router.push('/')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('加载公司信息失败,请稍后再试')
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="company-detail-page">
|
||||
<div class="detail-container">
|
||||
<div class="header-region">
|
||||
<el-avatar shape="square" :size="64" class="logo" :src="companyDetail.logo || '/no-avatar.png'" />
|
||||
<div class="info">
|
||||
<div class="title">
|
||||
<span>{{ companyDetail.name }}</span>
|
||||
</div>
|
||||
<div class="tag-section">
|
||||
<el-tag v-for="item in companyDetail.industries" :key="item" type="primary">
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-region">
|
||||
<div id="basic" class="info-item">
|
||||
<div class="info-header">
|
||||
<span class="info-title">基础信息</span>
|
||||
</div>
|
||||
|
||||
<el-descriptions border>
|
||||
<el-descriptions-item label="电话">
|
||||
{{ companyDetail.phone || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="邮箱">
|
||||
{{ companyDetail.email || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="成立日期">
|
||||
-
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="区域">
|
||||
{{ companyDetail.areas.join('/') || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="详细地址" :span="2">
|
||||
-
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div id="profile" class="info-item">
|
||||
<div class="info-header">
|
||||
<span class="info-title">公司简介</span>
|
||||
</div>
|
||||
<span class="company-profile">
|
||||
{{ companyDetail.profile || '-' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="users" class="info-item">
|
||||
<div class="info-header">
|
||||
<span class="info-title">公司成员</span>
|
||||
</div>
|
||||
<el-table :data="companyDetail.users" style="width: 100%" stripe border>
|
||||
<el-table-column prop="name" label="姓名" width="180" />
|
||||
<el-table-column prop="position" label="职务" width="180" />
|
||||
<el-table-column prop="phone" label="手机号" width="180" />
|
||||
<el-table-column prop="email" label="邮箱号" width="180" />
|
||||
<el-table-column fixed="right" label="操作" min-width="120">
|
||||
<template #default>
|
||||
<el-button type="primary" size="small" text bg>
|
||||
发起聊天
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div id="description" class="info-item">
|
||||
<div class="info-header">
|
||||
<span class="info-title">公司详细介绍</span>
|
||||
</div>
|
||||
<WangEditor v-model="companyDetail.description" mode="view" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="anchor-container">
|
||||
<el-affix :offset="80">
|
||||
<div class="anchor-title">
|
||||
导航
|
||||
</div>
|
||||
<el-anchor :offset="70">
|
||||
<el-anchor-link href="#basic">
|
||||
基础信息
|
||||
</el-anchor-link>
|
||||
<el-anchor-link href="#profile">
|
||||
公司简介
|
||||
</el-anchor-link>
|
||||
<el-anchor-link href="#users">
|
||||
公司成员
|
||||
</el-anchor-link>
|
||||
<el-anchor-link href="#description">
|
||||
公司详细介绍
|
||||
</el-anchor-link>
|
||||
</el-anchor>
|
||||
</el-affix>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.company-detail-page {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 48px 0px;
|
||||
|
||||
.detail-container {
|
||||
width: 1250px;
|
||||
|
||||
.header-region {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
.info {
|
||||
margin-left: 16px;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.tag-section {
|
||||
margin-top: 4px;
|
||||
> * {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-region {
|
||||
margin-top: 36px;
|
||||
background-color: #fff;
|
||||
padding: 16px;
|
||||
|
||||
.info-item {
|
||||
margin-bottom: 24px;
|
||||
|
||||
:deep(.el-table__header) {
|
||||
.el-table__cell {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-header {
|
||||
height: 32px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.info-title {
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.company-profile {
|
||||
word-break: break-all;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.anchor-container {
|
||||
min-width: 200px;
|
||||
margin-left: 40px;
|
||||
.anchor-title {
|
||||
background-color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
padding-left: 14px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
:deep(.el-anchor) {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,23 +1,275 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CompanyListItem } from '@/types/company'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import QueryCompany from '@/components/QueryCompany.vue'
|
||||
import { queryCompanyApi } from '@/request/api/company'
|
||||
import { useCommonStore } from '@/store/common'
|
||||
|
||||
const router = useRouter()
|
||||
const commonStore = useCommonStore()
|
||||
|
||||
const page = reactive<Pagination>({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
})
|
||||
|
||||
const loading = ref<boolean>(true)
|
||||
|
||||
const companyList = ref<CompanyListItem[]>([])
|
||||
|
||||
onMounted(() => {
|
||||
getCompanyList()
|
||||
})
|
||||
|
||||
function getCompanyList() {
|
||||
loading.value = true
|
||||
|
||||
queryCompanyApi({
|
||||
currentPage: page.current,
|
||||
pageSize: page.pageSize,
|
||||
|
||||
areas: commonStore.companyQuery.areas.map((item: string[]) => item.join(',')),
|
||||
industries: commonStore.companyQuery.industries,
|
||||
name: commonStore.companyQuery.name,
|
||||
}).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
companyList.value = res.data.records
|
||||
page.total = res.data.total
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '加载失败,请稍后再试')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('加载失败,请稍后再试')
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function toDetail(data: CompanyListItem) {
|
||||
router.push({
|
||||
path: '/company/detail',
|
||||
query: {
|
||||
id: data.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="query">
|
||||
<QueryCompany style="width: 1200px;" />
|
||||
<div class="company-wrapper">
|
||||
<div class="company-container">
|
||||
<QueryCompany @search="getCompanyList()" />
|
||||
|
||||
<div class="list-container">
|
||||
<div class="list-header">
|
||||
<div class="search-title">
|
||||
为您找到
|
||||
<span>
|
||||
{{ page.total }}
|
||||
</span>
|
||||
条相关企业
|
||||
</div>
|
||||
</div>
|
||||
<div class="company-list">
|
||||
<div v-for="item in companyList" :key="item.id" class="company-item">
|
||||
<el-avatar shape="square" :src="item.logo || '/no-avatar.png'" :size="70" class="company-logo" />
|
||||
|
||||
<div class="company-info">
|
||||
<div class="company-header">
|
||||
<div class="company-name">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="company-tags">
|
||||
<el-tag v-for="tag in item.industries" :key="tag" type="primary" effect="dark">
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<p class="company-profile">
|
||||
{{ item.profile || '-' }}
|
||||
</p>
|
||||
<div class="company-footer">
|
||||
<div class="company-details">
|
||||
<div class="detail-item">
|
||||
<i-material-symbols:location-on />
|
||||
<span>{{ item.areas.join('/') || '___' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<i-material-symbols:mail />
|
||||
<span>{{ item.email || '___' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<i-material-symbols:call />
|
||||
<span>{{ item.phone || '___' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="company-actions">
|
||||
<el-button @click="toDetail(item)">
|
||||
<i-ri:information-2-line />
|
||||
<span class="button-text">
|
||||
详细
|
||||
</span>
|
||||
</el-button>
|
||||
|
||||
<el-button type="primary">
|
||||
<i-ri:message-3-fill />
|
||||
<span class="button-text">
|
||||
发起聊天
|
||||
</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="company-pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="page.current"
|
||||
:page-size="page.pageSize"
|
||||
:total="page.total"
|
||||
layout="prev, pager, next"
|
||||
background
|
||||
size="large"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
.company-wrapper {
|
||||
width: 100%;
|
||||
.query {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.company-container {
|
||||
padding: 48px 0px;
|
||||
width: 1250px;
|
||||
}
|
||||
|
||||
.list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 36px;
|
||||
|
||||
.list-header {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
background-color: #fff;
|
||||
.search-title {
|
||||
font-weight: bold;
|
||||
span {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.company-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.company-item {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 13px 26px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
&:hover {
|
||||
background-color: #f2f8fe;
|
||||
|
||||
.company-name {
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.company-logo {
|
||||
flex-shrink: 0;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.company-info {
|
||||
flex: 1;
|
||||
|
||||
.company-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
|
||||
.company-name {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.company-tags {
|
||||
margin-bottom: 6px;
|
||||
> * {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.company-profile {
|
||||
color: #64748b;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.company-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.company-details {
|
||||
display: flex;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 16px;
|
||||
span {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.company-actions {
|
||||
display: flex;
|
||||
> * {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.button-text {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.company-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
margin: 16px 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -127,7 +127,6 @@ defineProps({
|
||||
}
|
||||
|
||||
.area-row:hover {
|
||||
background-color: #f9f9fb;
|
||||
}
|
||||
|
||||
.area-row:last-child {
|
||||
@@ -139,7 +138,7 @@ defineProps({
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 15%;
|
||||
background-color: #f8f9fa;
|
||||
background-color: #fcfcfd;
|
||||
color: #34495e;
|
||||
font-weight: bold;
|
||||
border-right: 1px solid #e0e3e8;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
settings
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//
|
||||
</style>
|
||||
+1668
-1139
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user