Files
2026-06-16 11:55:14 +08:00

1093 lines
56 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>企业详情 - 枢机信用储备银行附属红光证券</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.gvsds.com/font-awesome/css/all.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Tailwind 配置 -->
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#8b5cf6',
accent: '#10b981',
danger: '#ef4444',
warning: '#f59e0b',
info: '#06b6d4',
dark: {
100: '#1e293b',
200: '#0f172a',
300: '#020617'
},
light: {
100: '#f8fafc',
200: '#f1f5f9',
300: '#e2e8f0'
}
},
fontFamily: {
inter: ['Inter', 'sans-serif']
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.toast-enter {
animation: toastIn 0.3s ease forwards;
}
.toast-exit {
animation: toastOut 0.3s ease forwards;
}
@keyframes toastIn {
from { transform: translateY(-100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes toastOut {
from { transform: translateY(0); opacity: 1; }
to { transform: translateY(-100%); opacity: 0; }
}
}
</style>
</head>
<body class="font-inter bg-light-200 dark:bg-dark-200 text-dark-300 dark:text-light-100 transition-colors min-h-screen flex flex-col">
<!-- 导航栏 -->
<header class="sticky top-0 z-40 bg-light-100/80 dark:bg-dark-100/80 backdrop-blur-md border-b border-light-300/30 dark:border-dark-300/30 shadow-sm">
<div class="container mx-auto px-4 py-3 flex justify-between items-center">
<div class="flex items-center space-x-2">
<div class="text-primary dark:text-secondary text-2xl">
<i class="fa fa-building"></i>
</div>
<div>
<h1 class="text-lg md:text-xl font-bold text-primary dark:text-secondary">企业详情</h1>
<p class="text-xs md:text-sm text-gray-600 dark:text-gray-400">枢机信用储备银行附属红光证券</p>
</div>
</div>
<div class="flex items-center space-x-4">
<button id="theme-toggle" class="p-2 rounded-full bg-light-300 dark:bg-dark-300 hover:bg-light-200 dark:hover:bg-dark-100 transition-colors">
<i class="fa fa-moon dark:hidden text-dark-300"></i>
<i class="fa fa-sun hidden dark:inline text-light-100"></i>
</button>
</div>
</div>
</header>
<main class="flex-grow py-8">
<div class="container mx-auto px-4">
<!-- 加载状态 -->
<div id="loading-state" class="bg-light-100 dark:bg-dark-100 rounded-xl shadow-sm p-8 text-center">
<div class="flex flex-col items-center">
<i class="fa fa-circle-o-notch fa-spin text-4xl mb-4 text-primary dark:text-secondary"></i>
<p>正在加载企业信息...</p>
<p id="loading-enterprise-uuid" class="text-xs font-mono mt-2 text-gray-500 dark:text-gray-400"></p>
</div>
</div>
<!-- 错误状态 -->
<div id="error-state" class="bg-light-100 dark:bg-dark-100 rounded-xl shadow-sm p-8 text-center hidden">
<div class="flex flex-col items-center">
<i class="fa fa-exclamation-triangle text-4xl mb-4 text-warning"></i>
<p id="error-message" class="mb-4">加载企业信息失败</p>
<button id="retry-button" class="px-4 py-2 rounded-lg bg-primary dark:bg-secondary text-white hover:bg-primary/90 dark:hover:bg-secondary/90 transition-colors">
重试
</button>
</div>
</div>
<!-- 企业详情内容 -->
<div id="enterprise-detail" class="bg-light-100 dark:bg-dark-100 rounded-xl shadow-sm overflow-hidden hidden">
<!-- 企业头部信息 -->
<div class="bg-gradient-to-r from-primary/10 to-secondary/10 dark:from-primary/20 dark:to-secondary/20 p-6 border-b border-light-300 dark:border-dark-300">
<div class="flex flex-col md:flex-row md:items-center justify-between">
<div>
<h2 id="enterprise-name" class="text-2xl md:text-3xl font-bold mb-2"></h2>
<div class="flex flex-wrap items-center gap-3">
<span id="enterprise-type" class="px-3 py-1 bg-light-300 dark:bg-dark-300 rounded-full text-sm"></span>
<span id="enterprise-status" class="px-3 py-1 rounded-full text-sm"></span>
<span id="enterprise-uuid" class="text-xs font-mono text-gray-600 dark:text-gray-400"></span>
</div>
</div>
<div class="mt-4 md:mt-0">
<span id="enterprise-registered-capital" class="text-lg font-semibold"></span>
</div>
</div>
</div>
<!-- 详情内容区域 -->
<div class="p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<!-- 基本信息 -->
<div>
<h3 class="text-lg font-semibold mb-4 pb-2 border-b border-light-300 dark:border-dark-300">基本信息</h3>
<dl class="space-y-4">
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">企业UUID</dt>
<dd id="detail-uuid" class="w-2/3 font-mono text-sm break-all"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">上级企业</dt>
<dd id="detail-parent-enterprise" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">注册资本</dt>
<dd id="detail-registered-capital" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">资本币种</dt>
<dd id="detail-capital-currency" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">创建时间</dt>
<dd id="detail-create-time" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">营业期限</dt>
<dd id="detail-business-period" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">核准日期</dt>
<dd id="detail-approval-date" class="w-2/3"></dd>
</div>
</dl>
</div>
<!-- 联系信息 -->
<div>
<h3 class="text-lg font-semibold mb-4 pb-2 border-b border-light-300 dark:border-dark-300">联系信息</h3>
<dl class="space-y-4">
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">联系电话</dt>
<dd id="detail-phone" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">电子邮箱</dt>
<dd id="detail-email" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">企业网站</dt>
<dd id="detail-website" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">企业地址</dt>
<dd id="detail-address" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">行政区划</dt>
<dd id="detail-division" class="w-2/3"></dd>
</div>
<div class="flex">
<dt class="w-1/3 text-sm text-gray-600 dark:text-gray-400">许可证号</dt>
<dd id="detail-license" class="w-2/3 font-mono text-sm"></dd>
</div>
</dl>
</div>
</div>
<!-- 法人信息 -->
<div class="mt-8">
<h3 class="text-lg font-semibold mb-4 pb-2 border-b border-light-300 dark:border-dark-300">法人信息</h3>
<div id="detail-legal-persons" class="flex flex-wrap gap-2">
<!-- 法人信息将通过JS动态生成 -->
</div>
</div>
<!-- 经营范围 -->
<div class="mt-8">
<h3 class="text-lg font-semibold mb-4 pb-2 border-b border-light-300 dark:border-dark-300">经营范围</h3>
<div id="detail-business-scope" class="flex flex-wrap gap-2">
<!-- 经营范围将通过JS动态生成 -->
</div>
</div>
<!-- 企业成员管理 -->
<div class="mt-8">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold pb-2 border-b border-light-300 dark:border-dark-300">企业成员</h3>
<div class="flex gap-2">
<button id="refresh-members" class="px-3 py-1 text-sm rounded-lg bg-info/10 text-info hover:bg-info/20 transition-colors">
<i class="fa fa-sync-alt mr-1"></i>刷新列表
</button>
<button id="add-member" class="px-3 py-1 text-sm rounded-lg bg-accent/10 text-accent hover:bg-accent/20 transition-colors">
<i class="fa fa-plus mr-1"></i>添加成员
</button>
</div>
</div>
<!-- 成员列表加载状态 -->
<div id="members-loading" class="py-8 text-center">
<i class="fa fa-circle-o-notch fa-spin text-2xl text-primary dark:text-secondary"></i>
<p class="mt-2">加载成员列表中...</p>
</div>
<!-- 成员列表 -->
<div id="members-list" class="overflow-x-auto hidden">
<table class="min-w-full divide-y divide-light-300 dark:divide-dark-300">
<thead>
<tr>
<th class="px-4 py-3 bg-light-200 dark:bg-dark-300 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">玩家名</th>
<th class="px-4 py-3 bg-light-200 dark:bg-dark-300 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">用户名</th>
<th class="px-4 py-3 bg-light-200 dark:bg-dark-300 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">用户UUID</th>
<th class="px-4 py-3 bg-light-200 dark:bg-dark-300 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">玩家UUID</th>
<th class="px-4 py-3 bg-light-200 dark:bg-dark-300 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">用户类型</th>
<th class="px-4 py-3 bg-light-200 dark:bg-dark-300 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">操作</th>
</tr>
</thead>
<tbody id="members-table-body" class="divide-y divide-light-300 dark:divide-dark-300">
<!-- 成员数据将通过JS动态生成 -->
</tbody>
</table>
</div>
<!-- 成员列表为空状态 -->
<div id="members-empty" class="py-8 text-center hidden">
<i class="fa fa-users text-4xl text-gray-400 dark:text-gray-500 mb-2"></i>
<p class="text-gray-500 dark:text-gray-400">暂无成员信息</p>
</div>
<!-- 成员列表错误状态 -->
<div id="members-error" class="py-8 text-center hidden">
<i class="fa fa-exclamation-circle text-2xl text-warning mb-2"></i>
<p id="members-error-message" class="text-warning">加载成员列表失败</p>
</div>
</div>
<!-- 企业描述 -->
<div class="mt-8">
<h3 class="text-lg font-semibold mb-4 pb-2 border-b border-light-300 dark:border-dark-300">企业描述</h3>
<div id="detail-description" class="bg-light-200 dark:bg-dark-300 p-4 rounded-lg whitespace-pre-line">
<!-- 企业描述将通过JS动态生成 -->
</div>
</div>
</div>
</div>
</div>
</main>
<!-- 添加/编辑成员模态框 -->
<div id="member-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
<!-- 背景遮罩 -->
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
</div>
<!-- 模态框内容 -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-light-100 dark:bg-dark-100 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-gray-100" id="modal-title">
添加成员
</h3>
<div class="mt-4">
<form id="member-form">
<input type="hidden" id="form-mode" value="new">
<input type="hidden" id="form-enterprise-uuid">
<input type="hidden" id="form-original-user-uuid">
<div class="mb-4">
<label for="user-name" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
用户名( 和UUID选填其中一个 ) <span class="text-danger">*</span>
</label>
<input type="text" name="user-name" id="user-name" required
class="w-full px-3 py-2 border border-light-300 dark:border-dark-300 rounded-md shadow-sm focus:outline-none focus:ring-primary dark:focus:ring-secondary focus:border-primary dark:focus:border-secondary bg-light-200 dark:bg-dark-300">
</div>
<div class="mb-4">
<label for="user-uuid" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
用户UUID <span class="text-danger">*</span>
</label>
<input type="text" name="user-uuid" id="user-uuid" required
class="w-full px-3 py-2 border border-light-300 dark:border-dark-300 rounded-md shadow-sm focus:outline-none focus:ring-primary dark:focus:ring-secondary focus:border-primary dark:focus:border-secondary bg-light-200 dark:bg-dark-300">
</div>
<div class="mb-4">
<label for="user-type" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
用户类型 <span class="text-danger">*</span>
</label>
<select name="user-type" id="user-type" required
class="w-full px-3 py-2 border border-light-300 dark:border-dark-300 rounded-md shadow-sm focus:outline-none focus:ring-primary dark:focus:ring-secondary focus:border-primary dark:focus:border-secondary bg-light-200 dark:bg-dark-300">
<!--<option value="0">0 - 法人</option>-->
<option value="1">1 - 监事</option>
<option value="2">2 - 成员</option>
</select>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="bg-light-200 dark:bg-dark-300 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="save-member" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-primary dark:bg-secondary text-base font-medium text-white hover:bg-primary/90 dark:hover:bg-secondary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary dark:focus:ring-secondary sm:ml-3 sm:w-auto sm:text-sm">
保存
</button>
<button type="button" id="cancel-member" class="mt-3 w-full inline-flex justify-center rounded-md border border-light-300 dark:border-dark-300 shadow-sm px-4 py-2 bg-light-100 dark:bg-dark-100 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-light-200 dark:hover:bg-dark-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary dark:focus:ring-secondary sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
取消
</button>
</div>
</div>
</div>
</div>
<!-- 确认删除模态框 -->
<div id="delete-confirm-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
<!-- 背景遮罩 -->
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
</div>
<!-- 模态框内容 -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-light-100 dark:bg-dark-100 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full">
<div class="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 dark:bg-red-900/30 sm:mx-0 sm:h-10 sm:w-10">
<i class="fa fa-exclamation-circle text-danger" aria-hidden="true"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-gray-100">
确认删除
</h3>
<div class="mt-2">
<p class="text-sm text-gray-500 dark:text-gray-400">
您确定要删除该成员吗?此操作无法撤销。
</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-2" id="delete-member-info">
用户UUID: <span id="delete-user-uuid"></span>
</p>
</div>
</div>
</div>
</div>
<div class="bg-light-200 dark:bg-dark-300 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="confirm-delete" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-danger text-base font-medium text-white hover:bg-danger/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-danger sm:ml-3 sm:w-auto sm:text-sm">
确认删除
</button>
<button type="button" id="cancel-delete" class="mt-3 w-full inline-flex justify-center rounded-md border border-light-300 dark:border-dark-300 shadow-sm px-4 py-2 bg-light-100 dark:bg-dark-100 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-light-200 dark:hover:bg-dark-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary dark:focus:ring-secondary sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
取消
</button>
</div>
</div>
</div>
</div>
<!-- 自定义提示框 -->
<div id="toast-container" class="fixed top-4 right-4 z-50 flex flex-col gap-2 max-w-xs"></div>
<footer class="bg-light-100 dark:bg-dark-100 border-t border-light-300/30 dark:border-dark-300/30 py-6">
<div class="container mx-auto px-4 text-center text-sm text-gray-600 dark:text-gray-400">
<p>© 2025 枢机信用储备银行附属红光证券 - 保留所有权利</p>
</div>
</footer>
<script>
// 全局变量存储当前企业UUID和当前用户类型
let currentEnterpriseUUID = null;
let currentUserType = null; // 存储当前用户在企业中的类型(来自API的EnterpriseUserType)
// 初始化页面
document.addEventListener('DOMContentLoaded', function() {
// 初始化主题
if (localStorage.getItem('darkMode') === 'true') {
document.documentElement.classList.add('dark');
}
// 主题切换
const themeToggle = document.getElementById('theme-toggle');
themeToggle.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));
});
// 获取URL参数中的企业UUID
const urlParams = new URLSearchParams(window.location.search);
const enterpriseUUID = urlParams.get('EnterpriseUUID');
if (!enterpriseUUID) {
showError('未指定企业UUID,请从企业列表进入');
return;
}
// 保存当前企业UUID
currentEnterpriseUUID = enterpriseUUID;
// 显示加载中的UUID
document.getElementById('loading-enterprise-uuid').textContent = enterpriseUUID;
// 加载企业详情
loadEnterpriseDetail(enterpriseUUID);
// 重试按钮
document.getElementById('retry-button').addEventListener('click', function() {
loadEnterpriseDetail(enterpriseUUID);
});
// 成员管理相关事件绑定
bindMemberEvents();
});
/**
* 绑定成员管理相关事件
*/
function bindMemberEvents() {
// 刷新成员列表
document.getElementById('refresh-members').addEventListener('click', function() {
if (currentEnterpriseUUID) {
loadEnterpriseMembers(currentEnterpriseUUID);
}
});
// 添加成员按钮
document.getElementById('add-member').addEventListener('click', function() {
if (currentEnterpriseUUID) {
openMemberModal('new', {
EnterpriseUUID: currentEnterpriseUUID
});
}
});
// 保存成员按钮
document.getElementById('save-member').addEventListener('click', function() {
saveMember();
});
// 取消添加/编辑成员
document.getElementById('cancel-member').addEventListener('click', function() {
closeMemberModal();
});
// 取消删除
document.getElementById('cancel-delete').addEventListener('click', function() {
closeDeleteConfirmModal();
});
// 确认删除
document.getElementById('confirm-delete').addEventListener('click', function() {
confirmDeleteMember();
});
}
/**
* 根据用户类型更新操作按钮的可见性
* 当用户类型为0或1时显示按钮,否则隐藏
*/
function updateActionButtonsVisibility() {
const isAllowed = [0, 1].includes(Number(currentUserType));
// 控制"添加成员"按钮
document.getElementById('add-member').style.display = isAllowed ? 'inline-flex' : 'none';
}
/**
* 从API加载企业详情
* @param {string} enterpriseUUID 企业UUID
*/
function loadEnterpriseDetail(enterpriseUUID) {
// 显示加载状态
document.getElementById('loading-state').classList.remove('hidden');
document.getElementById('error-state').classList.add('hidden');
document.getElementById('enterprise-detail').classList.add('hidden');
// 构建API请求URL,包含企业UUID参数
const apiUrl = `/api/crb/enterprises/${encodeURIComponent(enterpriseUUID)}/`;
// 发送API请求
fetch(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误,状态码: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.status === 0 && data.data) {
if (data.data) {
// 保存当前用户在企业中的类型
currentUserType = data.data.EnterpriseUserType;
// 渲染企业详情
renderEnterpriseDetail(data.data);
// 根据用户类型更新按钮可见性
updateActionButtonsVisibility();
// 显示详情,隐藏加载状态
document.getElementById('loading-state').classList.add('hidden');
document.getElementById('enterprise-detail').classList.remove('hidden');
// 加载企业成员
loadEnterpriseMembers(enterpriseUUID);
} else {
showError(`未找到UUID为 ${enterpriseUUID} 的企业`);
}
} else {
// API返回错误状态
showError(data.msg || '获取企业信息失败');
}
})
.catch(error => {
// 请求失败
showError(`加载失败: ${error.message}`);
});
}
/**
* 从API加载企业成员
* @param {string} enterpriseUUID 企业UUID
*/
function loadEnterpriseMembers(enterpriseUUID) {
// 显示加载状态
document.getElementById('members-loading').classList.remove('hidden');
document.getElementById('members-list').classList.add('hidden');
document.getElementById('members-empty').classList.add('hidden');
document.getElementById('members-error').classList.add('hidden');
// 构建API请求URL
const apiUrl = `/api/crb/enterprise-users/?EnterpriseUUID=${encodeURIComponent(enterpriseUUID)}`;
// 发送API请求
fetch(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误,状态码: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.status === 0) {
// 隐藏加载状态
document.getElementById('members-loading').classList.add('hidden');
if (data.data && data.data.length > 0) {
// 渲染成员列表
renderEnterpriseMembers(data.data);
document.getElementById('members-list').classList.remove('hidden');
} else {
// 显示空状态
document.getElementById('members-empty').classList.remove('hidden');
}
} else {
// API返回错误状态
document.getElementById('members-loading').classList.add('hidden');
document.getElementById('members-error').classList.remove('hidden');
document.getElementById('members-error-message').textContent = data.msg || '加载成员列表失败';
}
})
.catch(error => {
// 请求失败
document.getElementById('members-loading').classList.add('hidden');
document.getElementById('members-error').classList.remove('hidden');
document.getElementById('members-error-message').textContent = `加载失败: ${error.message}`;
});
}
/**
* 渲染企业成员列表
* @param {Array} members 成员数组
*/
function renderEnterpriseMembers(members) {
const tableBody = document.getElementById('members-table-body');
tableBody.innerHTML = '';
// 判断当前用户是否有权限操作(类型为0或1)
const isAllowed = [0, 1].includes(Number(currentUserType));
members.forEach(member => {
// 转换用户类型为文本
let userTypeText = '未知';
switch(parseInt(member.EnterpriseUserType)) {
case 0:
userTypeText = '法人';
break;
case 1:
userTypeText = '监事';
break;
case 2:
userTypeText = '成员';
break;
}
const row = document.createElement('tr');
// 根据权限决定是否显示操作按钮
const actionButtons = isAllowed ? `
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium">
<button class="text-primary dark:text-secondary hover:text-primary/80 dark:hover:text-secondary/80 mr-3 edit-member"
data-user-uuid="${member.UserUUID}"
data-user-type="${member.EnterpriseUserType}">
编辑
</button>
<button class="text-danger hover:text-danger/80 delete-member"
data-user-uuid="${member.UserUUID}">
删除
</button>
</td>
` : `
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
无权限
</td>
`;
row.innerHTML = `
<td class="px-4 py-3 whitespace-nowrap">${member.PlayerName || '-'}</td>
<td class="px-4 py-3 whitespace-nowrap">${member.UserName || '-'}</td>
<td class="px-4 py-3 whitespace-nowrap font-mono text-sm">${truncateText(member.UserUUID, 20)}</td>
<td class="px-4 py-3 whitespace-nowrap font-mono text-sm">${member.PlayerUUID || '-'}</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
${member.EnterpriseUserType == 0 ? 'bg-primary/10 text-primary' :
member.EnterpriseUserType == 1 ? 'bg-secondary/10 text-secondary' :
'bg-accent/10 text-accent'}">
${userTypeText} (${member.EnterpriseUserType})
</span>
</td>
${actionButtons}
`;
tableBody.appendChild(row);
});
// 如果有权限,绑定编辑和删除按钮事件
if (isAllowed) {
bindMemberActionEvents();
}
}
/**
* 绑定成员操作按钮事件
*/
function bindMemberActionEvents() {
// 编辑成员按钮
document.querySelectorAll('.edit-member').forEach(button => {
button.addEventListener('click', function() {
const userUUID = this.getAttribute('data-user-uuid');
const userType = this.getAttribute('data-user-type');
openMemberModal('edit', {
EnterpriseUUID: currentEnterpriseUUID,
UserUUID: userUUID,
EnterpriseUserType: userType
});
});
});
// 删除成员按钮
document.querySelectorAll('.delete-member').forEach(button => {
button.addEventListener('click', function() {
const userUUID = this.getAttribute('data-user-uuid');
openDeleteConfirmModal(userUUID);
});
});
}
/**
* 打开添加/编辑成员模态框
* @param {string} mode 模式: new/edit
* @param {Object} data 成员数据
*/
function openMemberModal(mode, data) {
// 设置模态框标题
document.getElementById('modal-title').textContent = mode === 'new' ? '添加成员' : '编辑成员';
// 设置表单模式和隐藏字段
document.getElementById('form-mode').value = mode;
document.getElementById('form-enterprise-uuid').value = data.EnterpriseUUID;
if (mode === 'edit') {
document.getElementById('form-original-user-uuid').value = data.UserUUID;
document.getElementById('user-uuid').value = data.UserUUID;
document.getElementById('user-type').value = data.EnterpriseUserType;
} else {
document.getElementById('form-original-user-uuid').value = '';
document.getElementById('user-uuid').value = '';
document.getElementById('user-type').value = '2'; // 默认成员
}
// 显示模态框
document.getElementById('member-modal').classList.remove('hidden');
}
/**
* 关闭添加/编辑成员模态框
*/
function closeMemberModal() {
document.getElementById('member-modal').classList.add('hidden');
document.getElementById('member-form').reset();
}
/**
* 打开删除确认模态框
* @param {string} userUUID 用户UUID
*/
function openDeleteConfirmModal(userUUID) {
// 设置要删除的用户UUID
document.getElementById('delete-user-uuid').textContent = userUUID;
// 显示模态框
document.getElementById('delete-confirm-modal').classList.remove('hidden');
}
/**
* 关闭删除确认模态框
*/
function closeDeleteConfirmModal() {
document.getElementById('delete-confirm-modal').classList.add('hidden');
}
/**
* 保存成员信息(新增或编辑)
*/
function saveMember() {
const mode = document.getElementById('form-mode').value;
const enterpriseUUID = document.getElementById('form-enterprise-uuid').value;
const originalUserUUID = document.getElementById('form-original-user-uuid').value;
const userName = document.getElementById('user-name').value.trim();
const userUUID = document.getElementById('user-uuid').value.trim();
const userType = document.getElementById('user-type').value;
// 简单验证
if (!userUUID && !userName) {
showToast('请输入用户UUID或用户名', 'warning');
return;
}
// 构建请求参数
const params = new URLSearchParams();
params.append('EnterpriseUUID', enterpriseUUID);
params.append('UserName', userName);
params.append('UserUUID', userUUID);
params.append('EnterpriseUserType', userType);
// 如果是编辑模式,需要提供原始UserUUID用于识别
if (mode === 'edit' && originalUserUUID && originalUserUUID !== userUUID) {
params.append('OriginalUserUUID', originalUserUUID);
}
// 发送API请求
fetch('/api/crb/enterprise-users/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(Object.fromEntries(params))
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误,状态码: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.status === 0) {
// 操作成功,关闭模态框并刷新成员列表
closeMemberModal();
loadEnterpriseMembers(enterpriseUUID);
// 显示成功提示
showToast(mode === 'new' ? '成员添加成功' : '成员编辑成功', 'success');
} else {
// 操作失败
showToast(data.msg || (mode === 'new' ? '成员添加失败' : '成员编辑失败'), 'error');
}
})
.catch(error => {
console.error('保存成员失败:', error);
showToast('网络错误,保存失败', 'error');
});
}
/**
* 确认删除成员
*/
function confirmDeleteMember() {
const userUUID = document.getElementById('delete-user-uuid').textContent;
if (!currentEnterpriseUUID || !userUUID) {
closeDeleteConfirmModal();
return;
}
// 构建请求参数
const params = new URLSearchParams();
params.append('EnterpriseUUID', currentEnterpriseUUID);
params.append('UserUUID', userUUID);
// 发送API请求
fetch('/api/crb/enterprise-users/' + userUUID + '/', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误,状态码: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.status === 0) {
// 操作成功,关闭模态框并刷新成员列表
closeDeleteConfirmModal();
loadEnterpriseMembers(currentEnterpriseUUID);
// 显示成功提示
showToast('成员删除成功', 'success');
} else {
// 操作失败
showToast(data.msg || '成员删除失败', 'error');
}
})
.catch(error => {
console.error('删除成员失败:', error);
showToast('网络错误,删除失败', 'error');
});
}
/**
* 渲染企业详情
* @param {Object} enterprise 企业数据对象
*/
function renderEnterpriseDetail(enterprise) {
// 处理企业类型和状态的显示文本和样式
let enterpriseTypeText = '未知类型';
switch(enterprise.EnterpriseType) {
case 0:
enterpriseTypeText = '股份有限公司';
break;
case 1:
enterpriseTypeText = '国有企业';
break;
}
let enterpriseStatusText = '未知状态';
let enterpriseStatusClass = 'bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200';
switch(enterprise.EnterpriseStatus) {
case 0:
enterpriseStatusText = '正常';
enterpriseStatusClass = 'bg-accent/20 text-accent';
break;
case 1:
enterpriseStatusText = '停业';
enterpriseStatusClass = 'bg-warning/20 text-warning';
break;
case 2:
enterpriseStatusText = '注销';
enterpriseStatusClass = 'bg-danger/20 text-danger';
break;
case 3:
enterpriseStatusText = '吊销';
enterpriseStatusClass = 'bg-danger/20 text-danger';
break;
case 4:
enterpriseStatusText = '筹建';
enterpriseStatusClass = 'bg-info/20 text-info';
break;
}
// 处理法人信息和经营范围为数组
const juridicalPersons = typeof enterprise.EnterpriseJuridicalPerson === 'string'
? enterprise.EnterpriseJuridicalPerson.split(',')
: enterprise.EnterpriseJuridicalPerson || [];
const businessScope = typeof enterprise.EnterpriseBusinessScope === 'string'
? enterprise.EnterpriseBusinessScope.split(',')
: enterprise.EnterpriseBusinessScope || [];
// 填充基本信息
document.getElementById('enterprise-name').textContent = enterprise.EnterpriseName || '未知企业名称';
document.getElementById('enterprise-type').textContent = enterpriseTypeText;
document.getElementById('enterprise-status').textContent = enterpriseStatusText;
document.getElementById('enterprise-status').className = `px-3 py-1 rounded-full text-sm ${enterpriseStatusClass}`;
document.getElementById('enterprise-uuid').textContent = `UUID: ${enterprise.EnterpriseUUID}`;
document.getElementById('enterprise-registered-capital').textContent =
`${enterprise.EnterpriseRegisteredCapital || 0} 万 ${enterprise.EnterpriseCapitalGC || 'GC'}`;
// 填充详情信息
document.getElementById('detail-uuid').textContent = enterprise.EnterpriseUUID;
document.getElementById('detail-parent-enterprise').textContent =
enterprise.EnterpriseFatherUUID || '无上级企业';
document.getElementById('detail-registered-capital').textContent =
`${enterprise.EnterpriseRegisteredCapital || 0} 万`;
document.getElementById('detail-capital-currency').textContent =
enterprise.EnterpriseCapitalGC || 'GC';
document.getElementById('detail-create-time').textContent =
enterprise.EnterpriseCreateTime || '未知时间';
document.getElementById('detail-business-period').textContent =
enterprise.EnterpriseBusinessPeriod || '长期';
document.getElementById('detail-approval-date').textContent =
enterprise.EnterpriseApprovalDate || '未知';
// 填充联系信息
document.getElementById('detail-phone').textContent = enterprise.EnterpriseTele || '-';
document.getElementById('detail-email').textContent = enterprise.EnterpriseEmail || '-';
// 处理网站链接
const websiteElement = document.getElementById('detail-website');
if (enterprise.EnterpriseWebsite) {
websiteElement.innerHTML = `<a href="${enterprise.EnterpriseWebsite}" target="_blank" class="text-primary dark:text-secondary hover:underline">${truncateText(enterprise.EnterpriseWebsite, 30)}</a>`;
} else {
websiteElement.textContent = '-';
}
document.getElementById('detail-address').textContent = enterprise.EnterpriseAddres || '-';
document.getElementById('detail-division').textContent = enterprise.EnterpriseAdministrativeDivisions || '-';
document.getElementById('detail-license').textContent = enterprise.Enterprise3C || '-';
// 填充法人信息
const legalPersonsContainer = document.getElementById('detail-legal-persons');
legalPersonsContainer.innerHTML = '';
if (juridicalPersons.length > 0) {
juridicalPersons.forEach(person => {
const badge = document.createElement('span');
badge.className = 'px-3 py-1 bg-primary/10 text-primary rounded-full text-sm';
badge.textContent = person;
legalPersonsContainer.appendChild(badge);
});
} else {
legalPersonsContainer.innerHTML = '<span class="text-gray-500 dark:text-gray-400">无记录</span>';
}
// 填充经营范围
const businessScopeContainer = document.getElementById('detail-business-scope');
businessScopeContainer.innerHTML = '';
if (businessScope.length > 0) {
businessScope.forEach(scope => {
const badge = document.createElement('span');
badge.className = 'px-3 py-1 bg-light-300 dark:bg-dark-300 rounded-full text-sm';
badge.textContent = scope;
businessScopeContainer.appendChild(badge);
});
} else {
businessScopeContainer.innerHTML = '<span class="text-gray-500 dark:text-gray-400">无记录</span>';
}
// 填充企业描述
document.getElementById('detail-description').textContent =
enterprise.EnterpriseDesc || '暂无企业描述信息';
}
/**
* 显示错误信息
* @param {string} message 错误信息
*/
function showError(message) {
document.getElementById('loading-state').classList.add('hidden');
document.getElementById('enterprise-detail').classList.add('hidden');
document.getElementById('error-state').classList.remove('hidden');
document.getElementById('error-message').textContent = message;
}
/**
* 截断文本并添加省略号
* @param {string} text 文本
* @param {number} maxLength 最大长度
* @returns {string} 处理后的文本
*/
function truncateText(text, maxLength) {
if (!text) return '';
return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
}
/**
* 显示自定义提示框
* @param {string} message 提示消息
* @param {string} type 提示类型: success/error/warning/info
* @param {number} duration 显示时长(毫秒),默认3000
*/
function showToast(message, type = 'info', duration = 3000) {
// 创建提示框元素
const toast = document.createElement('div');
toast.className = 'toast-enter px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 max-w-xs';
// 根据类型设置样式和图标
let iconClass = 'fa-info-circle';
let bgClass = 'bg-info text-white';
switch(type) {
case 'success':
iconClass = 'fa-check-circle';
bgClass = 'bg-accent text-white';
break;
case 'error':
iconClass = 'fa-times-circle';
bgClass = 'bg-danger text-white';
break;
case 'warning':
iconClass = 'fa-exclamation-triangle';
bgClass = 'bg-warning text-white';
break;
case 'info':
default:
iconClass = 'fa-info-circle';
bgClass = 'bg-primary text-white';
break;
}
toast.classList.add(...bgClass.split(' '));
// 设置提示框内容
toast.innerHTML = `
<i class="fa ${iconClass} text-lg"></i>
<span class="flex-1">${message}</span>
<button class="toast-close text-white/80 hover:text-white">
<i class="fa fa-times"></i>
</button>
`;
// 添加到容器
const container = document.getElementById('toast-container');
container.appendChild(toast);
// 绑定关闭按钮事件
toast.querySelector('.toast-close').addEventListener('click', () => {
removeToast(toast);
});
// 设置自动关闭
setTimeout(() => {
removeToast(toast);
}, duration);
}
/**
* 移除提示框
* @param {HTMLElement} toast 提示框元素
*/
function removeToast(toast) {
toast.classList.remove('toast-enter');
toast.classList.add('toast-exit');
// 动画结束后移除元素
setTimeout(() => {
toast.remove();
}, 300);
}
</script>
</body>
</html>