Browse Source

直接覆盖KH分支代码

KH
Trae AI 1 month ago
parent
commit
26bb317baa
  1. 2
      web/src/main/java/com/example/web/config/SecurityConfig.java
  2. 5
      web/src/main/java/com/example/web/controller/UserController.java
  3. 4
      web/src/main/java/com/example/web/entity/CustomerApply.java
  4. 2
      web/src/main/java/com/example/web/mapper/CustomerApplyMapper.java
  5. 3
      web/src/main/java/com/example/web/mapper/PersonnelMapper.java
  6. 3
      web/src/main/java/com/example/web/mapper/UserTraceMapper.java
  7. 3
      web/src/main/java/com/example/web/mapper/UsersMapper.java
  8. 3
      web/src/main/java/com/example/web/service/UserService.java
  9. 124
      web/src/main/java/com/example/web/service/impl/CustomerApplyServiceImpl.java
  10. 86
      web/src/main/java/com/example/web/service/impl/UserServiceImpl.java
  11. 4
      web/src/main/resources/mapper/CustomerApplyMapper.xml
  12. 4
      web/src/main/resources/mapper/PersonnelMapper.xml
  13. 8
      web/src/main/resources/mapper/UserTraceMapper.xml
  14. 4
      web/src/main/resources/mapper/UsersMapper.xml
  15. 719
      web/src/main/resources/static/index.html
  16. 2
      web/src/main/resources/static/login.html

2
web/src/main/java/com/example/web/config/SecurityConfig.java

@ -14,7 +14,7 @@ public class SecurityConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers("/login.html", "/index.html", "/api/login", "/api/users/**", "/api/products/**").permitAll()
.requestMatchers("/login.html", "/index.html", "/api/login", "/api/users/**", "/api/products/**", "/api/personnel/**").permitAll()
.requestMatchers("/static/**").permitAll()
.anyRequest().authenticated()
.and()

5
web/src/main/java/com/example/web/controller/UserController.java

@ -139,4 +139,9 @@ public class UserController {
@RequestParam String productId) {
return userService.getProductDetail(productId);
}
@GetMapping("/personnel")
public Map<String, Object> getPersonnelList() {
return userService.getPersonnelList();
}
}

4
web/src/main/java/com/example/web/entity/CustomerApply.java

