|
|
@ -421,13 +421,43 @@ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@keyframes slideIn { |
|
|
@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 { |
|
|
from { |
|
|
|
|
|
opacity: 1; |
|
|
|
|
|
transform: translate(-50%, -50%) scale(1); |
|
|
|
|
|
} |
|
|
|
|
|
to { |
|
|
opacity: 0; |
|
|
opacity: 0; |
|
|
transform: translate(-50%, -50%) scale(0.95); |
|
|
transform: translate(-50%, -50%) scale(0.95); |
|
|
} |
|
|
} |
|
|
to { |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@keyframes scaleIn { |
|
|
|
|
|
0% { |
|
|
|
|
|
opacity: 0; |
|
|
|
|
|
transform: scale(0.9); |
|
|
|
|
|
} |
|
|
|
|
|
70% { |
|
|
opacity: 1; |
|
|
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"> |
|
|
<div class="user-info"> |
|
|
<span id="userRole"></span> |
|
|
<span id="userRole"></span> |
|
|
<span id="userName"></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 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> |
|
|
<button class="logout-btn" onclick="logout()">退出登录</button> |
|
|
</div> |
|
|
</div> |
|
|
@ -653,6 +687,8 @@ |
|
|
<option value="e-commerce">电商平台类</option> |
|
|
<option value="e-commerce">电商平台类</option> |
|
|
<option value="delivery_retail">配送零售类</option> |
|
|
<option value="delivery_retail">配送零售类</option> |
|
|
<option value="defective_egg">次品蛋专项类</option> |
|
|
<option value="defective_egg">次品蛋专项类</option> |
|
|
|
|
|
<option value="seller">供应商</option> |
|
|
|
|
|
<option value="buyer">大贸易客户</option> |
|
|
<option value="other">其他类型</option> |
|
|
<option value="other">其他类型</option> |
|
|
</select> |
|
|
</select> |
|
|
<span style="margin-left: 20px; font-size: 14px;">创建时间:</span> |
|
|
<span style="margin-left: 20px; font-size: 14px;">创建时间:</span> |
|
|
@ -694,7 +730,60 @@ |
|
|
<div id="products" class="tab-content"> |
|
|
<div id="products" class="tab-content"> |
|
|
<div class="filter-container"> |
|
|
<div class="filter-container"> |
|
|
<div class="filter-bar"> |
|
|
<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> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
@ -707,6 +796,8 @@ |
|
|
<th>库存</th> |
|
|
<th>库存</th> |
|
|
<th>地区</th> |
|
|
<th>地区</th> |
|
|
<th>创建时间</th> |
|
|
<th>创建时间</th> |
|
|
|
|
|
<th>销售负责人</th> |
|
|
|
|
|
<th>创建人</th> |
|
|
<th>操作</th> |
|
|
<th>操作</th> |
|
|
</tr> |
|
|
</tr> |
|
|
</thead> |
|
|
</thead> |
|
|
@ -745,6 +836,8 @@ |
|
|
<option value="e-commerce">电商平台类</option> |
|
|
<option value="e-commerce">电商平台类</option> |
|
|
<option value="delivery_retail">配送零售类</option> |
|
|
<option value="delivery_retail">配送零售类</option> |
|
|
<option value="defective_egg">次品蛋专项类</option> |
|
|
<option value="defective_egg">次品蛋专项类</option> |
|
|
|
|
|
<option value="seller">供应商</option> |
|
|
|
|
|
<option value="buyer">大贸易客户</option> |
|
|
<option value="other">其他类型</option> |
|
|
<option value="other">其他类型</option> |
|
|
</select> |
|
|
</select> |
|
|
<span style="margin-left: 20px; font-size: 14px;">创建时间:</span> |
|
|
<span style="margin-left: 20px; font-size: 14px;">创建时间:</span> |
|
|
@ -794,6 +887,16 @@ |
|
|
var publicPageSize = 10; |
|
|
var publicPageSize = 10; |
|
|
var productsPageSize = 10; |
|
|
var productsPageSize = 10; |
|
|
var personalFilter = 'all'; // all, followed, unfollowed |
|
|
var personalFilter = 'all'; // all, followed, unfollowed |
|
|
|
|
|
var productFilters = { |
|
|
|
|
|
category: '', |
|
|
|
|
|
productName: '', |
|
|
|
|
|
yolk: '', |
|
|
|
|
|
salesManager: '', |
|
|
|
|
|
creator: '', |
|
|
|
|
|
search: '' |
|
|
|
|
|
}; |
|
|
|
|
|
var salesManagers = []; |
|
|
|
|
|
var creators = []; |
|
|
|
|
|
|
|
|
var managersList = []; |
|
|
var managersList = []; |
|
|
var allPersonalData = []; |
|
|
var allPersonalData = []; |
|
|
@ -833,7 +936,89 @@ |
|
|
userInfo = JSON.parse(savedUserInfo); |
|
|
userInfo = JSON.parse(savedUserInfo); |
|
|
displayUserInfo(); |
|
|
displayUserInfo(); |
|
|
loadManagers(); |
|
|
loadManagers(); |
|
|
|
|
|
loadPersonnelData(); |
|
|
loadPersonalData(); |
|
|
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() { |
|
|
function displayUserInfo() { |
|
|
@ -856,6 +1041,7 @@ |
|
|
var publicAssignButton = document.getElementById('publicAssignButton'); |
|
|
var publicAssignButton = document.getElementById('publicAssignButton'); |
|
|
var permissionButton = document.getElementById('permissionButton'); |
|
|
var permissionButton = document.getElementById('permissionButton'); |
|
|
var applyButton = document.getElementById('applyButton'); |
|
|
var applyButton = document.getElementById('applyButton'); |
|
|
|
|
|
var employeeApplyButton = document.getElementById('employeeApplyButton'); |
|
|
if (assignButton) { |
|
|
if (assignButton) { |
|
|
assignButton.style.display = isAdmin ? 'inline-block' : 'none'; |
|
|
assignButton.style.display = isAdmin ? 'inline-block' : 'none'; |
|
|
} |
|
|
} |
|
|
@ -868,6 +1054,9 @@ |
|
|
if (applyButton) { |
|
|
if (applyButton) { |
|
|
applyButton.style.display = isAdmin ? 'inline-block' : 'none'; |
|
|
applyButton.style.display = isAdmin ? 'inline-block' : 'none'; |
|
|
} |
|
|
} |
|
|
|
|
|
if (employeeApplyButton) { |
|
|
|
|
|
employeeApplyButton.style.display = isAdmin ? 'none' : 'inline-block'; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function switchTab(tabName, button) { |
|
|
function switchTab(tabName, button) { |
|
|
@ -1049,7 +1238,18 @@ |
|
|
if (currentTypeFilter) { |
|
|
if (currentTypeFilter) { |
|
|
var userType = user.type || ''; |
|
|
var userType = user.type || ''; |
|
|
console.log('筛选类型:', currentTypeFilter, '用户类型:', userType); |
|
|
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 = { |
|
|
var typeMap = { |
|
|
'wholesale': '批发贸易类', |
|
|
'wholesale': '批发贸易类', |
|
|
'e-commerce': '电商平台类', |
|
|
'e-commerce': '电商平台类', |
|
|
@ -1062,6 +1262,7 @@ |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 其他情况,不过滤 |
|
|
// 其他情况,不过滤 |
|
|
return true; |
|
|
return true; |
|
|
@ -1781,8 +1982,8 @@ |
|
|
|
|
|
|
|
|
// 构建查询参数,获取所有数据 |
|
|
// 构建查询参数,获取所有数据 |
|
|
var params = { |
|
|
var params = { |
|
|
page: 1, |
|
|
page: publicPage, |
|
|
size: 1000, // 假设最多1000条数据 |
|
|
size: publicPageSize, |
|
|
userRole: userRole, |
|
|
userRole: userRole, |
|
|
userName: usersManagements.userName || '', |
|
|
userName: usersManagements.userName || '', |
|
|
managercompany: usersManagements.managercompany || '', |
|
|
managercompany: usersManagements.managercompany || '', |
|
|
@ -1803,7 +2004,11 @@ |
|
|
allPublicData = data.users; |
|
|
allPublicData = data.users; |
|
|
} |
|
|
} |
|
|
displayPublicData(data); |
|
|
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(); |
|
|
xhr.send(); |
|
|
@ -1953,6 +2158,8 @@ |
|
|
'<td>' + (product.quantity || '-') + '</td>' + |
|
|
'<td>' + (product.quantity || '-') + '</td>' + |
|
|
'<td>' + (product.fullRegion || product.region || '-') + '</td>' + |
|
|
'<td>' + (product.fullRegion || product.region || '-') + '</td>' + |
|
|
'<td>' + formatDateTime(product.created_at) + '</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>' + |
|
|
'<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>'; |
|
|
'</tr>'; |
|
|
productsBody.innerHTML += row; |
|
|
productsBody.innerHTML += row; |
|
|
@ -1985,6 +2192,105 @@ |
|
|
xhr.send(); |
|
|
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) { |
|
|
function showProductDetail(product, traces) { |
|
|
// 对traces数据进行分组,按用户ID分组 |
|
|
// 对traces数据进行分组,按用户ID分组 |
|
|
@ -2025,10 +2331,12 @@ |
|
|
justify-content: center; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
align-items: center; |
|
|
z-index: 1000; |
|
|
z-index: 1000; |
|
|
|
|
|
animation: fadeIn 0.4s ease; |
|
|
`; |
|
|
`; |
|
|
|
|
|
|
|
|
var modalContent = document.createElement('div'); |
|
|
var modalContent = document.createElement('div'); |
|
|
modalContent.style.cssText = ` |
|
|
modalContent.style.cssText = ` |
|
|
|
|
|
position: relative; |
|
|
background: white; |
|
|
background: white; |
|
|
border-radius: 8px; |
|
|
border-radius: 8px; |
|
|
width: 90%; |
|
|
width: 90%; |
|
|
@ -2036,7 +2344,9 @@ |
|
|
max-height: 80%; |
|
|
max-height: 80%; |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
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> |
|
|
</tr> |
|
|
</thead> |
|
|
</thead> |
|
|
<tbody> |
|
|
<tbody> |
|
|
${mergedTraces.map(trace => ` |
|
|
${mergedTraces.map((trace, index) => ` |
|
|
<tr> |
|
|
<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.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; white-space: nowrap; vertical-align: top;">${trace.phoneNumber || '-'}</td> |
|
|
<td style="padding: 8px; border: 1px solid #e8e8e8; vertical-align: top;"> |
|
|
<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.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;">${trace.managerName || '-'}</td> |
|
|
<td style="padding: 8px; border: 1px solid #e8e8e8; white-space: nowrap; vertical-align: top;"> |
|
|
<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> |
|
|
</td> |
|
|
</tr> |
|
|
</tr> |
|
|
`).join('')} |
|
|
`).join('')} |
|
|
@ -2137,10 +2447,6 @@ |
|
|
function loadApplyStatusForTraces(traces) { |
|
|
function loadApplyStatusForTraces(traces) { |
|
|
if (!traces || traces.length === 0) return; |
|
|
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 url = '/KH/api/users/apply/list'; |
|
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
var xhr = new XMLHttpRequest(); |
|
|
@ -2149,11 +2455,12 @@ |
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
var applyList = JSON.parse(xhr.responseText); |
|
|
var applyList = JSON.parse(xhr.responseText); |
|
|
if (applyList && applyList.length > 0) { |
|
|
if (applyList && applyList.length > 0) { |
|
|
// 创建申请状态映射 |
|
|
// 创建申请状态映射,使用user_id和sales_id的组合作为键 |
|
|
var applyStatusMap = {}; |
|
|
var applyStatusMap = {}; |
|
|
applyList.forEach(apply => { |
|
|
applyList.forEach(apply => { |
|
|
if (apply.user_id) { |
|
|
if (apply.user_id && apply.sales_id) { |
|
|
applyStatusMap[apply.user_id] = apply.status; |
|
|
var key = apply.user_id + '_' + apply.sales_id; |
|
|
|
|
|
applyStatusMap[key] = apply.status; |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
@ -2167,24 +2474,26 @@ |
|
|
var tbody = table.querySelector('tbody'); |
|
|
var tbody = table.querySelector('tbody'); |
|
|
if (tbody) { |
|
|
if (tbody) { |
|
|
var rows = tbody.querySelectorAll('tr'); |
|
|
var rows = tbody.querySelectorAll('tr'); |
|
|
rows.forEach((row, index) => { |
|
|
rows.forEach((row) => { |
|
|
// 获取对应的trace |
|
|
// 从row的data属性获取userId |
|
|
var trace = traces[index]; |
|
|
var userId = row.dataset.userId; |
|
|
if (trace && trace.userId) { |
|
|
if (userId) { |
|
|
var status = applyStatusMap[trace.userId]; |
|
|
// 遍历所有申请记录,查找匹配的记录 |
|
|
|
|
|
applyList.forEach(apply => { |
|
|
|
|
|
if (apply.user_id === userId) { |
|
|
var button = row.querySelector('button[onclick^="applyCustomer"]'); |
|
|
var button = row.querySelector('button[onclick^="applyCustomer"]'); |
|
|
if (button && status !== undefined) { |
|
|
if (button) { |
|
|
if (status === 0) { |
|
|
if (apply.status === 0) { |
|
|
// 申请中 |
|
|
// 申请中 |
|
|
button.textContent = '申请中'; |
|
|
button.textContent = '申请中'; |
|
|
button.disabled = true; |
|
|
button.disabled = true; |
|
|
button.style.backgroundColor = '#faad14'; |
|
|
button.style.backgroundColor = '#faad14'; |
|
|
} else if (status === 1) { |
|
|
} else if (apply.status === 1) { |
|
|
// 申请通过 |
|
|
// 申请通过 |
|
|
button.textContent = '申请通过'; |
|
|
button.textContent = '申请通过'; |
|
|
button.disabled = true; |
|
|
button.disabled = true; |
|
|
button.style.backgroundColor = '#52c41a'; |
|
|
button.style.backgroundColor = '#52c41a'; |
|
|
} else if (status === 2) { |
|
|
} else if (apply.status === 2) { |
|
|
// 申请失败 |
|
|
// 申请失败 |
|
|
button.textContent = '申请失败'; |
|
|
button.textContent = '申请失败'; |
|
|
button.disabled = false; |
|
|
button.disabled = false; |
|
|
@ -2194,6 +2503,8 @@ |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
@ -2202,6 +2513,135 @@ |
|
|
xhr.send(); |
|
|
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) { |
|
|
function showAlert(message) { |
|
|
var alert = document.createElement('div'); |
|
|
var alert = document.createElement('div'); |
|
|
@ -2466,16 +2906,6 @@ |
|
|
// 淡入淡出动画 |
|
|
// 淡入淡出动画 |
|
|
var style = document.createElement('style'); |
|
|
var style = document.createElement('style'); |
|
|
style.textContent = ` |
|
|
style.textContent = ` |
|
|
@keyframes slideIn { |
|
|
|
|
|
from { |
|
|
|
|
|
transform: translateX(100%); |
|
|
|
|
|
opacity: 0; |
|
|
|
|
|
} |
|
|
|
|
|
to { |
|
|
|
|
|
transform: translateX(0); |
|
|
|
|
|
opacity: 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
@keyframes fadeOut { |
|
|
@keyframes fadeOut { |
|
|
from { |
|
|
from { |
|
|
opacity: 1; |
|
|
opacity: 1; |
|
|
@ -3013,7 +3443,7 @@ |
|
|
// 申请管理模态框HTML |
|
|
// 申请管理模态框HTML |
|
|
var applyModalHTML = ` |
|
|
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 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;"> |
|
|
<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> |
|
|
<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;"> |
|
|
<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;">客户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> |
|
|
<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> |
|
|
</thead> |
|
|
<tbody id="applyTableBody"> |
|
|
<tbody id="applyTableBody"> |
|
|
<tr> |
|
|
<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> |
|
|
</tr> |
|
|
</tbody> |
|
|
</tbody> |
|
|
</table> |
|
|
</table> |
|
|
@ -3143,6 +3574,56 @@ |
|
|
document.body.insertAdjacentHTML('beforeend', assignModalHTML); |
|
|
document.body.insertAdjacentHTML('beforeend', assignModalHTML); |
|
|
document.body.insertAdjacentHTML('beforeend', permissionModalHTML); |
|
|
document.body.insertAdjacentHTML('beforeend', permissionModalHTML); |
|
|
document.body.insertAdjacentHTML('beforeend', applyModalHTML); |
|
|
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;">×</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', alertModalHTML); |
|
|
document.body.insertAdjacentHTML('beforeend', typeHelpModalHTML); |
|
|
document.body.insertAdjacentHTML('beforeend', typeHelpModalHTML); |
|
|
|
|
|
|
|
|
@ -3564,7 +4045,18 @@ |
|
|
if (currentTypeFilter) { |
|
|
if (currentTypeFilter) { |
|
|
var userType = user.type || ''; |
|
|
var userType = user.type || ''; |
|
|
console.log('公海池筛选类型:', currentTypeFilter, '用户类型:', userType); |
|
|
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 = { |
|
|
var typeMap = { |
|
|
'wholesale': '批发贸易类', |
|
|
'wholesale': '批发贸易类', |
|
|
'e-commerce': '电商平台类', |
|
|
'e-commerce': '电商平台类', |
|
|
@ -3577,6 +4069,7 @@ |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 其他情况,不过滤 |
|
|
// 其他情况,不过滤 |
|
|
return true; |
|
|
return true; |
|
|
@ -5058,11 +5551,13 @@ |
|
|
pagination.appendChild(jumpContainer); |
|
|
pagination.appendChild(jumpContainer); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function applyCustomer(userId, userName, button) { |
|
|
function applyCustomer(userId, userName, button, traceId) { |
|
|
// 显示确认弹窗 |
|
|
// 显示确认弹窗 |
|
|
if (confirm('确认申请该客户吗?')) { |
|
|
if (confirm('确认申请该客户吗?')) { |
|
|
// 获取当前按钮元素 |
|
|
// 获取当前按钮元素 |
|
|
|
|
|
var buttons = []; |
|
|
if (button) { |
|
|
if (button) { |
|
|
|
|
|
buttons.push(button); |
|
|
// 保存原始状态 |
|
|
// 保存原始状态 |
|
|
button.dataset.originalText = button.textContent; |
|
|
button.dataset.originalText = button.textContent; |
|
|
button.dataset.originalDisabled = button.disabled; |
|
|
button.dataset.originalDisabled = button.disabled; |
|
|
@ -5072,8 +5567,9 @@ |
|
|
button.style.backgroundColor = '#faad14'; |
|
|
button.style.backgroundColor = '#faad14'; |
|
|
} else { |
|
|
} else { |
|
|
// 尝试通过选择器查找按钮(兼容旧格式) |
|
|
// 尝试通过选择器查找按钮(兼容旧格式) |
|
|
var buttons = document.querySelectorAll('button[onclick*="applyCustomer(\'" + userId + "\'")]'); |
|
|
var btnElements = document.querySelectorAll('button[onclick*="applyCustomer(\'" + userId + "\'")]'); |
|
|
buttons.forEach(function(btn) { |
|
|
btnElements.forEach(function(btn) { |
|
|
|
|
|
buttons.push(btn); |
|
|
// 保存原始状态 |
|
|
// 保存原始状态 |
|
|
btn.dataset.originalText = btn.textContent; |
|
|
btn.dataset.originalText = btn.textContent; |
|
|
btn.dataset.originalDisabled = btn.disabled; |
|
|
btn.dataset.originalDisabled = btn.disabled; |
|
|
@ -5088,8 +5584,7 @@ |
|
|
var usersManagements = userInfo.usersManagements; |
|
|
var usersManagements = userInfo.usersManagements; |
|
|
|
|
|
|
|
|
var params = { |
|
|
var params = { |
|
|
userId: userId, |
|
|
traceId: traceId, |
|
|
salesId: personnel.managerId || usersManagements.userId || '', |
|
|
|
|
|
salesName: personnel.name || usersManagements.userName || '', |
|
|
salesName: personnel.name || usersManagements.userName || '', |
|
|
reason: '申请成为该客户的负责人' |
|
|
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() { |
|
|
function openApplyModal() { |
|
|
document.getElementById('applyModal').style.display = 'block'; |
|
|
document.getElementById('applyModal').style.display = 'block'; |
|
|
// 加载申请列表 |
|
|
// 加载申请列表 |
|
|
loadApplyList(); |
|
|
loadApplyList(); |
|
|
|
|
|
// 打开后更新角标(可选,因为打开后用户会处理申请) |
|
|
|
|
|
checkApplyStatus(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function closeApplyModal() { |
|
|
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.id}</td> |
|
|
<td style="padding: 10px; border: 1px solid #e8e8e8;">${apply.user_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.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;">${formatDateTime(apply.apply_time)}</td> |
|
|
<td style="padding: 10px; border: 1px solid #e8e8e8;"> |
|
|
<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> |
|
|
<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; |
|
|
tbody.innerHTML += row; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} 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) { |
|
|
if (data.success) { |
|
|
showAlert(`${action}成功`); |
|
|
showAlert(`${action}成功`); |
|
|
loadApplyList(); |
|
|
loadApplyList(); |
|
|
|
|
|
// 更新申请状态角标 |
|
|
|
|
|
checkApplyStatus(); |
|
|
} else { |
|
|
} else { |
|
|
showAlert(`${action}失败: ` + data.message); |
|
|
showAlert(`${action}失败: ` + data.message); |
|
|
} |
|
|
} |
|
|
@ -5265,6 +5790,106 @@ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
window.onload = init; |
|
|
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> |
|
|
</script> |
|
|
</body> |
|
|
</body> |
|
|
</html> |
|
|
</html> |