修复了一些问题
This commit is contained in:
1 parent
f3cf68a51a
commit
a77df5da0f
114 files changed
+5183
-1664
No files matched your search
@@ -0,0 +1,244 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js?v=20260625d"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<a href="javascript:void(0)" class="cp-back-btn" onclick="goBack()"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-building icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">公司详情</span>
|
||||
</h1>
|
||||
<button class="GERPBtn Primary" onclick="handleEdit()" style="margin-left:auto;"><i class="fas fa-edit"></i> 编辑</button>
|
||||
</div>
|
||||
<div class="cp-container" id="detailContainer" style="overflow:auto;">
|
||||
<div class="cp-loading"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const currentServer = CompanyUtils.getServer();
|
||||
const companyUUID = new URLSearchParams(window.location.search).get('CompanyUUID');
|
||||
|
||||
CompanyUtils.setPageTitle('公司详情');
|
||||
|
||||
function goBack() {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
GERP.Navigate('/pages/Company/company.html' + (currentServer !== 'gvsds-master' ? `?server=${encodeURIComponent(currentServer)}` : ''), '公司管理');
|
||||
}
|
||||
}
|
||||
|
||||
let currentData = null;
|
||||
let deptTable = null;
|
||||
let wgTable = null;
|
||||
let empTable = null;
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const containerEl = document.getElementById('detailContainer');
|
||||
|
||||
if (!companyUUID) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-triangle" style="margin-right:6px;"></i> 缺少 CompanyUUID 参数,无法加载公司详情。</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dataResp = await fetch(buildApiUrl('/API/FormAPI/Get/Company', { CompanyUUID: companyUUID, PageSize: '1' }), { credentials: 'include' });
|
||||
const dataResult = await dataResp.json();
|
||||
if (dataResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 加载失败: ${CompanyUtils.esc(dataResult.msg || '未知错误')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = dataResult.data || [];
|
||||
const data = Array.isArray(list) ? (list.find(c => c.CompanyUUID === companyUUID) || list[0]) : list;
|
||||
if (!data) {
|
||||
containerEl.innerHTML = `<div class="cp-error">未找到公司数据</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
currentData = data;
|
||||
CompanyUtils.setPageTitle(data.CompanyName || '公司详情');
|
||||
|
||||
// 解析 UUID 字段为名称
|
||||
const uuidMap = {};
|
||||
if (data.ParentCompanyUUID) uuidMap.parentCompany = { table: 'Company', uuids: [data.ParentCompanyUUID] };
|
||||
if (data.TenantUUID) uuidMap.tenant = { table: 'Tenant', uuids: [data.TenantUUID] };
|
||||
const resolved = await CompanyUtils.resolveUUIDs(uuidMap);
|
||||
|
||||
// 渲染基本信息 + 表格容器
|
||||
containerEl.innerHTML = `
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-building"></i> 基本信息</h3>
|
||||
<div class="cp-info-grid">
|
||||
<div class="cp-info-item"><div class="label">公司名称</div><div class="value">${CompanyUtils.esc(data.CompanyName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">公司简称</div><div class="value">${CompanyUtils.esc(data.CompanyShort) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">公司状态</div><div class="value">${CompanyUtils.statusTag(data.CompanyStatus)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">上级公司</div><div class="value">${CompanyUtils.esc(resolved.parentCompany?.[data.ParentCompanyUUID] || data.ParentCompanyUUID) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">租户</div><div class="value">${CompanyUtils.esc(resolved.tenant?.[data.TenantUUID] || data.TenantUUID) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">创建时间</div><div class="value">${CompanyUtils.formatTime(data.CompanyCreateTime)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-sitemap"></i> 部门</h3>
|
||||
<div id="dept-table-container" style="height:400px;"></div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-users-cog"></i> 工作组</h3>
|
||||
<div id="wg-table-container" style="height:400px;"></div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-user-friends"></i> 员工</h3>
|
||||
<div id="emp-table-container" style="height:400px;"></div>
|
||||
</div>`;
|
||||
|
||||
// 初始化 TableEngine 实例
|
||||
initDeptTable();
|
||||
initWorkgroupTable();
|
||||
initEmployeeTable();
|
||||
} catch (e) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 网络错误: ${CompanyUtils.esc(e.message)}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function initDeptTable() {
|
||||
deptTable = new TableEngine({
|
||||
container: '#dept-table-container',
|
||||
height: '400px',
|
||||
tableName: 'Department',
|
||||
columns: [
|
||||
{ field: 'DeptUUID', title: '部门UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'DeptName', title: '部门名称' },
|
||||
{ field: 'DeptStatus', title: '状态', type: 'select', options: [{ value: 0, label: '禁用' }, { value: 1, label: '启用' }] },
|
||||
{ field: 'DeptSort', title: '排序', type: 'number' },
|
||||
{ field: 'ParentDeptUUID_label', title: '上级部门' },
|
||||
{ field: 'DeptCreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/Department'),
|
||||
add: buildApiUrl('/API/FormAPI/Add/Department'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/Department/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/Department/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/Department/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/department-detail.html?DeptUUID=${encodeURIComponent(row.DeptUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.DeptName || '部门详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function initWorkgroupTable() {
|
||||
wgTable = new TableEngine({
|
||||
container: '#wg-table-container',
|
||||
tableName: 'Workgroup',
|
||||
columns: [
|
||||
{ field: 'WorkgroupUUID', title: '工作组UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'WorkgroupName', title: '工作组名称' },
|
||||
{ field: 'WorkgroupStatus', title: '状态', type: 'select', options: [{ value: 0, label: '禁用' }, { value: 1, label: '启用' }] },
|
||||
{ field: 'WorkgroupCreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/Workgroup'),
|
||||
add: buildApiUrl('/API/FormAPI/Add/Workgroup'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/Workgroup/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/Workgroup/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/Workgroup/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/workgroup-detail.html?WorkgroupUUID=${encodeURIComponent(row.WorkgroupUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.WorkgroupName || '工作组详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function initEmployeeTable() {
|
||||
empTable = new TableEngine({
|
||||
container: '#emp-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserRole',
|
||||
columns: [
|
||||
{ field: 'UserRoleUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('UserUUID', '用户名', 'User', { editable: false }),
|
||||
CompanyUtils.epColumn('RoleUUID', '角色名', 'Role'),
|
||||
CompanyUtils.epColumn('CompanyUUID', '公司', 'Company', { editable: false, hideInForm: true }),
|
||||
CompanyUtils.epColumn('DeptUUID', '部门', 'Department'),
|
||||
CompanyUtils.epColumn('WorkgroupUUID', '工作组', 'Workgroup'),
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{ value: 0, label: '组员' }, { value: 1, label: '组长' }] },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserRole'),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserRole'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserRole/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserRole/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserRole/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/employee-detail.html?UserUUID=${encodeURIComponent(row.UserUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.UserUUID_label || '员工详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑按钮:弹出编辑对话框 */
|
||||
async function handleEdit() {
|
||||
if (!currentData) return;
|
||||
CompanyUtils.showEditDialog({
|
||||
tableName: 'Company',
|
||||
data: currentData,
|
||||
onSave: () => {
|
||||
if (window.GERPUI && typeof window.GERPUI.ShowToast === 'function') {
|
||||
window.GERPUI.ShowToast({ message: '保存成功', type: 'success' });
|
||||
}
|
||||
init();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-building icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">公司管理</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="cp-container" id="TableContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const page = new CompanyTablePage({
|
||||
tableName: 'Company',
|
||||
title: '公司管理',
|
||||
pkField: 'CompanyUUID',
|
||||
defaultColumns: () => [
|
||||
{ field: 'CompanyUUID', title: '公司UUID', width: 140, primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'CompanyName', title: '公司全称', width: 200, type: 'text' },
|
||||
{ field: 'CompanyShort', title: '公司简称', width: 120, type: 'text' },
|
||||
{ field: 'CompanyStatus', title: '状态', width: 70, type: 'select', options: [{value:0,label:'禁用'},{value:1,label:'启用'}] },
|
||||
{ field: 'ParentCompanyUUID', title: '上级公司', width: 140, type: 'text' },
|
||||
{ field: 'CreateTime', title: '创建时间', width: 160, type: 'datetime', editable: false },
|
||||
],
|
||||
onView: (row) => {
|
||||
console.log('[company] onView row:', row);
|
||||
const server = new URLSearchParams(window.location.search).get('server');
|
||||
let url = `/pages/Company/company-detail.html?CompanyUUID=${encodeURIComponent(row.CompanyUUID || '')}`;
|
||||
if (server && server !== 'gvsds-master') url += `&server=${encodeURIComponent(server)}`;
|
||||
GERP.Navigate(url, row.CompanyName || '公司详情');
|
||||
},
|
||||
});
|
||||
|
||||
page.init();
|
||||
</script>
|
||||
@@ -0,0 +1,152 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js?v=20260625d"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<a href="javascript:void(0)" class="cp-back-btn" onclick="goBack()"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-sitemap icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">部门详情</span>
|
||||
</h1>
|
||||
<button class="GERPBtn Primary" onclick="handleEdit()" style="margin-left:auto;"><i class="fas fa-edit"></i> 编辑</button>
|
||||
</div>
|
||||
<div class="cp-container" id="detailContainer" style="overflow:auto;">
|
||||
<div class="cp-loading"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const currentServer = CompanyUtils.getServer();
|
||||
const deptUUID = new URLSearchParams(window.location.search).get('DeptUUID');
|
||||
|
||||
CompanyUtils.setPageTitle('部门详情');
|
||||
|
||||
function goBack() {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
GERP.Navigate('/pages/Company/department.html' + (currentServer !== 'gvsds-master' ? `?server=${encodeURIComponent(currentServer)}` : ''), '部门管理');
|
||||
}
|
||||
}
|
||||
|
||||
let currentData = null;
|
||||
let empTable = null;
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const containerEl = document.getElementById('detailContainer');
|
||||
|
||||
if (!deptUUID) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-triangle" style="margin-right:6px;"></i> 缺少 DeptUUID 参数,无法加载部门详情。</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dataResp = await fetch(buildApiUrl('/API/FormAPI/Get/Department', { DeptUUID: deptUUID, PageSize: '1' }), { credentials: 'include' });
|
||||
const dataResult = await dataResp.json();
|
||||
if (dataResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 加载失败: ${CompanyUtils.esc(dataResult.msg || '未知错误')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = dataResult.data || [];
|
||||
const data = Array.isArray(list) ? (list.find(d => d.DeptUUID === deptUUID) || list[0]) : list;
|
||||
if (!data) {
|
||||
containerEl.innerHTML = `<div class="cp-error">未找到部门数据</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
currentData = data;
|
||||
CompanyUtils.setPageTitle(data.DeptName || '部门详情');
|
||||
|
||||
// 解析 UUID 字段为名称
|
||||
const uuidMap = {};
|
||||
if (data.ParentDeptUUID) uuidMap.parentDept = { table: 'Department', uuids: [data.ParentDeptUUID] };
|
||||
const resolved = await CompanyUtils.resolveUUIDs(uuidMap);
|
||||
|
||||
// 渲染基本信息 + 表格容器
|
||||
containerEl.innerHTML = `
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-sitemap"></i> 基本信息</h3>
|
||||
<div class="cp-info-grid">
|
||||
<div class="cp-info-item"><div class="label">部门名称</div><div class="value">${CompanyUtils.esc(data.DeptName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">部门状态</div><div class="value">${CompanyUtils.statusTag(data.DeptStatus)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">上级部门</div><div class="value">${CompanyUtils.esc(resolved.parentDept?.[data.ParentDeptUUID] || data.ParentDeptUUID) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">排序</div><div class="value">${data.DeptSort ?? '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">创建时间</div><div class="value">${CompanyUtils.formatTime(data.DeptCreateTime)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-users"></i> 部门员工</h3>
|
||||
<div id="emp-table-container" style="height:400px;"></div>
|
||||
</div>`;
|
||||
|
||||
// 初始化 TableEngine 实例
|
||||
initEmployeeTable();
|
||||
} catch (e) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 网络错误: ${CompanyUtils.esc(e.message)}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function initEmployeeTable() {
|
||||
empTable = new TableEngine({
|
||||
container: '#emp-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserRole',
|
||||
columns: [
|
||||
{ field: 'UserRoleUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('UserUUID', '用户名', 'User', { editable: false }),
|
||||
CompanyUtils.epColumn('RoleUUID', '角色名', 'Role'),
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{ value: 0, label: '员工' }, { value: 1, label: '负责人' }] },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserRole', { DeptUUID: deptUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserRole'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserRole/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserRole/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserRole/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/employee-detail.html?UserUUID=${encodeURIComponent(row.UserUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.UserUUID_label || '员工详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑按钮:弹出编辑对话框 */
|
||||
async function handleEdit() {
|
||||
if (!currentData) return;
|
||||
CompanyUtils.showEditDialog({
|
||||
tableName: 'Department',
|
||||
data: currentData,
|
||||
onSave: () => {
|
||||
if (window.GERPUI && typeof window.GERPUI.ShowToast === 'function') {
|
||||
window.GERPUI.ShowToast({ message: '保存成功', type: 'success' });
|
||||
}
|
||||
init();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
@@ -0,0 +1,39 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-sitemap icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">部门管理</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="cp-container" id="TableContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const page = new CompanyTablePage({
|
||||
tableName: 'Department',
|
||||
title: '部门管理',
|
||||
pkField: 'DeptUUID',
|
||||
defaultColumns: () => [
|
||||
{ field: 'DeptUUID', title: '部门UUID', width: 140, primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'DeptName', title: '部门名称', width: 160, type: 'text' },
|
||||
{ field: 'DeptSort', title: '排序', width: 80, type: 'number' },
|
||||
{ field: 'DeptStatus', title: '状态', width: 80, type: 'select', options: [{value:0,label:'禁用'},{value:1,label:'启用'}] },
|
||||
{ field: 'CompanyUUID', title: '所属公司', width: 160, type: 'text', editable: false, hideInForm: true },
|
||||
{ field: 'ParentDeptUUID', title: '上级部门', width: 160, type: 'text' },
|
||||
{ field: 'CreateTime', title: '创建时间', width: 160, type: 'datetime', editable: false },
|
||||
],
|
||||
onView: (row) => {
|
||||
console.log('[department] onView row:', row);
|
||||
const server = new URLSearchParams(window.location.search).get('server');
|
||||
let url = `/pages/Company/department-detail.html?DeptUUID=${encodeURIComponent(row.DeptUUID || '')}`;
|
||||
if (server && server !== 'gvsds-master') url += `&server=${encodeURIComponent(server)}`;
|
||||
GERP.Navigate(url, row.DeptName || '部门详情');
|
||||
},
|
||||
});
|
||||
|
||||
page.init();
|
||||
</script>
|
||||
@@ -0,0 +1,187 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js?v=20260625d"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<a href="javascript:void(0)" class="cp-back-btn" onclick="goBack()"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-user-circle icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">员工详情</span>
|
||||
</h1>
|
||||
<button class="GERPBtn Primary" onclick="handleEdit()" style="margin-left:auto;"><i class="fas fa-edit"></i> 编辑</button>
|
||||
</div>
|
||||
<div class="cp-container" id="detailContainer" style="overflow:auto;">
|
||||
<div class="cp-loading"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const currentServer = CompanyUtils.getServer();
|
||||
const userUUID = new URLSearchParams(window.location.search).get('UserUUID');
|
||||
|
||||
CompanyUtils.setPageTitle('员工详情');
|
||||
|
||||
function goBack() {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
GERP.Navigate('/pages/system/users.html' + (currentServer !== 'gvsds-master' ? `?server=${encodeURIComponent(currentServer)}` : ''), '用户管理');
|
||||
}
|
||||
}
|
||||
|
||||
let currentData = null;
|
||||
let roleTable = null;
|
||||
let deptTable = null;
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const containerEl = document.getElementById('detailContainer');
|
||||
|
||||
if (!userUUID) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-triangle" style="margin-right:6px;"></i> 缺少 UserUUID 参数,无法加载员工详情。</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dataResp = await fetch(buildApiUrl('/API/FormAPI/Get/User', { UserUUID: userUUID, PageSize: '1' }), { credentials: 'include' });
|
||||
const dataResult = await dataResp.json();
|
||||
if (dataResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 加载失败: ${CompanyUtils.esc(dataResult.msg || '未知错误')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = dataResult.data || [];
|
||||
const data = Array.isArray(list) ? (list.find(u => u.UserUUID === userUUID) || list[0]) : list;
|
||||
if (!data) {
|
||||
containerEl.innerHTML = `<div class="cp-error">未找到用户数据</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
currentData = data;
|
||||
CompanyUtils.setPageTitle(data.UserName || '员工详情');
|
||||
|
||||
// 渲染基本信息 + 表格容器
|
||||
containerEl.innerHTML = `
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-user-circle"></i> 基本信息</h3>
|
||||
<div class="cp-info-grid">
|
||||
<div class="cp-info-item"><div class="label">用户名</div><div class="value">${CompanyUtils.esc(data.UserName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">真实姓名</div><div class="value">${CompanyUtils.esc(data.UserRealName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">邮箱</div><div class="value">${CompanyUtils.esc(data.UserEmail) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">电话</div><div class="value">${CompanyUtils.esc(data.UserTele) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">账号状态</div><div class="value">${CompanyUtils.statusTag(data.UserAccountLicense)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">是否员工</div><div class="value">${data.IsStaff ? '<span style="color:#166534;">是</span>' : '<span style="color:#991b1b;">否</span>'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">创建时间</div><div class="value">${CompanyUtils.formatTime(data.UserCreateTime)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-shield-alt"></i> 角色与组织</h3>
|
||||
<div id="role-table-container" style="height:400px;"></div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-sitemap"></i> 部门关联</h3>
|
||||
<div id="dept-table-container" style="height:400px;"></div>
|
||||
</div>`;
|
||||
|
||||
// 初始化 TableEngine 实例
|
||||
initRoleTable();
|
||||
initDeptTable();
|
||||
} catch (e) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 网络错误: ${CompanyUtils.esc(e.message)}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function initRoleTable() {
|
||||
roleTable = new TableEngine({
|
||||
container: '#role-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserRole',
|
||||
columns: [
|
||||
{ field: 'UserRoleUUID', title: '角色UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('RoleUUID', '角色名', 'Role'),
|
||||
CompanyUtils.epColumn('CompanyUUID', '公司', 'Company', { editable: false, hideInForm: true }),
|
||||
CompanyUtils.epColumn('DeptUUID', '部门', 'Department'),
|
||||
CompanyUtils.epColumn('WorkgroupUUID', '工作组', 'Workgroup'),
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{ value: 0, label: '组员' }, { value: 1, label: '组长' }] },
|
||||
{ field: 'RoleUUID_RoleStatus', title: '角色状态', type: 'select', options: [{ value: 0, label: '禁用' }, { value: 1, label: '启用' }], editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserRole', { UserUUID: userUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserRole'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserRole/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserRole/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserRole/<id>'),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function initDeptTable() {
|
||||
deptTable = new TableEngine({
|
||||
container: '#dept-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserDept',
|
||||
columns: [
|
||||
{ field: 'UserDeptUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('DeptUUID', '部门名称', 'Department'),
|
||||
{ field: 'IsMainDept', title: '主部门', type: 'select', options: [{ value: 0, label: '兼职' }, { value: 1, label: '主部门' }] },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserDept', { UserUUID: userUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserDept'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserDept/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserDept/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserDept/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/department-detail.html?DeptUUID=${encodeURIComponent(row.DeptUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.DeptUUID_label || '部门详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑按钮:弹出编辑对话框 */
|
||||
async function handleEdit() {
|
||||
if (!currentData) return;
|
||||
CompanyUtils.showEditDialog({
|
||||
tableName: 'User',
|
||||
data: currentData,
|
||||
onSave: () => {
|
||||
if (window.GERPUI && typeof window.GERPUI.ShowToast === 'function') {
|
||||
window.GERPUI.ShowToast({ message: '保存成功', type: 'success' });
|
||||
}
|
||||
init();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
@@ -0,0 +1,145 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js?v=20260625d"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<a href="javascript:void(0)" class="cp-back-btn" onclick="goBack()"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-users-cog icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">工作组详情</span>
|
||||
</h1>
|
||||
<button class="GERPBtn Primary" onclick="handleEdit()" style="margin-left:auto;"><i class="fas fa-edit"></i> 编辑</button>
|
||||
</div>
|
||||
<div class="cp-container" id="detailContainer" style="overflow:auto;">
|
||||
<div class="cp-loading"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const currentServer = CompanyUtils.getServer();
|
||||
const workgroupUUID = new URLSearchParams(window.location.search).get('WorkgroupUUID');
|
||||
|
||||
CompanyUtils.setPageTitle('工作组详情');
|
||||
|
||||
function goBack() {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
GERP.Navigate('/pages/Company/workgroup.html' + (currentServer !== 'gvsds-master' ? `?server=${encodeURIComponent(currentServer)}` : ''), '工作组管理');
|
||||
}
|
||||
}
|
||||
|
||||
let currentData = null;
|
||||
let memberTable = null;
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const containerEl = document.getElementById('detailContainer');
|
||||
|
||||
if (!workgroupUUID) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-triangle" style="margin-right:6px;"></i> 缺少 WorkgroupUUID 参数,无法加载工作组详情。</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dataResp = await fetch(buildApiUrl('/API/FormAPI/Get/Workgroup', { WorkgroupUUID: workgroupUUID, PageSize: '1' }), { credentials: 'include' });
|
||||
const dataResult = await dataResp.json();
|
||||
if (dataResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 加载失败: ${CompanyUtils.esc(dataResult.msg || '未知错误')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = dataResult.data || [];
|
||||
const data = Array.isArray(list) ? (list.find(w => w.WorkgroupUUID === workgroupUUID) || list[0]) : list;
|
||||
if (!data) {
|
||||
containerEl.innerHTML = `<div class="cp-error">未找到工作组数据</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
currentData = data;
|
||||
CompanyUtils.setPageTitle(data.WorkgroupName || '工作组详情');
|
||||
|
||||
// 渲染基本信息 + 表格容器
|
||||
containerEl.innerHTML = `
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-users-cog"></i> 基本信息</h3>
|
||||
<div class="cp-info-grid">
|
||||
<div class="cp-info-item"><div class="label">工作组名称</div><div class="value">${CompanyUtils.esc(data.WorkgroupName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">工作组状态</div><div class="value">${CompanyUtils.statusTag(data.WorkgroupStatus)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">创建时间</div><div class="value">${CompanyUtils.formatTime(data.WorkgroupCreateTime)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-user-friends"></i> 工作组成员</h3>
|
||||
<div id="member-table-container" style="height:400px;"></div>
|
||||
</div>`;
|
||||
|
||||
// 初始化 TableEngine 实例
|
||||
initMemberTable();
|
||||
} catch (e) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 网络错误: ${CompanyUtils.esc(e.message)}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function initMemberTable() {
|
||||
memberTable = new TableEngine({
|
||||
container: '#member-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserRole',
|
||||
columns: [
|
||||
{ field: 'UserRoleUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('UserUUID', '用户名', 'User', { editable: false }),
|
||||
CompanyUtils.epColumn('RoleUUID', '角色名', 'Role'),
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{ value: 0, label: '组员' }, { value: 1, label: '组长' }] },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserRole', { WorkgroupUUID: workgroupUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserRole'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserRole/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserRole/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserRole/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/employee-detail.html?UserUUID=${encodeURIComponent(row.UserUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.UserUUID_label || '员工详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑按钮:弹出编辑对话框 */
|
||||
async function handleEdit() {
|
||||
if (!currentData) return;
|
||||
CompanyUtils.showEditDialog({
|
||||
tableName: 'Workgroup',
|
||||
data: currentData,
|
||||
onSave: () => {
|
||||
if (window.GERPUI && typeof window.GERPUI.ShowToast === 'function') {
|
||||
window.GERPUI.ShowToast({ message: '保存成功', type: 'success' });
|
||||
}
|
||||
init();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
@@ -0,0 +1,35 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-users-cog icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">工作组管理</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="cp-container" id="TableContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const page = new CompanyTablePage({
|
||||
tableName: 'Workgroup',
|
||||
title: '工作组管理',
|
||||
defaultColumns: () => [
|
||||
{ field: 'WorkgroupUUID', title: '工作组UUID', width: 140, primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'WorkgroupName', title: '工作组名称', width: 160, type: 'text' },
|
||||
{ field: 'WorkgroupEnglishName', title: '英文名称', width: 160, type: 'text' },
|
||||
{ field: 'WorkgroupIntroduction', title: '工作组介绍', width: 240, type: 'textarea' },
|
||||
],
|
||||
onView: (row) => {
|
||||
console.log('[workgroup] onView row:', row);
|
||||
const server = new URLSearchParams(window.location.search).get('server');
|
||||
let url = `/pages/Company/workgroup-detail.html?WorkgroupUUID=${encodeURIComponent(row.WorkgroupUUID || '')}`;
|
||||
if (server && server !== 'gvsds-master') url += `&server=${encodeURIComponent(server)}`;
|
||||
GERP.Navigate(url, row.WorkgroupName || '工作组详情');
|
||||
},
|
||||
});
|
||||
|
||||
page.init();
|
||||
</script>
|
||||
@@ -0,0 +1,261 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js?v=20260625d"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<a href="javascript:void(0)" class="cp-back-btn" onclick="goBack()"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-user-tag icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">角色详情</span>
|
||||
</h1>
|
||||
<span id="admin-badge" style="display:none;margin-left:8px;padding:2px 10px;border-radius:4px;background:#1e40af;color:#fff;font-size:12px;font-weight:600;"><i class="fas fa-shield-alt"></i> 特权模式</span>
|
||||
<button class="GERPBtn Primary" onclick="handleEdit()" style="margin-left:auto;"><i class="fas fa-edit"></i> 编辑</button>
|
||||
</div>
|
||||
<div class="cp-container" id="detailContainer" style="overflow:auto;">
|
||||
<div class="cp-loading"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const currentServer = CompanyUtils.getServer();
|
||||
const roleUUID = new URLSearchParams(window.location.search).get('RoleUUID');
|
||||
|
||||
CompanyUtils.setPageTitle('角色详情');
|
||||
|
||||
function goBack() {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
GERP.Navigate('/pages/system/roles.html' + (currentServer !== 'gvsds-master' ? `?server=${encodeURIComponent(currentServer)}` : ''), '角色管理');
|
||||
}
|
||||
}
|
||||
|
||||
let currentData = null;
|
||||
let userRoleTable = null;
|
||||
let permTable = null;
|
||||
let adminTable = null;
|
||||
let isAdminMode = false;
|
||||
|
||||
/** 检查当前用户是否具有管理员特权 */
|
||||
async function checkAdmin() {
|
||||
try {
|
||||
const resp = await fetch(buildApiUrl('/API/FormAPI/CheckAdmin'), { credentials: 'include' });
|
||||
const result = await resp.json();
|
||||
return result.code === 0 && result.data && result.data.is_admin;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
if (isAdminMode) allParams.admin_verify = '1';
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
function roleTypeText(t) {
|
||||
if (t === 0 || t === '0') return '组员';
|
||||
if (t === 1 || t === '1') return '组长';
|
||||
return '-';
|
||||
}
|
||||
|
||||
function assignScopeText(s) {
|
||||
if (s === 0 || s === '0') return '<span style="color:#166534;">全租户可分发</span>';
|
||||
if (s === 1 || s === '1') return '<span style="color:#1e40af;">指定公司可分发</span>';
|
||||
if (s === 2 || s === '2') return '<span style="color:#6d28d9;">指定部门可分发</span>';
|
||||
return '-';
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const containerEl = document.getElementById('detailContainer');
|
||||
|
||||
if (!roleUUID) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-triangle" style="margin-right:6px;"></i> 缺少 RoleUUID 参数,无法加载角色详情。</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
// 先检查管理员特权
|
||||
isAdminMode = await checkAdmin();
|
||||
const adminBadge = document.getElementById('admin-badge');
|
||||
if (isAdminMode) {
|
||||
adminBadge.style.display = 'inline-block';
|
||||
}
|
||||
|
||||
try {
|
||||
const dataResp = await fetch(buildApiUrl('/API/FormAPI/Get/Role', { RoleUUID: roleUUID, PageSize: '1' }), { credentials: 'include' });
|
||||
const dataResult = await dataResp.json();
|
||||
if (dataResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 加载失败: ${CompanyUtils.esc(dataResult.msg || '未知错误')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = dataResult.data || [];
|
||||
const data = Array.isArray(list) ? (list.find(r => r.RoleUUID === roleUUID) || list[0]) : list;
|
||||
if (!data) {
|
||||
containerEl.innerHTML = `<div class="cp-error">未找到角色数据</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
currentData = data;
|
||||
CompanyUtils.setPageTitle(data.RoleName || '角色详情');
|
||||
|
||||
const isolationNotice = isAdminMode
|
||||
? `<div style="margin-bottom:12px;padding:8px 12px;background:#eff6ff;border:1px solid #bfdbfe;border-radius:4px;color:#1e40af;font-size:13px;"><i class="fas fa-info-circle"></i> 特权模式:显示该角色在所有公司的关联记录(无公司隔离)</div>`
|
||||
: `<div style="margin-bottom:12px;padding:8px 12px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:4px;color:#6b7280;font-size:13px;"><i class="fas fa-info-circle"></i> 仅显示当前公司数据。如需查看所有公司记录,需管理员特权。</div>`;
|
||||
|
||||
containerEl.innerHTML = `
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-user-tag"></i> 基本信息</h3>
|
||||
<div class="cp-info-grid">
|
||||
<div class="cp-info-item"><div class="label">角色名称</div><div class="value">${CompanyUtils.esc(data.RoleName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">角色类型</div><div class="value">${roleTypeText(data.RoleType)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">角色状态</div><div class="value">${CompanyUtils.statusTag(data.RoleStatus)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">分配范围</div><div class="value">${assignScopeText(data.AssignScope)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">角色描述</div><div class="value">${CompanyUtils.esc(data.RoleDesc) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">创建时间</div><div class="value">${CompanyUtils.formatTime(data.CreateTime)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
${isolationNotice}
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-users"></i> 关联用户</h3>
|
||||
<div id="userrole-table-container" style="height:400px;"></div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-key"></i> 角色权限</h3>
|
||||
<div id="perm-table-container" style="height:400px;"></div>
|
||||
<div style="margin-top:8px;font-size:12px;color:#6b7280;"><i class="fas fa-info-circle"></i> 添加 <code>admin:super</code> 权限可使该角色成为超级管理员</div>
|
||||
</div>`;
|
||||
|
||||
initUserRoleTable();
|
||||
initPermTable();
|
||||
initAdminTable();
|
||||
} catch (e) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 网络错误: ${CompanyUtils.esc(e.message)}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function initUserRoleTable() {
|
||||
userRoleTable = new TableEngine({
|
||||
container: '#userrole-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserRole',
|
||||
columns: [
|
||||
{ field: 'UserRoleUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('UserUUID', '用户名', 'User'),
|
||||
CompanyUtils.epColumn('CompanyUUID', '公司', 'Company', { editable: false }),
|
||||
CompanyUtils.epColumn('DeptUUID', '部门', 'Department'),
|
||||
CompanyUtils.epColumn('WorkgroupUUID', '工作组', 'Workgroup'),
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{ value: 0, label: '组员' }, { value: 1, label: '组长' }] },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserRole', { RoleUUID: roleUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserRole'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserRole/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserRole/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserRole/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/system/user-detail.html?UserUUID=${encodeURIComponent(row.UserUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.UserUUID_label || '用户详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function initPermTable() {
|
||||
permTable = new TableEngine({
|
||||
container: '#perm-table-container',
|
||||
height: '400px',
|
||||
tableName: 'RolePermission',
|
||||
columns: [
|
||||
{ field: 'RolePermUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('PermUUID', '权限名称', 'Permission'),
|
||||
CompanyUtils.epColumn('CompanyUUID', '公司', 'Company', { editable: false, hideInForm: true }),
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/RolePermission', { RoleUUID: roleUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/RolePermission'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/RolePermission/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/RolePermission/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/RolePermission/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
// 权限没有独立详情页,暂不跳转
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function initAdminTable() {
|
||||
adminTable = new TableEngine({
|
||||
container: '#admin-table-container',
|
||||
height: '200px',
|
||||
tableName: 'RoleAdmin',
|
||||
columns: [
|
||||
{ field: 'RoleAdminUUID', title: '主键UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'RoleUUID', title: '角色UUID', editable: false, hideInForm: true },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/RoleAdmin', { RoleUUID: roleUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/RoleAdmin'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/RoleAdmin/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/RoleAdmin/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/RoleAdmin/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
// 无需跳转
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑按钮:弹出编辑对话框 */
|
||||
async function handleEdit() {
|
||||
if (!currentData) return;
|
||||
CompanyUtils.showEditDialog({
|
||||
tableName: 'Role',
|
||||
data: currentData,
|
||||
extraParams: isAdminMode ? { admin_verify: '1' } : {},
|
||||
onSave: () => init()
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
@@ -0,0 +1,118 @@
|
||||
<style>
|
||||
.GERPPage { padding: 24px; max-width: 1400px; margin: 0 auto; height: 100%; display: flex; flex-direction: column; box-sizing: border-box; }
|
||||
.role-page { padding: 20px; flex: 1; min-height: 0; display: flex; flex-direction: column; box-sizing: border-box; }
|
||||
.role-header { display: flex; align-items: center; margin-bottom: 16px; gap: 12px; flex-shrink: 0; }
|
||||
.role-header h1 { margin: 0; flex: 1; }
|
||||
.role-container { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
|
||||
</style>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="role-page">
|
||||
<div class="role-header">
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-user-tag icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">角色管理</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="role-container" id="TableContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const currentServer = urlParams.get('server') || 'gvsds-master';
|
||||
let _tableInstance = null;
|
||||
let _isAdminMode = false;
|
||||
|
||||
GERP.SetTitle(currentServer === 'gvsds-master' ? '角色管理' : `${currentServer} 角色管理`);
|
||||
document.getElementById('page-title').textContent = currentServer === 'gvsds-master' ? '角色管理' : `${currentServer} - 角色管理`;
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
if (_isAdminMode) allParams.admin_verify = '1';
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
async function checkAdmin() {
|
||||
try {
|
||||
const resp = await fetch(buildApiUrl('/API/FormAPI/CheckAdmin'), { credentials: 'include' });
|
||||
const result = await resp.json();
|
||||
return result.code === 0 && result.data && result.data.is_admin;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function initTable() {
|
||||
const containerEl = document.getElementById('TableContainer');
|
||||
|
||||
// 先检查管理员特权
|
||||
_isAdminMode = await checkAdmin();
|
||||
|
||||
try {
|
||||
let columns;
|
||||
if (currentServer === 'gvsds-master') {
|
||||
const columnsResp = await fetch(buildApiUrl('/API/FormAPI/Columns/Role'), { credentials: 'include' });
|
||||
const columnsResult = await columnsResp.json();
|
||||
if (columnsResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div style="color:var(--DangerColor);padding:40px;text-align:center;">加载列配置失败: ${columnsResult.msg || ''}</div>`;
|
||||
return;
|
||||
}
|
||||
columns = columnsResult.data || [];
|
||||
} else {
|
||||
columns = getDefaultColumns();
|
||||
}
|
||||
|
||||
_tableInstance = new TableEngine({
|
||||
container: '#TableContainer',
|
||||
tableName: 'Role',
|
||||
columns: columns,
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
columnDistribution: 'equal',
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/Role'),
|
||||
add: buildApiUrl('/API/FormAPI/Add/Role'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/Role/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/Role/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/Role/<id>'),
|
||||
columns: buildApiUrl('/API/FormAPI/Columns/Role'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/system/role-detail.html?RoleUUID=${encodeURIComponent(row.RoleUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.RoleName || '角色详情');
|
||||
},
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('initTable error:', error);
|
||||
containerEl.innerHTML = `<div style="color:var(--DangerColor);padding:40px;text-align:center;">初始化失败: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultColumns() {
|
||||
return [
|
||||
{ field: 'RoleUUID', title: '角色UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'RoleName', title: '角色名称', type: 'text' },
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{value:0,label:'组员'},{value:1,label:'组长'},{value:2,label:'其他'}] },
|
||||
{ field: 'RoleStatus', title: '状态', type: 'select', options: [{value:0,label:'禁用'},{value:1,label:'启用'}] },
|
||||
{ field: 'RoleDesc', title: '描述', type: 'text' },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
];
|
||||
}
|
||||
|
||||
initTable();
|
||||
</script>
|
||||
@@ -0,0 +1,227 @@
|
||||
<script src="/assets/gerp/CompanyCommon.js?v=20260625d"></script>
|
||||
|
||||
<div class="GERPPage">
|
||||
<div class="cp-page">
|
||||
<div class="cp-header">
|
||||
<a href="javascript:void(0)" class="cp-back-btn" onclick="goBack()"><i class="fas fa-arrow-left"></i> 返回</a>
|
||||
<h1 class="PageTitle">
|
||||
<i class="fas fa-user-circle icon-primary icon-left-lg"></i>
|
||||
<span id="page-title">用户详情</span>
|
||||
</h1>
|
||||
<span id="admin-badge" style="display:none;margin-left:8px;padding:2px 10px;border-radius:4px;background:#1e40af;color:#fff;font-size:12px;font-weight:600;"><i class="fas fa-shield-alt"></i> 特权模式</span>
|
||||
<button class="GERPBtn Primary" onclick="handleEdit()" style="margin-left:auto;"><i class="fas fa-edit"></i> 编辑</button>
|
||||
</div>
|
||||
<div class="cp-container" id="detailContainer" style="overflow:auto;">
|
||||
<div class="cp-loading"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const currentServer = CompanyUtils.getServer();
|
||||
const userUUID = new URLSearchParams(window.location.search).get('UserUUID');
|
||||
|
||||
CompanyUtils.setPageTitle('用户详情');
|
||||
|
||||
function goBack() {
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
GERP.Navigate('/pages/system/users.html' + (currentServer !== 'gvsds-master' ? `?server=${encodeURIComponent(currentServer)}` : ''), '用户管理');
|
||||
}
|
||||
}
|
||||
|
||||
let currentData = null;
|
||||
let roleTable = null;
|
||||
let deptTable = null;
|
||||
let isAdminMode = false;
|
||||
|
||||
/** 检查当前用户是否具有管理员特权 */
|
||||
async function checkAdmin() {
|
||||
try {
|
||||
const resp = await fetch(buildApiUrl('/API/FormAPI/CheckAdmin'), { credentials: 'include' });
|
||||
const result = await resp.json();
|
||||
return result.code === 0 && result.data && result.data.is_admin;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildApiUrl(path, params = {}) {
|
||||
const allParams = {};
|
||||
if (currentServer !== 'gvsds-master') allParams.server = currentServer;
|
||||
if (isAdminMode) allParams.admin_verify = '1';
|
||||
Object.assign(allParams, params);
|
||||
const qs = new URLSearchParams(allParams).toString();
|
||||
return qs ? `${path}?${qs}` : path;
|
||||
}
|
||||
|
||||
function genderText(g) {
|
||||
if (g === 1 || g === '1') return '男';
|
||||
if (g === 0 || g === '0') return '女';
|
||||
return '-';
|
||||
}
|
||||
|
||||
function yesNoText(val) {
|
||||
return val ? '<span style="color:#166534;">是</span>' : '<span style="color:#991b1b;">否</span>';
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const containerEl = document.getElementById('detailContainer');
|
||||
|
||||
if (!userUUID) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-triangle" style="margin-right:6px;"></i> 缺少 UserUUID 参数,无法加载用户详情。</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
// 先检查管理员特权,决定是否启用无隔离模式
|
||||
isAdminMode = await checkAdmin();
|
||||
const adminBadge = document.getElementById('admin-badge');
|
||||
if (isAdminMode) {
|
||||
adminBadge.style.display = 'inline-block';
|
||||
}
|
||||
|
||||
try {
|
||||
const dataResp = await fetch(buildApiUrl('/API/FormAPI/Get/User', { UserUUID: userUUID, PageSize: '1' }), { credentials: 'include' });
|
||||
const dataResult = await dataResp.json();
|
||||
if (dataResult.code !== 0) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 加载失败: ${CompanyUtils.esc(dataResult.msg || '未知错误')}</div>`;
|
||||
return;
|
||||
}
|
||||
const list = dataResult.data || [];
|
||||
const data = Array.isArray(list) ? (list.find(u => u.UserUUID === userUUID) || list[0]) : list;
|
||||
if (!data) {
|
||||
containerEl.innerHTML = `<div class="cp-error">未找到用户数据</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
currentData = data;
|
||||
CompanyUtils.setPageTitle(data.UserName || '用户详情');
|
||||
|
||||
// 渲染基本信息 + 表格容器
|
||||
const isolationNotice = isAdminMode
|
||||
? `<div style="margin-bottom:12px;padding:8px 12px;background:#eff6ff;border:1px solid #bfdbfe;border-radius:4px;color:#1e40af;font-size:13px;"><i class="fas fa-info-circle"></i> 特权模式:显示该用户在所有公司、所有部门的关联记录(无公司隔离)</div>`
|
||||
: `<div style="margin-bottom:12px;padding:8px 12px;background:#f9fafb;border:1px solid #e5e7eb;border-radius:4px;color:#6b7280;font-size:13px;"><i class="fas fa-info-circle"></i> 仅显示当前公司数据。如需查看所有公司记录,需管理员特权。</div>`;
|
||||
|
||||
containerEl.innerHTML = `
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-user-circle"></i> 基本信息</h3>
|
||||
<div class="cp-info-grid">
|
||||
<div class="cp-info-item"><div class="label">用户名</div><div class="value">${CompanyUtils.esc(data.UserName) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">邮箱</div><div class="value">${CompanyUtils.esc(data.UserEmail) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">电话</div><div class="value">${CompanyUtils.esc(data.UserTele) || '-'}</div></div>
|
||||
<div class="cp-info-item"><div class="label">性别</div><div class="value">${genderText(data.UserGender)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">账号状态</div><div class="value">${CompanyUtils.statusTag(data.UserAccountLicense)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">是否员工</div><div class="value">${yesNoText(data.IsStaff)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">是否超级用户</div><div class="value">${yesNoText(data.IsSuperuser)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">创建时间</div><div class="value">${CompanyUtils.formatTime(data.UserCreateTime)}</div></div>
|
||||
<div class="cp-info-item"><div class="label">最后登录</div><div class="value">${CompanyUtils.formatTime(data.UserLastLoginDate)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
${isolationNotice}
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-shield-alt"></i> 角色与组织</h3>
|
||||
<div id="role-table-container" style="height:400px;"></div>
|
||||
</div>
|
||||
<div class="cp-detail-section">
|
||||
<h3><i class="fas fa-sitemap"></i> 部门关联</h3>
|
||||
<div id="dept-table-container" style="height:400px;"></div>
|
||||
</div>`;
|
||||
|
||||
// 初始化 TableEngine 实例
|
||||
initRoleTable();
|
||||
initDeptTable();
|
||||
} catch (e) {
|
||||
containerEl.innerHTML = `<div class="cp-error"><i class="fas fa-exclamation-circle" style="margin-right:6px;"></i> 网络错误: ${CompanyUtils.esc(e.message)}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
function initRoleTable() {
|
||||
roleTable = new TableEngine({
|
||||
container: '#role-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserRole',
|
||||
columns: [
|
||||
{ field: 'UserRoleUUID', title: '角色UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('RoleUUID', '角色名', 'Role'),
|
||||
CompanyUtils.epColumn('CompanyUUID', '公司', 'Company', { editable: false }),
|
||||
CompanyUtils.epColumn('DeptUUID', '部门', 'Department'),
|
||||
CompanyUtils.epColumn('WorkgroupUUID', '工作组', 'Workgroup'),
|
||||
{ field: 'RoleType', title: '角色类型', type: 'select', options: [{ value: 0, label: '组员' }, { value: 1, label: '组长' }] },
|
||||
{ field: 'CreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserRole', { UserUUID: userUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserRole'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserRole/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserRole/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserRole/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/system/role-detail.html?RoleUUID=${encodeURIComponent(row.RoleUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.RoleUUID_label || '角色详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function initDeptTable() {
|
||||
deptTable = new TableEngine({
|
||||
container: '#dept-table-container',
|
||||
height: '400px',
|
||||
tableName: 'UserDept',
|
||||
columns: [
|
||||
{ field: 'UserDeptUUID', title: '关联UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
CompanyUtils.epColumn('DeptUUID', '部门名称', 'Department'),
|
||||
{ field: 'IsMainDept', title: '主部门', type: 'select', options: [{ value: 0, label: '兼职' }, { value: 1, label: '主部门' }] },
|
||||
],
|
||||
data: [],
|
||||
pageSize: 20,
|
||||
columnDistribution: 'equal',
|
||||
showPagination: true,
|
||||
showCheckbox: true,
|
||||
editable: true,
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
api: {
|
||||
get: buildApiUrl('/API/FormAPI/Get/UserDept', { UserUUID: userUUID }),
|
||||
add: buildApiUrl('/API/FormAPI/Add/UserDept'),
|
||||
edit: buildApiUrl('/API/FormAPI/Modify/UserDept/<id>'),
|
||||
modify: buildApiUrl('/API/FormAPI/ModifyItem/UserDept/<id>'),
|
||||
delete: buildApiUrl('/API/FormAPI/Delete/UserDept/<id>'),
|
||||
},
|
||||
onView: (row) => {
|
||||
let url = `/pages/Company/department-detail.html?DeptUUID=${encodeURIComponent(row.DeptUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.DeptUUID_label || '部门详情');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑按钮:弹出编辑对话框 */
|
||||
async function handleEdit() {
|
||||
if (!currentData) return;
|
||||
CompanyUtils.showEditDialog({
|
||||
tableName: 'User',
|
||||
data: currentData,
|
||||
extraParams: isAdminMode ? { admin_verify: '1' } : {},
|
||||
onSave: () => init()
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
@@ -4,24 +4,6 @@
|
||||
.user-header { display: flex; align-items: center; margin-bottom: 16px; gap: 12px; flex-shrink: 0; }
|
||||
.user-header h1 { margin: 0; flex: 1; }
|
||||
.user-container { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
|
||||
|
||||
/* 详情面板内样式 */
|
||||
.user-detail-section { margin-bottom: 20px; }
|
||||
.user-detail-section h3 { font-size: 14px; font-weight: 600; margin: 0 0 10px 0; padding-bottom: 8px; border-bottom: 1px solid var(--BorderColor); display: flex; align-items: center; gap: 8px; }
|
||||
.user-detail-section h3 i { color: var(--PrimaryColor); }
|
||||
.user-info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; }
|
||||
.user-info-item { font-size: 13px; }
|
||||
.user-info-item .label { color: var(--TextSecondary); font-size: 12px; }
|
||||
.user-info-item .value { color: var(--TextPrimary); font-weight: 500; word-break: break-all; }
|
||||
.user-detail-list { list-style: none; padding: 0; margin: 0; }
|
||||
.user-detail-list li { padding: 8px 12px; border: 1px solid var(--BorderColor); border-radius: 6px; margin-bottom: 6px; font-size: 13px; display: flex; align-items: center; gap: 8px; }
|
||||
.user-detail-list li .item-name { font-weight: 500; flex: 1; }
|
||||
.user-detail-list li .item-desc { color: var(--TextSecondary); font-size: 12px; }
|
||||
.user-order-item { display: flex; align-items: center; gap: 12px; width: 100%; }
|
||||
.user-order-item .order-no { font-weight: 600; color: var(--PrimaryColor); }
|
||||
.user-order-item .order-amount { font-weight: 600; }
|
||||
.user-order-item .order-status { margin-left: auto; }
|
||||
.user-empty { text-align: center; padding: 20px; color: var(--TextSecondary); font-size: 13px; }
|
||||
</style>
|
||||
|
||||
<div class="GERPPage">
|
||||
@@ -40,9 +22,7 @@
|
||||
<script>
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const currentServer = urlParams.get('server') || 'gvsds-master';
|
||||
const API_BASE = '/api/gerp/users/';
|
||||
let _tableInstance = null;
|
||||
let _drawerClose = null;
|
||||
|
||||
GERP.SetTitle(currentServer === 'gvsds-master' ? '用户管理' : `${currentServer} 用户管理`);
|
||||
document.getElementById('page-title').textContent = currentServer === 'gvsds-master' ? '用户管理' : `${currentServer} - 用户管理`;
|
||||
@@ -78,17 +58,20 @@
|
||||
striped: true,
|
||||
hoverable: true,
|
||||
bordered: true,
|
||||
columnDistribution: 'equal',
|
||||
api: {
|
||||
get: `${API_BASE}list/?server=${currentServer}`,
|
||||
get: '/API/FormAPI/Get/User',
|
||||
add: '/API/FormAPI/Add/User',
|
||||
edit: '/API/FormAPI/Modify/User/<id>',
|
||||
modify: '/API/FormAPI/ModifyItem/User/<id>',
|
||||
delete: '/API/FormAPI/Delete/User/<id>',
|
||||
columns: '/API/FormAPI/Columns/User'
|
||||
},
|
||||
onRowClick: (row) => openDetail(row.UserUUID),
|
||||
onDelete: (row) => {},
|
||||
onEdit: (row) => {},
|
||||
onView: (row) => {
|
||||
let url = `/pages/system/user-detail.html?UserUUID=${encodeURIComponent(row.UserUUID || '')}`;
|
||||
if (currentServer !== 'gvsds-master') url += `&server=${encodeURIComponent(currentServer)}`;
|
||||
GERP.Navigate(url, row.UserName || '用户详情');
|
||||
},
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
@@ -99,181 +82,16 @@
|
||||
|
||||
function getDefaultColumns() {
|
||||
return [
|
||||
{ field: 'UserUUID', title: '用户UUID', width: 140, primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'UserName', title: '用户名', width: 120, type: 'text' },
|
||||
{ field: 'UserEmail', title: '邮箱', width: 180, type: 'text' },
|
||||
{ field: 'UserTele', title: '电话', width: 120, type: 'text' },
|
||||
{ field: 'UserGender', title: '性别', width: 60, type: 'select', options: [{value:0,label:'女'},{value:1,label:'男'}] },
|
||||
{ field: 'UserAccountLicense', title: '状态', width: 70, type: 'select', options: [{value:0,label:'禁用'},{value:1,label:'启用'}] },
|
||||
{ field: 'UserCreateTime', title: '创建时间', width: 160, type: 'datetime', editable: false },
|
||||
{ field: 'UserLastLoginDate', title: '最后登录', width: 160, type: 'datetime', editable: false },
|
||||
{ field: 'UserUUID', title: '用户UUID', primaryKey: true, editable: false, hideInForm: true },
|
||||
{ field: 'UserName', title: '用户名', type: 'text' },
|
||||
{ field: 'UserEmail', title: '邮箱', type: 'text' },
|
||||
{ field: 'UserTele', title: '电话', type: 'text' },
|
||||
{ field: 'UserGender', title: '性别', type: 'select', options: [{value:0,label:'女'},{value:1,label:'男'}] },
|
||||
{ field: 'UserAccountLicense', title: '状态', type: 'select', options: [{value:0,label:'禁用'},{value:1,label:'启用'}] },
|
||||
{ field: 'UserCreateTime', title: '创建时间', type: 'datetime', editable: false },
|
||||
{ field: 'UserLastLoginDate', title: '最后登录', type: 'datetime', editable: false },
|
||||
];
|
||||
}
|
||||
|
||||
// === 用户详情抽屉 ===
|
||||
|
||||
function openDetail(userUUID) {
|
||||
if (_drawerClose) _drawerClose();
|
||||
|
||||
WaitForUI((UI) => {
|
||||
const { element, close } = UI.OpenDrawer({
|
||||
title: '加载中...',
|
||||
placement: 'right',
|
||||
width: '520px',
|
||||
content: '<div style="text-align:center;padding:40px;color:var(--TextSecondary);"><i class="fas fa-spinner fa-spin"></i> 加载中...</div>',
|
||||
});
|
||||
_drawerClose = close;
|
||||
|
||||
const params = new URLSearchParams({ server: currentServer, UserUUID: userUUID });
|
||||
fetch(`${API_BASE}detail/?${params}`, { credentials: 'include' })
|
||||
.then(resp => resp.json())
|
||||
.then(json => {
|
||||
if (json.code !== 0) {
|
||||
element.querySelector('.GERPDrawerBody').innerHTML = `<div class="user-empty" style="color:var(--DangerColor);">${json.msg || '加载失败'}</div>`;
|
||||
return;
|
||||
}
|
||||
const d = json.data;
|
||||
element.querySelector('.GERPDrawerTitle').textContent = d.User.UserName || userUUID;
|
||||
element.querySelector('.GERPDrawerBody').innerHTML = renderDetail(d);
|
||||
})
|
||||
.catch(e => {
|
||||
element.querySelector('.GERPDrawerBody').innerHTML = `<div class="user-empty" style="color:var(--DangerColor);">网络错误: ${e.message}</div>`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function WaitForUI(callback) {
|
||||
if (window.GERPUI && typeof window.GERPUI.OpenDrawer === 'function') {
|
||||
callback(window.GERPUI);
|
||||
return;
|
||||
}
|
||||
document.addEventListener('GERPUIReady', () => callback(window.GERPUI), { once: true });
|
||||
}
|
||||
|
||||
function renderDetail(d) {
|
||||
const u = d.User;
|
||||
let html = '';
|
||||
|
||||
html += `<div class="user-detail-section">
|
||||
<h3><i class="fas fa-id-card"></i> 基本信息</h3>
|
||||
<div class="user-info-grid">
|
||||
<div class="user-info-item"><div class="label">用户名</div><div class="value">${esc(u.UserName)}</div></div>
|
||||
<div class="user-info-item"><div class="label">邮箱</div><div class="value">${esc(u.UserEmail) || '-'}</div></div>
|
||||
<div class="user-info-item"><div class="label">电话</div><div class="value">${esc(u.UserTele) || '-'}</div></div>
|
||||
<div class="user-info-item"><div class="label">性别</div><div class="value">${genderText(u.UserGender)}</div></div>
|
||||
<div class="user-info-item"><div class="label">状态</div><div class="value">${statusTag(u.UserAccountLicense)}</div></div>
|
||||
<div class="user-info-item"><div class="label">职位状态</div><div class="value">${u.UserPositionStatus === 1 ? '在职' : '离职'}</div></div>
|
||||
<div class="user-info-item"><div class="label">创建时间</div><div class="value">${formatTime(u.UserCreateTime)}</div></div>
|
||||
<div class="user-info-item"><div class="label">最后登录</div><div class="value">${formatTime(u.UserLastLoginDate)}</div></div>
|
||||
<div class="user-info-item"><div class="label">UUID</div><div class="value" style="font-size:11px;font-family:monospace;">${esc(u.UserUUID)}</div></div>
|
||||
<div class="user-info-item"><div class="label">标签</div><div class="value">${u.IsSuperuser ? '<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:#fef3c7;color:#92400e;">超级用户</span> ' : ''}${u.IsStaff ? '<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:#dbeafe;color:#1e40af;">员工</span>' : ''}</div></div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="user-detail-section">
|
||||
<h3><i class="fas fa-shield-alt"></i> 角色 (${d.Roles.length}) <a href="javascript:void(0)" onclick="openTable('Role')" style="font-size:12px;font-weight:400;margin-left:auto;">管理</a></h3>`;
|
||||
if (d.Roles.length === 0) {
|
||||
html += `<div class="user-empty">暂无角色</div>`;
|
||||
} else {
|
||||
html += `<ul class="user-detail-list">`;
|
||||
d.Roles.forEach(r => {
|
||||
html += `<li>
|
||||
<i class="fas fa-user-tag" style="color:var(--PrimaryColor);"></i>
|
||||
<span class="item-name">${esc(r.RoleName)}</span>
|
||||
${r.CompanyName ? `<span class="item-desc">${esc(r.CompanyName)}${r.CompanyShort ? ` (${esc(r.CompanyShort)})` : ''}</span>` : ''}
|
||||
${assignScopeTag(r.AssignScope)}
|
||||
${r.RoleStatus === 1 ? '<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:#dcfce7;color:#166534;">启用</span>' : '<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:#fee2e2;color:#991b1b;">禁用</span>'}
|
||||
</li>`;
|
||||
});
|
||||
html += `</ul>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
|
||||
html += `<div class="user-detail-section">
|
||||
<h3><i class="fas fa-key"></i> 权限 (${d.Permissions.length}) <a href="javascript:void(0)" onclick="openTable('Permission')" style="font-size:12px;font-weight:400;margin-left:auto;">管理</a></h3>`;
|
||||
if (d.Permissions.length === 0) {
|
||||
html += `<div class="user-empty">暂无权限</div>`;
|
||||
} else {
|
||||
html += `<ul class="user-detail-list">`;
|
||||
d.Permissions.forEach(p => {
|
||||
html += `<li>
|
||||
<i class="fas fa-lock" style="color:#f59e0b;"></i>
|
||||
<span class="item-name">${esc(p.PermName)}</span>
|
||||
${p.PermCategory ? `<span style="display:inline-block;padding:2px 6px;border-radius:4px;font-size:10px;background:#f3f4f6;color:#6b7280;">${esc(p.PermCategory)}</span>` : ''}
|
||||
<span class="item-desc" style="font-family:monospace;font-size:11px;">${esc(p.PermCode)}</span>
|
||||
</li>`;
|
||||
});
|
||||
html += `</ul>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
|
||||
html += `<div class="user-detail-section">
|
||||
<h3><i class="fas fa-receipt"></i> 订单 (${d.Orders.length}) <a href="javascript:void(0)" onclick="openTable('Order')" style="font-size:12px;font-weight:400;margin-left:auto;">管理</a></h3>`;
|
||||
if (d.Orders.length === 0) {
|
||||
html += `<div class="user-empty">暂无订单</div>`;
|
||||
} else {
|
||||
html += `<ul class="user-detail-list">`;
|
||||
d.Orders.forEach(o => {
|
||||
html += `<li>
|
||||
<div class="user-order-item">
|
||||
<i class="fas fa-file-invoice" style="color:#10b981;"></i>
|
||||
<span class="order-no">${esc(o.OrderNO)}</span>
|
||||
<span class="item-name">${esc(o.OrderTitle)}</span>
|
||||
<span class="order-amount">${o.Currency} ${o.PayAmount}</span>
|
||||
<span class="order-status">${orderStatusText(o.OrderStatus)}</span>
|
||||
</div>
|
||||
</li>`;
|
||||
});
|
||||
html += `</ul>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
// === 工具函数 ===
|
||||
|
||||
function openTable(tableName) {
|
||||
if (currentServer === 'gvsds-master') {
|
||||
GERP.Navigate(`/pages/system/dbtable.html?table=${encodeURIComponent(tableName)}`, tableName);
|
||||
} else {
|
||||
GERP.Navigate(`/pages/system/sub-dbtable.html?server=${encodeURIComponent(currentServer)}&table=${encodeURIComponent(tableName)}`, `${currentServer} / ${tableName}`);
|
||||
}
|
||||
}
|
||||
|
||||
function esc(s) { if (s == null) return ''; const d = document.createElement('div'); d.textContent = String(s); return d.innerHTML; }
|
||||
|
||||
function assignScopeTag(scope) {
|
||||
const map = {
|
||||
0: { label: '全租户', bg: '#ede9fe', color: '#6d28d9' },
|
||||
1: { label: '公司级', bg: '#dbeafe', color: '#1e40af' },
|
||||
2: { label: '部门级', bg: '#fef3c7', color: '#92400e' },
|
||||
};
|
||||
const s = map[scope];
|
||||
if (!s) return '';
|
||||
return `<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:${s.bg};color:${s.color};">${s.label}</span>`;
|
||||
}
|
||||
|
||||
function genderText(g) {
|
||||
if (g === 1 || g === '1') return '男';
|
||||
if (g === 0 || g === '0') return '女';
|
||||
return '未知';
|
||||
}
|
||||
|
||||
function statusTag(license) {
|
||||
if (license === 1 || license === '1') return '<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:#dcfce7;color:#166534;">启用</span>';
|
||||
return '<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:#fee2e2;color:#991b1b;">禁用</span>';
|
||||
}
|
||||
|
||||
function formatTime(t) {
|
||||
if (!t) return '-';
|
||||
try { const d = new Date(t + (t.endsWith('Z') ? '' : 'Z')); return d.toLocaleString(); } catch { return t; }
|
||||
}
|
||||
|
||||
function orderStatusText(s) {
|
||||
const map = { 0:'待确认', 1:'已确认', 2:'已支付', 3:'处理中', 4:'已完成', 5:'已取消', 6:'退款中', 7:'已退款', 8:'已关闭' };
|
||||
return map[s] || String(s);
|
||||
}
|
||||
|
||||
initTable();
|
||||
</script>
|
||||
Reference in new issue
Block a user