@ -16,16 +16,18 @@ public class CustomerApply {
private String user_id; // 客户ID
private String sales_id; // 业务员ID
private String sales_name; // 业务员姓名
private String original_manager_name; // 原始负责人姓名
private Integer status; // 申请状态:0-申请中,1-通过,2-失败
private LocalDateTime apply_time; // 申请时间
private LocalDateTime approve_time; // 审批时间
private String approve_by; // 审批人
private String reason; // 申请理由/失败原因
public CustomerApply(String user_id, String sales_id, String sales_name, String reason) {
public CustomerApply(String user_id, String sales_id, String sales_name, String original_manager_name, String reason) {
this.user_id = user_id;
this.sales_id = sales_id;
this.sales_name = sales_name;
this.original_manager_name = original_manager_name;
this.status = 0; // 默认状态为申请中
this.apply_time = LocalDateTime.now();
this.reason = reason;

2
web/src/main/java/com/example/web/mapper/CustomerApplyMapper.java

@ -1,5 +1,6 @@
package com.example.web.mapper;
import com.example.web.annotation.DataSource;
import com.example.web.entity.CustomerApply;
import java.util.List;
@ -8,6 +9,7 @@ import java.util.Map;
/**
* 客户申请Mapper接口
*/
@DataSource("wechat")
public interface CustomerApplyMapper {
/**

3
web/src/main/java/com/example/web/mapper/PersonnelMapper.java

@ -12,6 +12,9 @@ public interface PersonnelMapper {
@DataSource("primary")
Personnel findByNameAndProjectName(String name, String projectName);
@DataSource("primary")
Personnel findByPhoneNumber(String phoneNumber);
@DataSource("primary")
List<Personnel> findAll();
}

3
web/src/main/java/com/example/web/mapper/UserTraceMapper.java

@ -9,4 +9,7 @@ public interface UserTraceMapper {
@DataSource("wechat")
List<UserTrace> getProductTraces(String productId);
@DataSource("wechat")
UserTrace findById(Integer id);
}

3
web/src/main/java/com/example/web/mapper/UsersMapper.java

@ -75,4 +75,7 @@ public interface UsersMapper {
@DataSource("wechat")
List<Users> findAllUsers();
@DataSource("wechat")
Users findByPhoneNumber(String phoneNumber);
}

3
web/src/main/java/com/example/web/service/UserService.java

@ -32,4 +32,7 @@ public interface UserService {
Map<String, Object> applyCustomer(Map<String, Object> params);
Map<String, Object> approveApply(Map<String, Object> params);
List<CustomerApply> getApplyList(Integer status);
// 获取人员列表
Map<String, Object> getPersonnelList();
}

124
web/src/main/java/com/example/web/service/impl/CustomerApplyServiceImpl.java

@ -1,13 +1,17 @@
package com.example.web.service.impl;
import com.example.web.entity.CustomerApply;
import com.example.web.entity.InformationTra;
import com.example.web.entity.Personnel;
import com.example.web.entity.UserTrace;
import com.example.web.entity.Users;
import com.example.web.mapper.CustomerApplyMapper;
import com.example.web.mapper.PersonnelMapper;
import com.example.web.mapper.UserTraceMapper;
import com.example.web.mapper.UsersMapper;
import com.example.web.mapper.UsersManagementsMapper;
import com.example.web.service.CustomerApplyService;
import com.example.web.service.InformationTraService;
import com.example.web.config.DataSourceContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -35,26 +39,61 @@ public class CustomerApplyServiceImpl implements CustomerApplyService {
@Autowired
private UsersMapper usersMapper;
@Autowired
private UserTraceMapper userTraceMapper;
@Autowired
private InformationTraService informationTraService;
@Override
public Map<String, Object> submitApply(Map<String, Object> params) {
Map<String, Object> result = new HashMap<>();
try {
// 切换到wechat数据源
DataSourceContextHolder.setDataSource("wechat");
String userId = (String) params.get("userId");
String salesId = (String) params.get("salesId");
// 获取当前登录信息
String salesName = (String) params.get("salesName");
String reason = (String) params.get("reason");
String traceId = (String) params.get("traceId"); // 从前端传递的浏览记录ID
if (userId == null || salesId == null || salesName == null) {
if (salesName == null || traceId == null) {
result.put("success", false);
result.put("message", "缺少必要参数");
return result;
}
// 检查是否已经有申请记录
// 1. 到primary数据源的personnel表里获取业务员的信息
DataSourceContextHolder.setDataSource("primary");
Personnel personnel = personnelMapper.findByName(salesName);
if (personnel == null || personnel.getPhoneNumber() == null) {
result.put("success", false);
result.put("message", "未找到业务员信息");
return result;
}
String phoneNumber = personnel.getPhoneNumber();
// 2. 到wechat数据源的users表里查询业务员的userId
DataSourceContextHolder.setDataSource("wechat");
Users salesUser = usersMapper.findByPhoneNumber(phoneNumber);
if (salesUser == null || salesUser.getUserId() == null) {
result.put("success", false);
result.put("message", "未找到业务员的用户ID");
return result;
}
String salesId = salesUser.getUserId(); // 业务员的ID
// 3. 到wechat数据源的usertraces表里获取相应的客户userId
UserTrace trace = userTraceMapper.findById(Integer.parseInt(traceId));
if (trace == null || trace.getUserId() == null) {
result.put("success", false);
result.put("message", "未找到浏览记录信息");
return result;
}
String userId = trace.getUserId(); // 客户的ID
// 允许自己申请自己,这是合理的测试场景
// 如果需要防止这种情况,可以在此处添加验证
// 4. 检查是否已经有申请记录
CustomerApply existingApply = customerApplyMapper.findByUserIdAndSalesId(userId, salesId);
if (existingApply != null && existingApply.getStatus() == 0) {
result.put("success", false);
@ -62,8 +101,15 @@ public class CustomerApplyServiceImpl implements CustomerApplyService {
return result;
}
// 创建新的申请记录
CustomerApply apply = new CustomerApply(userId, salesId, salesName, reason);
// 5. 获取客户的原始负责人信息
String original_manager_name = null;
com.example.web.entity.UsersManagements existingManagements = usersManagementsMapper.findByUserId(userId);
if (existingManagements != null) {
original_manager_name = existingManagements.getUserName();
}
// 6. 创建新的申请记录
CustomerApply apply = new CustomerApply(userId, salesId, salesName, original_manager_name, reason);
int count = customerApplyMapper.insert(apply);
if (count > 0) {
@ -121,20 +167,28 @@ public class CustomerApplyServiceImpl implements CustomerApplyService {
// 根据id查询完整的申请记录
CustomerApply apply = customerApplyMapper.findById(id);
if (apply != null) {
// 实现更新客户负责人的逻辑
// 1. 使用wechat数据源的customer_apply表里的user_id到usermanagements表里查询
com.example.web.entity.UsersManagements usersManagements = usersManagementsMapper.findByUserId(apply.getUser_id());
// 切换到primary数据源查询personnel表
// 2. 将customer_apply表里的original_manager_name的值放到primary数据源的personnel数据源里获取信息
DataSourceContextHolder.setDataSource("primary");
Personnel originalPersonnel = null;
if (apply.getOriginal_manager_name() != null) {
try {
originalPersonnel = personnelMapper.findByName(apply.getOriginal_manager_name());
} catch (Exception e) {
e.printStackTrace();
System.out.println("查询原始负责人信息时发生错误: " + e.getMessage());
}
}
// 从personnel表中查询业务员的详细信息
Personnel personnel = null;
// 3. 从personnel表中查询业务员的详细信息
Personnel salesPersonnel = null;
try {
// 只通过name查询业务员信息
personnel = personnelMapper.findByName(apply.getSales_name());
salesPersonnel = personnelMapper.findByName(apply.getSales_name());
} catch (Exception e) {
e.printStackTrace();
System.out.println("查询Personnel时发生错误: " + e.getMessage());
System.out.println("查询业务员信息时发生错误: " + e.getMessage());
}
// 切换回wechat数据源
@ -144,11 +198,11 @@ public class CustomerApplyServiceImpl implements CustomerApplyService {
// 更新现有记录
usersManagements.setManagerId(apply.getSales_id());
usersManagements.setUserName(apply.getSales_name());
if (personnel != null) {
usersManagements.setManagercompany(personnel.getManagercompany());
usersManagements.setManagerdepartment(personnel.getManagerdepartment());
usersManagements.setOrganization(personnel.getOrganization());
usersManagements.setRole(personnel.getProjectName()); // projectName与role同值
if (salesPersonnel != null) {
usersManagements.setManagercompany(salesPersonnel.getManagercompany());
usersManagements.setManagerdepartment(salesPersonnel.getManagerdepartment());
usersManagements.setOrganization(salesPersonnel.getOrganization());
usersManagements.setRole(salesPersonnel.getProjectName()); // role与projectName同值
}
usersManagements.setUpdated_at(LocalDateTime.now());
usersManagementsMapper.update(usersManagements);
@ -167,11 +221,11 @@ public class CustomerApplyServiceImpl implements CustomerApplyService {
newUsersManagements.setUserId(apply.getUser_id());
newUsersManagements.setManagerId(apply.getSales_id());
newUsersManagements.setUserName(apply.getSales_name());
if (personnel != null) {
newUsersManagements.setManagercompany(personnel.getManagercompany());
newUsersManagements.setManagerdepartment(personnel.getManagerdepartment());
newUsersManagements.setOrganization(personnel.getOrganization());
newUsersManagements.setRole(personnel.getProjectName()); // projectName与role同值
if (salesPersonnel != null) {
newUsersManagements.setManagercompany(salesPersonnel.getManagercompany());
newUsersManagements.setManagerdepartment(salesPersonnel.getManagerdepartment());
newUsersManagements.setOrganization(salesPersonnel.getOrganization());
newUsersManagements.setRole(salesPersonnel.getProjectName()); // role与projectName同值
}
newUsersManagements.setCreated_at(LocalDateTime.now());
newUsersManagements.setUpdated_at(LocalDateTime.now());
@ -185,6 +239,24 @@ public class CustomerApplyServiceImpl implements CustomerApplyService {
System.out.println("客户ID " + apply.getUser_id() + " 在users表中不存在,无法创建usermanagements记录");
}
}
// 记录分配操作
try {
com.example.web.entity.InformationTra tra = new com.example.web.entity.InformationTra();
if (salesPersonnel != null) {
tra.setTracompany(salesPersonnel.getManagercompany());
tra.setTradepartment(salesPersonnel.getManagerdepartment());
tra.setTraorganization(salesPersonnel.getOrganization());
tra.setTrarole(salesPersonnel.getProjectName());
}
tra.setTrauserName(apply.getSales_name());
tra.setUserId(apply.getUser_id());
tra.setOperationEvent("申请通过分配客户: " + apply.getSales_name());
informationTraService.recordUserOperation(tra);
} catch (Exception e) {
e.printStackTrace();
System.out.println("记录分配操作时发生错误: " + e.getMessage());
}
}
}

86
web/src/main/java/com/example/web/service/impl/UserServiceImpl.java

@ -718,8 +718,76 @@ public class UserServiceImpl implements UserService {
}
}
// 处理产品列表,添加销售负责人和创建人信息
List<Map<String, Object>> processedProducts = new ArrayList<>();
for (Product product : products) {
Map<String, Object> productMap = new HashMap<>();
// 复制原有字段
productMap.put("id", product.getId());
productMap.put("productId", product.getProductId());
productMap.put("sellerId", product.getSellerId());
productMap.put("productName", product.getProductName());
productMap.put("price", product.getPrice());
productMap.put("costprice", product.getCostprice());
productMap.put("quantity", product.getQuantity());
productMap.put("grossWeight", product.getGrossWeight());
productMap.put("yolk", product.getYolk());
productMap.put("specification", product.getSpecification());
productMap.put("created_at", product.getCreated_at());
productMap.put("updated_at", product.getUpdated_at());
productMap.put("status", product.getStatus());
productMap.put("region", product.getRegion());
productMap.put("sourceType", product.getSourceType());
productMap.put("supplyStatus", product.getSupplyStatus());
productMap.put("category", product.getCategory());
productMap.put("producting", product.getProducting());
productMap.put("description", product.getDescription());
productMap.put("frequency", product.getFrequency());
productMap.put("contact_phone", product.getContact_phone());
productMap.put("product_contact", product.getProduct_contact());
productMap.put("negotiateStatus", product.getNegotiateStatus());
productMap.put("fullRegion", product.getFullRegion());
productMap.put("createdAt", product.getCreatedAt());
productMap.put("reservedCount", product.getReservedCount());
productMap.put("reservedCountDisplay", product.getReservedCountDisplay());
productMap.put("sales", product.getSales());
productMap.put("totalStock", product.getTotalStock());
productMap.put("originalTotalStock", product.getOriginalTotalStock());
productMap.put("displaySpecification", product.getDisplaySpecification());
productMap.put("displayYolk", product.getDisplayYolk());
// 计算销售负责人
if (product.getContact_phone() != null && !product.getContact_phone().isEmpty()) {
try {
Personnel salesPersonnel = personnelMapper.findByPhoneNumber(product.getContact_phone());
if (salesPersonnel != null) {
productMap.put("salesManager", salesPersonnel.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 计算创建人
if (product.getSellerId() != null && !product.getSellerId().isEmpty()) {
try {
Users seller = usersMapper.findByUserId(product.getSellerId());
if (seller != null && seller.getPhoneNumber() != null) {
Personnel creatorPersonnel = personnelMapper.findByPhoneNumber(seller.getPhoneNumber());
if (creatorPersonnel != null) {
productMap.put("creator", creatorPersonnel.getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
processedProducts.add(productMap);
}
result.put("success", true);
result.put("products", products);
result.put("products", processedProducts);
result.put("total", total);
result.put("page", page);
result.put("size", size);
@ -778,4 +846,20 @@ public class UserServiceImpl implements UserService {
public List<CustomerApply> getApplyList(Integer status) {
return customerApplyService.getApplyList(status);
}
@Override
public Map<String, Object> getPersonnelList() {
Map<String, Object> result = new HashMap<>();
try {
// 从primary数据源的personnel表获取所有人员
List<Personnel> personnelList = personnelMapper.findAll();
result.put("success", true);
result.put("personnel", personnelList);
} catch (Exception e) {
e.printStackTrace();
result.put("success", false);
result.put("message", "获取人员列表失败: " + e.getMessage());
}
return result;
}
}

4
web/src/main/resources/mapper/CustomerApplyMapper.xml

@ -6,8 +6,8 @@
<mapper namespace="com.example.web.mapper.CustomerApplyMapper">
<insert id="insert" parameterType="com.example.web.entity.CustomerApply">
INSERT INTO customer_apply (user_id, sales_id, sales_name, status, apply_time, reason)
VALUES (#{user_id}, #{sales_id}, #{sales_name}, #{status}, #{apply_time}, #{reason})
INSERT INTO customer_apply (user_id, sales_id, sales_name, original_manager_name, status, apply_time, reason)
VALUES (#{user_id}, #{sales_id}, #{sales_name}, #{original_manager_name}, #{status}, #{apply_time}, #{reason})
</insert>
<update id="updateStatus" parameterType="java.util.Map">

4
web/src/main/resources/mapper/PersonnelMapper.xml

@ -12,4 +12,8 @@
<select id="findAll" resultType="com.example.web.entity.Personnel">
SELECT * FROM personnel
</select>
<select id="findByPhoneNumber" parameterType="String" resultType="com.example.web.entity.Personnel">
SELECT * FROM personnel WHERE phoneNumber = #{phoneNumber} LIMIT 1
</select>
</mapper>

8
web/src/main/resources/mapper/UserTraceMapper.xml

@ -10,4 +10,12 @@
WHERE ut.originalData LIKE CONCAT('%', #{productId}, '%')
ORDER BY ut.operationTime DESC
</select>
<select id="findById" resultType="com.example.web.entity.UserTrace">
SELECT ut.*, u.nickName, u.followup, um.userName as managerName
FROM usertraces ut
LEFT JOIN users u ON ut.userId = u.userId
LEFT JOIN usermanagements um ON ut.userId = um.userId
WHERE ut.id = #{id}
</select>
</mapper>

4
web/src/main/resources/mapper/UsersMapper.xml

@ -281,4 +281,8 @@
<select id="findAllUsers" resultType="com.example.web.entity.Users">
SELECT * FROM users WHERE type != 'Colleague'
</select>
<select id="findByPhoneNumber" parameterType="String" resultType="com.example.web.entity.Users">
SELECT * FROM users WHERE phoneNumber = #{phoneNumber} LIMIT 1
</select>
</mapper>

719
web/src/main/resources/static/index.html

@ -421,13 +421,43 @@
}
@keyframes slideIn {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(0.9);
}
70% {
opacity: 1;
transform: translate(-50%, -50%) scale(1.02);
}
100% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
@keyframes slideOut {
from {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
to {
opacity: 0;
transform: translate(-50%, -50%) scale(0.95);
}
to {
}
@keyframes scaleIn {
0% {
opacity: 0;
transform: scale(0.9);
}
70% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
transform: scale(1.02);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@ -573,7 +603,11 @@
<div class="user-info">
<span id="userRole"></span>
<span id="userName"></span>
<button id="applyButton" onclick="openApplyModal()" style="display: none; margin-right: 10px; padding: 5px 10px; background-color: #722ed1; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">申请管理</button>
<div style="position: relative; display: inline-block; margin-right: 10px;">
<button id="applyButton" onclick="openApplyModal()" style="display: none; padding: 5px 10px; background-color: #722ed1; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">申请管理</button>
<span id="applyBadge" style="position: absolute; top: -5px; right: -5px; background-color: #ff4d4f; color: white; border-radius: 50%; width: 18px; height: 18px; font-size: 12px; display: flex; align-items: center; justify-content: center; font-weight: bold; opacity: 0; transition: opacity 0.3s ease;">0</span>
</div>
<button id="employeeApplyButton" onclick="openEmployeeApplyModal()" style="display: none; margin-right: 10px; padding: 5px 10px; background-color: #722ed1; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">申请记录</button>
<button id="permissionButton" onclick="openPermissionModal()" style="display: none; margin-right: 10px; padding: 5px 10px; background-color: #1890ff; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">权限管理</button>
<button class="logout-btn" onclick="logout()">退出登录</button>
</div>
@ -653,6 +687,8 @@
<option value="e-commerce">电商平台类</option>
<option value="delivery_retail">配送零售类</option>
<option value="defective_egg">次品蛋专项类</option>
<option value="seller">供应商</option>
<option value="buyer">大贸易客户</option>
<option value="other">其他类型</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">创建时间:</span>
@ -694,7 +730,60 @@
<div id="products" class="tab-content">
<div class="filter-container">
<div class="filter-bar">
<button onclick="loadProducts()" style="background-color: #1890ff; color: white; border: none; border-radius: 4px; padding: 8px 16px; cursor: pointer; font-size: 14px;">刷新货源</button>
<span style="font-size: 14px;">种类:</span>
<select id="categoryFilter" onchange="filterProducts()" style="padding: 6px 8px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 14px;">
<option value="">全部</option>
<option value="粉壳">粉壳</option>
<option value="褐壳">褐壳</option>
<option value="绿壳">绿壳</option>
<option value="白壳">白壳</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">商品名称:</span>
<select id="productNameFilter" onchange="filterProducts()" style="padding: 6px 8px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 14px;">
<option value="">全部</option>
<option value="罗曼粉">罗曼粉</option>
<option value="伊莎粉">伊莎粉</option>
<option value="罗曼灰">罗曼灰</option>
<option value="海蓝灰">海蓝灰</option>
<option value="海蓝褐">海蓝褐</option>
<option value="绿壳">绿壳</option>
<option value="粉一">粉一</option>
<option value="粉三">粉三</option>
<option value="粉六">粉六</option>
<option value="粉八">粉八</option>
<option value="京粉1号">京粉1号</option>
<option value="京红">京红</option>
<option value="京粉6号">京粉6号</option>
<option value="京粉3号">京粉3号</option>
<option value="农二">农二</option>
<option value="农三">农三</option>
<option value="农五">农五</option>
<option value="农六">农六</option>
<option value="黑鸡土蛋">黑鸡土蛋</option>
<option value="大午金凤">大午金凤</option>
<option value="黑凤">黑凤</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">蛋黄:</span>
<select id="yolkFilter" onchange="filterProducts()" style="padding: 6px 8px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 14px;">
<option value="">全部</option>
<option value="红心">红心</option>
<option value="黄心">黄心</option>
<option value="双色">双色</option>
<option value="未知">未知</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">销售负责人:</span>
<select id="salesManagerFilter" onchange="filterProducts()" style="padding: 6px 8px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 14px;">
<option value="">全部</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">创建人:</span>
<select id="creatorFilter" onchange="filterProducts()" style="padding: 6px 8px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 14px;">
<option value="">全部</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">搜索:</span>
<input type="text" id="productSearch" placeholder="搜索商品名称或地区" style="padding: 6px 8px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 14px; width: 200px;">
<button onclick="searchProducts()" style="margin-left: 8px; padding: 6px 12px; background-color: #1890ff; color: white; border: none; border-radius: 4px; font-size: 14px;">搜索</button>
<button onclick="resetProductFilters()" style="margin-left: 10px; padding: 6px 12px; background-color: #666; color: white; border: none; border-radius: 4px; font-size: 14px;">重置筛选</button>
<button onclick="loadProducts()" style="margin-left: 10px; background-color: #1890ff; color: white; border: none; border-radius: 4px; padding: 6px 16px; cursor: pointer; font-size: 14px;">刷新货源</button>
</div>
</div>
@ -707,6 +796,8 @@
<th>库存</th>
<th>地区</th>
<th>创建时间</th>
<th>销售负责人</th>
<th>创建人</th>
<th>操作</th>
</tr>
</thead>
@ -745,6 +836,8 @@
<option value="e-commerce">电商平台类</option>
<option value="delivery_retail">配送零售类</option>
<option value="defective_egg">次品蛋专项类</option>
<option value="seller">供应商</option>
<option value="buyer">大贸易客户</option>
<option value="other">其他类型</option>
</select>
<span style="margin-left: 20px; font-size: 14px;">创建时间:</span>
@ -794,6 +887,16 @@
var publicPageSize = 10;
var productsPageSize = 10;
var personalFilter = 'all'; // all, followed, unfollowed
var productFilters = {
category: '',
productName: '',
yolk: '',
salesManager: '',
creator: '',
search: ''
};
var salesManagers = [];
var creators = [];
var managersList = [];
var allPersonalData = [];
@ -833,7 +936,89 @@
userInfo = JSON.parse(savedUserInfo);
displayUserInfo();
loadManagers();
loadPersonnelData();
loadPersonalData();
// 检查申请状态
var userRole = userInfo.loginInfo.projectName;
if (userRole === '管理员') {
checkApplyStatus();
}
}
function loadPersonnelData() {
// 加载销售负责人和创建人数据
var url = '/KH/api/personnel';
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
if (data.success) {
var personnelList = data.personnel || [];
console.log('获取到的人员列表:', personnelList);
// 筛选销售负责人(projectName为销售员)
salesManagers = personnelList.filter(item => item && item.projectName && (item.projectName === '销售员' || item.projectName.includes('销售'))).map(item => item.name);
// 筛选创建人(projectName为采购员)
creators = personnelList.filter(item => item && item.projectName && (item.projectName === '采购员' || item.projectName.includes('采购'))).map(item => item.name);
// 去重
salesManagers = [...new Set(salesManagers)].filter(name => name);
creators = [...new Set(creators)].filter(name => name);
console.log('筛选后的销售负责人:', salesManagers);
console.log('筛选后的创建人:', creators);
// 填充销售负责人下拉框
populateSalesManagers();
// 填充创建人下拉框
populateCreators();
} else {
console.error('获取人员列表失败:', data.message);
}
} else if (xhr.readyState == 4) {
console.error('获取人员列表失败:', xhr.status, xhr.statusText);
}
};
xhr.send();
}
function populateSalesManagers() {
var select = document.getElementById('salesManagerFilter');
if (select) {
// 清空现有选项(保留第一个全部选项)
while (select.options.length > 1) {
select.remove(1);
}
// 添加销售负责人选项
salesManagers.forEach(name => {
var option = document.createElement('option');
option.value = name;
option.textContent = name;
select.appendChild(option);
});
}
}
function populateCreators() {
var select = document.getElementById('creatorFilter');
if (select) {
// 清空现有选项(保留第一个全部选项)
while (select.options.length > 1) {
select.remove(1);
}
// 添加创建人选项
creators.forEach(name => {
var option = document.createElement('option');
option.value = name;
option.textContent = name;
select.appendChild(option);
});
}
}
function displayUserInfo() {
@ -856,6 +1041,7 @@
var publicAssignButton = document.getElementById('publicAssignButton');
var permissionButton = document.getElementById('permissionButton');
var applyButton = document.getElementById('applyButton');
var employeeApplyButton = document.getElementById('employeeApplyButton');
if (assignButton) {
assignButton.style.display = isAdmin ? 'inline-block' : 'none';
}
@ -868,6 +1054,9 @@
if (applyButton) {
applyButton.style.display = isAdmin ? 'inline-block' : 'none';
}
if (employeeApplyButton) {
employeeApplyButton.style.display = isAdmin ? 'none' : 'inline-block';
}
}
function switchTab(tabName, button) {
@ -1049,7 +1238,18 @@
if (currentTypeFilter) {
var userType = user.type || '';
console.log('筛选类型:', currentTypeFilter, '用户类型:', userType);
// 如果筛选值是英文,需要转换为中文进行比较
// 特殊处理seller和buyer类型,直接比较英文
if (currentTypeFilter === 'seller') {
if (userType !== 'seller' && userType !== '供应商') {
return false;
}
} else if (currentTypeFilter === 'buyer') {
if (userType !== 'buyer' && userType !== '大贸易客户') {
return false;
}
} else {
// 其他类型的映射
var typeMap = {
'wholesale': '批发贸易类',
'e-commerce': '电商平台类',
@ -1062,6 +1262,7 @@
return false;
}
}
}
// 其他情况,不过滤
return true;
@ -1781,8 +1982,8 @@
// 构建查询参数,获取所有数据
var params = {
page: 1,
size: 1000, // 假设最多1000条数据
page: publicPage,
size: publicPageSize,
userRole: userRole,
userName: usersManagements.userName || '',
managercompany: usersManagements.managercompany || '',
@ -1803,7 +2004,11 @@
allPublicData = data.users;
}
displayPublicData(data);
renderPublicPagination(data.page, data.pages, data.total);
// 确保传递正确的参数给分页函数
var page = data.page || 1;
var pages = data.pages || 1;
var total = data.total || 0;
renderPublicPagination(page, pages, total);
}
};
xhr.send();
@ -1953,6 +2158,8 @@
'<td>' + (product.quantity || '-') + '</td>' +
'<td>' + (product.fullRegion || product.region || '-') + '</td>' +
'<td>' + formatDateTime(product.created_at) + '</td>' +
'<td>' + (product.salesManager || '-') + '</td>' +
'<td>' + (product.creator || '-') + '</td>' +
'<td><button onclick="openProductDetailModal(\'' + (product.productId || '') + '\')" style="padding: 4px 8px; background-color: #1890ff; color: white; border: none; border-radius: 4px; font-size: 12px;">查看详情</button></td>' +
'</tr>';
productsBody.innerHTML += row;
@ -1985,6 +2192,105 @@
xhr.send();
}
// 筛选货源
function filterProducts() {
// 获取筛选值
productFilters.category = document.getElementById('categoryFilter').value;
productFilters.productName = document.getElementById('productNameFilter').value;
productFilters.yolk = document.getElementById('yolkFilter').value;
productFilters.salesManager = document.getElementById('salesManagerFilter').value;
productFilters.creator = document.getElementById('creatorFilter').value;
// 应用筛选
applyProductFilters();
}
// 搜索货源
function searchProducts() {
productFilters.search = document.getElementById('productSearch').value;
applyProductFilters();
}
// 重置货源筛选
function resetProductFilters() {
// 重置筛选值
document.getElementById('categoryFilter').value = '';
document.getElementById('productNameFilter').value = '';
document.getElementById('yolkFilter').value = '';
document.getElementById('salesManagerFilter').value = '';
document.getElementById('creatorFilter').value = '';
document.getElementById('productSearch').value = '';
// 重置筛选对象
productFilters = {
category: '',
productName: '',
yolk: '',
salesManager: '',
creator: '',
search: ''
};
// 重新加载数据
loadProducts();
}
// 应用货源筛选
function applyProductFilters() {
if (allProducts.length === 0) {
// 如果还没有数据,先加载
loadProducts();
return;
}
// 应用筛选
var filteredProducts = allProducts.filter(product => {
// 种类筛选
if (productFilters.category && product.category !== productFilters.category) {
return false;
}
// 商品名称筛选
if (productFilters.productName && product.productName !== productFilters.productName) {
return false;
}
// 蛋黄筛选
if (productFilters.yolk && product.yolk !== productFilters.yolk) {
return false;
}
// 销售负责人筛选
if (productFilters.salesManager && product.salesManager !== productFilters.salesManager) {
return false;
}
// 创建人筛选
if (productFilters.creator && product.creator !== productFilters.creator) {
return false;
}
// 搜索筛选
if (productFilters.search) {
var searchLower = productFilters.search.toLowerCase();
var productNameLower = (product.productName || '').toLowerCase();
var regionLower = (product.fullRegion || product.region || '').toLowerCase();
if (!productNameLower.includes(searchLower) && !regionLower.includes(searchLower)) {
return false;
}
}
return true;
});
// 显示筛选结果
displayProducts(filteredProducts);
// 重新渲染分页(筛选后的数据可能更少)
var totalPages = Math.ceil(filteredProducts.length / productsPageSize);
renderProductsPagination(1, totalPages, filteredProducts.length);
}
// 显示商品详情
function showProductDetail(product, traces) {
// 对traces数据进行分组,按用户ID分组
@ -2025,10 +2331,12 @@
justify-content: center;
align-items: center;
z-index: 1000;
animation: fadeIn 0.4s ease;
`;
var modalContent = document.createElement('div');
modalContent.style.cssText = `
position: relative;
background: white;
border-radius: 8px;
width: 90%;
@ -2036,7 +2344,9 @@
max-height: 80%;
display: flex;
flex-direction: column;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
box-shadow: 0 8px 32px rgba(0,0,0,0.2);
animation: scaleIn 0.4s ease;
transform-origin: center;
`;
// 固定导航栏
@ -2101,8 +2411,8 @@
</tr>
</thead>
<tbody>
${mergedTraces.map(trace => `
<tr>
${mergedTraces.map((trace, index) => `
<tr data-trace-id="${traces[index].id || ''}" data-user-id="${trace.userId || ''}">
<td style="padding: 8px; border: 1px solid #e8e8e8; white-space: nowrap; vertical-align: top;">${trace.nickName || '-'}</td>
<td style="padding: 8px; border: 1px solid #e8e8e8; white-space: nowrap; vertical-align: top;">${trace.phoneNumber || '-'}</td>
<td style="padding: 8px; border: 1px solid #e8e8e8; vertical-align: top;">
@ -2112,7 +2422,7 @@
<td style="padding: 8px; border: 1px solid #e8e8e8; white-space: nowrap; vertical-align: top;">${trace.responseTime || '-'}</td>
<td style="padding: 8px; border: 1px solid #e8e8e8; white-space: nowrap; vertical-align: top;">${trace.managerName || '-'}</td>
<td style="padding: 8px; border: 1px solid #e8e8e8; white-space: nowrap; vertical-align: top;">
${!isAdmin ? `<button onclick="applyCustomer('${trace.userId || ''}', '${trace.nickName || ''}', this); event.stopPropagation();" style="padding: 4px 8px; background-color: #722ed1; color: white; border: none; border-radius: 4px; font-size: 12px;">申请</button>` : '-'}
${!isAdmin ? `<button onclick="applyCustomer('${trace.userId || ''}', '${trace.nickName || ''}', this, '${traces[index].id || ''}'); event.stopPropagation();" style="padding: 4px 8px; background-color: #722ed1; color: white; border: none; border-radius: 4px; font-size: 12px;">申请</button>` : '-'}
</td>
</tr>
`).join('')}
@ -2137,10 +2447,6 @@
function loadApplyStatusForTraces(traces) {
if (!traces || traces.length === 0) return;
// 获取所有客户ID
var userIds = traces.map(trace => trace.userId).filter(Boolean);
if (userIds.length === 0) return;
var url = '/KH/api/users/apply/list';
var xhr = new XMLHttpRequest();
@ -2149,11 +2455,12 @@
if (xhr.readyState == 4 && xhr.status == 200) {
var applyList = JSON.parse(xhr.responseText);
if (applyList && applyList.length > 0) {
// 创建申请状态映射
// 创建申请状态映射,使用user_id和sales_id的组合作为键
var applyStatusMap = {};
applyList.forEach(apply => {
if (apply.user_id) {
applyStatusMap[apply.user_id] = apply.status;
if (apply.user_id && apply.sales_id) {
var key = apply.user_id + '_' + apply.sales_id;
applyStatusMap[key] = apply.status;
}
});
@ -2167,24 +2474,26 @@
var tbody = table.querySelector('tbody');
if (tbody) {
var rows = tbody.querySelectorAll('tr');
rows.forEach((row, index) => {
// 获取对应的trace
var trace = traces[index];
if (trace && trace.userId) {
var status = applyStatusMap[trace.userId];
rows.forEach((row) => {
// 从row的data属性获取userId
var userId = row.dataset.userId;
if (userId) {
// 遍历所有申请记录,查找匹配的记录
applyList.forEach(apply => {
if (apply.user_id === userId) {
var button = row.querySelector('button[onclick^="applyCustomer"]');
if (button && status !== undefined) {
if (status === 0) {
if (button) {
if (apply.status === 0) {
// 申请中
button.textContent = '申请中';
button.disabled = true;
button.style.backgroundColor = '#faad14';
} else if (status === 1) {
} else if (apply.status === 1) {
// 申请通过
button.textContent = '申请通过';
button.disabled = true;
button.style.backgroundColor = '#52c41a';
} else if (status === 2) {
} else if (apply.status === 2) {
// 申请失败
button.textContent = '申请失败';
button.disabled = false;
@ -2194,6 +2503,8 @@
}
});
}
});
}
}
});
}
@ -2202,6 +2513,135 @@
xhr.send();
}
// 加载普通员工的申请记录
function loadEmployeeApplyRecords() {
if (!userInfo || (!userInfo.personnel && !userInfo.usersManagements)) return;
var salesName = userInfo.personnel ? userInfo.personnel.name : (userInfo.usersManagements ? userInfo.usersManagements.userName : '');
if (!salesName) return;
var url = '/KH/api/users/apply/list';
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var applyList = JSON.parse(xhr.responseText);
if (applyList && applyList.length > 0) {
// 过滤出当前员工的申请记录
var employeeApplies = applyList.filter(apply => apply.sales_name === salesName);
if (employeeApplies.length > 0) {
// 显示申请记录
showEmployeeApplyRecords(employeeApplies);
}
}
}
};
xhr.send();
}
// 显示普通员工的申请记录
function showEmployeeApplyRecords(applies) {
var container = document.getElementById('employeeApplyRecords');
if (!container) {
// 创建申请记录容器
container = document.createElement('div');
container.id = 'employeeApplyRecords';
container.style.cssText = `
margin: 20px 0;
padding: 15px;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
`;
// 添加到页面
var containerElement = document.querySelector('.container');
if (containerElement) {
var userDetailsContainer = containerElement.querySelector('.user-details-container');
if (userDetailsContainer) {
containerElement.insertBefore(container, userDetailsContainer.nextSibling);
} else {
containerElement.insertBefore(container, containerElement.firstChild);
}
}
}
// 清空容器
container.innerHTML = '';
// 添加标题
var title = document.createElement('h3');
title.textContent = '我的申请记录';
title.style.cssText = `
margin-top: 0;
margin-bottom: 15px;
color: #333;
font-size: 18px;
`;
container.appendChild(title);
// 创建表格
var table = document.createElement('table');
table.style.cssText = `
width: 100%;
border-collapse: collapse;
background-color: white;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
`;
// 添加表头
var thead = document.createElement('thead');
thead.innerHTML = `
<tr style="background-color: #f5f5f5;">
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">客户ID</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">申请时间</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">状态</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">审批时间</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">审批人</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">备注</th>
</tr>
`;
table.appendChild(thead);
// 添加表体
var tbody = document.createElement('tbody');
applies.forEach(apply => {
var statusText = '';
var statusColor = '';
switch (apply.status) {
case 0:
statusText = '申请中';
statusColor = '#faad14';
break;
case 1:
statusText = '申请通过';
statusColor = '#52c41a';
break;
case 2:
statusText = '申请失败';
statusColor = '#ff4d4f';
break;
}
var row = document.createElement('tr');
row.innerHTML = `
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.user_id || '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.apply_time ? new Date(apply.apply_time).toLocaleString() : '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">
<span style="color: ${statusColor}; font-weight: bold;">${statusText}</span>
</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.approve_time ? new Date(apply.approve_time).toLocaleString() : '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.approve_by || '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.reason || '-'}</td>
`;
tbody.appendChild(row);
});
table.appendChild(tbody);
container.appendChild(table);
}
// 显示提示信息
function showAlert(message) {
var alert = document.createElement('div');
@ -2466,16 +2906,6 @@
// 淡入淡出动画
var style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes fadeOut {
from {
opacity: 1;
@ -3013,7 +3443,7 @@
// 申请管理模态框HTML
var applyModalHTML = `
<div id="applyModal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.7) 100%); backdrop-filter: blur(5px); display: none; z-index: 1000; animation: fadeIn 0.3s ease;">
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border-radius: 8px; width: 90%; max-width: 1000px; max-height: 80vh; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.15); animation: slideIn 0.3s ease;">
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border-radius: 8px; width: 95%; max-width: 1400px; max-height: 80vh; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.15); animation: slideIn 0.3s ease;">
<div style="padding: 16px 20px; border-bottom: 1px solid #e8e8e8; display: flex; justify-content: space-between; align-items: center; background-color: white; border-radius: 8px 8px 0 0;">
<h3 style="margin: 0; color: #722ed1;">申请管理</h3>
<button onclick="closeApplyModal()" style="padding: 6px 12px; background-color: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;">
@ -3037,6 +3467,7 @@
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">申请ID</th>
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">客户ID</th>
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">业务员</th>
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">原负责人</th>
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">申请时间</th>
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">状态</th>
<th style="padding: 12px; border: 1px solid #e8e8e8; text-align: left;">申请理由</th>
@ -3045,7 +3476,7 @@
</thead>
<tbody id="applyTableBody">
<tr>
<td colspan="7" style="padding: 20px; text-align: center; color: #999;">暂无申请记录</td>
<td colspan="8" style="padding: 20px; text-align: center; color: #999;">暂无申请记录</td>
</tr>
</tbody>
</table>
@ -3143,6 +3574,56 @@
document.body.insertAdjacentHTML('beforeend', assignModalHTML);
document.body.insertAdjacentHTML('beforeend', permissionModalHTML);
document.body.insertAdjacentHTML('beforeend', applyModalHTML);
// 员工申请记录模态框HTML
var employeeApplyModalHTML = `
<div id="employeeApplyModal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.7) 100%); backdrop-filter: blur(5px); display: none; z-index: 1000; animation: fadeIn 0.3s ease;">
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); width: 90%; max-width: 900px; max-height: 80vh; overflow: hidden; display: flex; flex-direction: column; animation: slideIn 0.3s ease;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #e8e8e8;">
<h3 style="margin: 0; color: #722ed1;">我的申请记录</h3>
<button onclick="closeEmployeeApplyModal()" style="background: none; border: none; font-size: 20px; cursor: pointer; color: #999;">&times;</button>
</div>
<div style="flex: 1; overflow-y: auto; margin-bottom: 15px;">
<div style="margin-bottom: 15px; display: flex; gap: 10px; flex-wrap: wrap;">
<button onclick="filterEmployeeApplyList('all')" style="padding: 6px 12px; background-color: #1890ff; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">全部</button>
<button onclick="filterEmployeeApplyList('0')" style="padding: 6px 12px; background-color: #faad14; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">申请中</button>
<button onclick="filterEmployeeApplyList('1')" style="padding: 6px 12px; background-color: #52c41a; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">已通过</button>
<button onclick="filterEmployeeApplyList('2')" style="padding: 6px 12px; background-color: #ff4d4f; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">已拒绝</button>
</div>
<div style="overflow-x: auto;">
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background-color: #f5f5f5;">
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">申请ID</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">客户ID</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">申请时间</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">状态</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">审批时间</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">审批人</th>
<th style="padding: 10px; border: 1px solid #e8e8e8; text-align: left;">备注</th>
</tr>
</thead>
<tbody id="employeeApplyTableBody">
<!-- 申请记录将通过JavaScript动态添加 -->
</tbody>
</table>
</div>
<div id="employeeApplyEmpty" style="text-align: center; padding: 40px 20px; color: #999; display: none;">
暂无申请记录
</div>
</div>
<div style="display: flex; justify-content: flex-end; padding-top: 15px; border-top: 1px solid #e8e8e8;">
<button onclick="closeEmployeeApplyModal()" style="padding: 8px 16px; background-color: #1890ff; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">关闭</button>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', employeeApplyModalHTML);
document.body.insertAdjacentHTML('beforeend', alertModalHTML);
document.body.insertAdjacentHTML('beforeend', typeHelpModalHTML);
@ -3564,7 +4045,18 @@
if (currentTypeFilter) {
var userType = user.type || '';
console.log('公海池筛选类型:', currentTypeFilter, '用户类型:', userType);
// 如果筛选值是英文,需要转换为中文进行比较
// 特殊处理seller和buyer类型,直接比较英文
if (currentTypeFilter === 'seller') {
if (userType !== 'seller' && userType !== '供应商') {
return false;
}
} else if (currentTypeFilter === 'buyer') {
if (userType !== 'buyer' && userType !== '大贸易客户') {
return false;
}
} else {
// 其他类型的映射
var typeMap = {
'wholesale': '批发贸易类',
'e-commerce': '电商平台类',
@ -3577,6 +4069,7 @@
return false;
}
}
}
// 其他情况,不过滤
return true;
@ -5058,11 +5551,13 @@
pagination.appendChild(jumpContainer);
}
function applyCustomer(userId, userName, button) {
function applyCustomer(userId, userName, button, traceId) {
// 显示确认弹窗
if (confirm('确认申请该客户吗?')) {
// 获取当前按钮元素
var buttons = [];
if (button) {
buttons.push(button);
// 保存原始状态
button.dataset.originalText = button.textContent;
button.dataset.originalDisabled = button.disabled;
@ -5072,8 +5567,9 @@
button.style.backgroundColor = '#faad14';
} else {
// 尝试通过选择器查找按钮(兼容旧格式)
var buttons = document.querySelectorAll('button[onclick*="applyCustomer(\'" + userId + "\'")]');
buttons.forEach(function(btn) {
var btnElements = document.querySelectorAll('button[onclick*="applyCustomer(\'" + userId + "\'")]');
btnElements.forEach(function(btn) {
buttons.push(btn);
// 保存原始状态
btn.dataset.originalText = btn.textContent;
btn.dataset.originalDisabled = btn.disabled;
@ -5088,8 +5584,7 @@
var usersManagements = userInfo.usersManagements;
var params = {
userId: userId,
salesId: personnel.managerId || usersManagements.userId || '',
traceId: traceId,
salesName: personnel.name || usersManagements.userName || '',
reason: '申请成为该客户的负责人'
};
@ -5128,11 +5623,38 @@
}
}
// 检查申请状态并更新角标
function checkApplyStatus() {
var url = '/KH/api/users/apply/list?status=0'; // 只获取申请中的数据
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var applies = JSON.parse(xhr.responseText);
var applyCount = applies.length || 0;
var badge = document.getElementById('applyBadge');
if (badge) {
if (applyCount > 0) {
badge.textContent = applyCount;
badge.style.opacity = '1';
} else {
badge.style.opacity = '0';
}
}
}
};
xhr.send();
}
// 申请管理相关函数
function openApplyModal() {
document.getElementById('applyModal').style.display = 'block';
// 加载申请列表
loadApplyList();
// 打开后更新角标(可选,因为打开后用户会处理申请)
checkApplyStatus();
}
function closeApplyModal() {
@ -5208,6 +5730,7 @@
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.id}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.user_id}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.sales_name}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.original_manager_name || '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${formatDateTime(apply.apply_time)}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">
<span style="display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; color: white; background-color: ${statusColor};">${statusText}</span>
@ -5220,7 +5743,7 @@
tbody.innerHTML += row;
}
} else {
tbody.innerHTML = '<tr><td colspan="7" style="padding: 20px; text-align: center; color: #999;">暂无申请记录</td></tr>';
tbody.innerHTML = '<tr><td colspan="8" style="padding: 20px; text-align: center; color: #999;">暂无申请记录</td></tr>';
}
}
@ -5255,6 +5778,8 @@
if (data.success) {
showAlert(`${action}成功`);
loadApplyList();
// 更新申请状态角标
checkApplyStatus();
} else {
showAlert(`${action}失败: ` + data.message);
}
@ -5265,6 +5790,106 @@
}
window.onload = init;
// 员工申请记录相关函数
function openEmployeeApplyModal() {
document.getElementById('employeeApplyModal').style.display = 'block';
// 加载员工申请列表
loadEmployeeApplyList();
}
function closeEmployeeApplyModal() {
document.getElementById('employeeApplyModal').style.display = 'none';
}
function loadEmployeeApplyList() {
var url = '/KH/api/users/apply/list';
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
// 过滤出当前员工的申请记录
var salesName = userInfo.personnel ? userInfo.personnel.name : (userInfo.usersManagements ? userInfo.usersManagements.userName : '');
var employeeApplies = data.filter(apply => apply.sales_name === salesName);
displayEmployeeApplyList(employeeApplies);
}
};
xhr.send();
}
function filterEmployeeApplyList(status) {
var url = '/KH/api/users/apply/list';
if (status !== 'all') {
url += '?status=' + status;
}
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
// 过滤出当前员工的申请记录
var salesName = userInfo.personnel ? userInfo.personnel.name : (userInfo.usersManagements ? userInfo.usersManagements.userName : '');
var employeeApplies = data.filter(apply => apply.sales_name === salesName);
displayEmployeeApplyList(employeeApplies);
}
};
xhr.send();
}
function displayEmployeeApplyList(applies) {
var tbody = document.getElementById('employeeApplyTableBody');
tbody.innerHTML = '';
if (applies && applies.length > 0) {
for (var i = 0; i < applies.length; i++) {
var apply = applies[i];
var statusText = '';
var statusColor = '';
switch (apply.status) {
case 0:
statusText = '申请中';
statusColor = '#faad14';
break;
case 1:
statusText = '申请通过';
statusColor = '#52c41a';
break;
case 2:
statusText = '申请失败';
statusColor = '#ff4d4f';
break;
}
var row = `
<tr>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.id}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.user_id}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${formatDateTime(apply.apply_time)}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">
<span style="display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; color: white; background-color: ${statusColor};">${statusText}</span>
</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.approve_time ? formatDateTime(apply.approve_time) : '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.approve_by || '-'}</td>
<td style="padding: 10px; border: 1px solid #e8e8e8; white-space: normal; word-wrap: break-word; max-width: 300px;">${apply.reason}</td>
</tr>
`;
tbody.innerHTML += row;
}
document.getElementById('employeeApplyEmpty').style.display = 'none';
} else {
document.getElementById('employeeApplyEmpty').style.display = 'block';
}
}
// 页面加载完成后初始化
window.onload = function() {
init();
};
</script>
</body>
</html>

2
web/src/main/resources/static/login.html

@ -273,7 +273,7 @@
console.log('收到来自其他页面的消息:', event);
// 验证消息来源(可选,增强安全性)
if (event.origin === 'http://localhost:3005' || event.origin === 'http://localhost:8083') {
if (event.origin === 'http://8.137.125.67:3005' || event.origin === 'http://8.137.125.67:8083') {
try {
const messageData = event.data;
if (messageData.type === 'LOGIN_INFO') {

Loading…
Cancel
Save