someone-oa/pc/settings-dict.html
2025-12-11 19:04:46 +08:00

471 lines
19 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>字典管理 - OA系统</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 统一布局样式 -->
<link rel="stylesheet" href="unified-layout.css">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
background: #f0f2f5;
overflow: hidden;
}
.layout-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.main-container {
flex: 1;
display: flex;
overflow: hidden;
}
.app-main {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
background: #f0f2f5;
}
.sidebar {
width: 210px;
background: #fff;
border-right: 1px solid #e6e6e6;
overflow-y: auto;
}
.menu-item { padding: 12px 24px; cursor: pointer; transition: background 0.3s; color: #303133; }
.menu-item:hover {
background: #ecf5ff;
color: #409EFF;
}
.menu-item.active { background: #409EFF; color: #fff; }
.content {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #fff;
margin: 10px;
border-radius: 4px;
}
.page-header {
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
}
.page-title { font-size: 20px; font-weight: 500; color: #303133; }
.search-form {
background: #fafafa;
padding: 16px;
border-radius: 4px;
margin-bottom: 16px;
}
.form-row {
display: flex;
gap: 16px;
margin-bottom: 12px;
}
.form-item {
flex: 1;
}
.form-input, .form-select {
width: 100%;
padding: 6px 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-size: 14px;
}
.btn {
padding: 6px 16px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s;
}
.btn-primary {
background: #409EFF;
color: white;
}
.btn-primary:hover {
background: #66b1ff;
}
.btn-default {
background: white;
color: #606266;
border: 1px solid #dcdfe6;
}
.btn-default:hover {
color: #409EFF;
border-color: #409EFF;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #f0f0f0;
}
th {
background: #fafafa;
font-weight: 500;
color: #303133;
}
.action-link {
color: #409EFF;
cursor: pointer;
margin-right: 12px;
}
.dict-content {
display: flex;
gap: 20px;
}
.dict-type-list {
width: 300px;
background: #fafafa;
border-radius: 4px;
padding: 16px;
}
.dict-type-item {
padding: 12px;
background: #fff;
border-radius: 4px;
margin-bottom: 8px;
cursor: pointer;
border: 1px solid #e6e6e6;
transition: all 0.3s;
}
.dict-type-item:hover {
border-color: #409EFF;
}
.dict-type-item.active {
background: #ecf5ff;
border-color: #409EFF;
}
.dict-type-name {
font-weight: 500;
color: #303133;
margin-bottom: 4px;
}
.dict-type-code {
font-size: 12px;
color: #909399;
}
.dict-data-table {
flex: 1;
}
</style>
<!-- Vue.js -->
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<!-- Element UI JS -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
<div class="layout-container">
<div class="main-container">
<div class="sidebar">
<div class="menu-item" onclick="window.location.href='settings-org.html'">组织架构</div>
<div class="menu-item" onclick="window.location.href='settings-user.html'">账号管理</div>
<div class="menu-item" onclick="window.location.href='settings-role.html'">权限配置</div>
<div class="menu-item" onclick="window.location.href='settings-workflow.html'">流程配置</div>
<div class="menu-item" onclick="window.location.href='settings-notice.html'">系统公告</div>
<div class="menu-item active" onclick="window.location.href='settings-dict.html'">字典管理</div>
<div class="menu-item" onclick="window.location.href='settings-param.html'">参数配置</div>
<div class="menu-item" onclick="window.location.href='settings-log.html'">操作日志</div>
</div>
<div class="app-main">
<div class="content">
<div class="page-header">
<div class="page-title">字典管理</div>
<button class="btn btn-primary" onclick="addDictType()">+ 新增字典类型</button>
</div>
<div class="dict-content">
<div class="dict-type-list">
<div class="dict-type-item active" onclick="selectDictType('service_type')">
<div class="dict-type-name">服务内容</div>
<div class="dict-type-code">service_type</div>
</div>
<div class="dict-type-item" onclick="selectDictType('project_status')">
<div class="dict-type-name">项目状态</div>
<div class="dict-type-code">project_status</div>
</div>
<div class="dict-type-item" onclick="selectDictType('output_type')">
<div class="dict-type-name">成果类型</div>
<div class="dict-type-code">output_type</div>
</div>
<div class="dict-type-item" onclick="selectDictType('approval_status')">
<div class="dict-type-name">审核状态</div>
<div class="dict-type-code">approval_status</div>
</div>
</div>
<div class="dict-data-table">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
<div style="font-weight: 500; color: #303133;">字典数据列表</div>
<button class="btn btn-primary" onclick="addDictData()">+ 新增</button>
</div>
<table>
<thead>
<tr>
<th>字典标签</th>
<th>字典值</th>
<th>排序</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- 字典数据将动态渲染 -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="common.js"></script>
<script>
// 字典数据
let dictData = {
'service_type': [
{ id: 1, label: '结算审计', value: '1', sort: 1, status: '启用' },
{ id: 2, label: '工程咨询', value: '2', sort: 2, status: '启用' },
{ id: 3, label: '跟踪审计', value: '3', sort: 3, status: '启用' }
],
'project_status': [
{ id: 4, label: '已立项', value: '1', sort: 1, status: '启用' },
{ id: 5, label: '投标中', value: '2', sort: 2, status: '启用' },
{ id: 6, label: '已签合同', value: '3', sort: 3, status: '启用' },
{ id: 7, label: '已启动', value: '4', sort: 4, status: '启用' }
],
'output_type': [
{ id: 8, label: '初稿', value: '1', sort: 1, status: '启用' },
{ id: 9, label: '对账', value: '2', sort: 2, status: '启用' },
{ id: 10, label: '最终成果', value: '3', sort: 3, status: '启用' }
],
'approval_status': [
{ id: 11, label: '待审核', value: '1', sort: 1, status: '启用' },
{ id: 12, label: '已通过', value: '2', sort: 2, status: '启用' },
{ id: 13, label: '已驳回', value: '3', sort: 3, status: '启用' }
]
};
let currentDictType = 'service_type';
function selectDictType(typeCode) {
document.querySelectorAll('.dict-type-item').forEach(item => {
item.classList.remove('active');
});
event.currentTarget.classList.add('active');
currentDictType = typeCode;
renderDictData();
}
function renderDictData() {
const data = dictData[currentDictType] || [];
const tbody = document.querySelector('.dict-data-table tbody');
if (!tbody) return;
tbody.innerHTML = data.map(item => `
<tr>
<td>${item.label}</td>
<td>${item.value}</td>
<td>${item.sort}</td>
<td>${item.status}</td>
<td>
<span class="action-link" onclick="editDictData(${item.id})">编辑</span>
<span class="action-link" onclick="deleteDictData(${item.id})" style="color: #f56c6c;">删除</span>
</td>
</tr>
`).join('');
}
function addDictType() {
const content = `
<form style="padding: 10px 0;">
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">字典类型名称 <span style="color: #f56c6c;">*</span></label>
<input type="text" id="dict-type-name" class="form-input" placeholder="如:服务内容" required>
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">字典类型编码 <span style="color: #f56c6c;">*</span></label>
<input type="text" id="dict-type-code" class="form-input" placeholder="如service_type" required>
</div>
</form>
`;
CommonUtils.createModal('新增字典类型', content, () => {
const name = document.getElementById('dict-type-name').value.trim();
const code = document.getElementById('dict-type-code').value.trim();
if (!name || !code) {
CommonUtils.showMessage('请填写必填项', 'error');
return false;
}
// 添加到字典类型列表实际应该添加到DOM
CommonUtils.showMessage('字典类型添加成功');
return true;
});
}
function addDictData() {
const content = `
<form style="padding: 10px 0;">
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">字典标签 <span style="color: #f56c6c;">*</span></label>
<input type="text" id="dict-label" class="form-input" placeholder="如:结算审计" required>
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">字典值 <span style="color: #f56c6c;">*</span></label>
<input type="text" id="dict-value" class="form-input" placeholder="如1" required>
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">排序</label>
<input type="number" id="dict-sort" class="form-input" placeholder="数字,越小越靠前" value="1">
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">状态</label>
<select id="dict-status" class="form-select">
<option>启用</option>
<option>禁用</option>
</select>
</div>
</form>
`;
CommonUtils.createModal('新增字典数据', content, () => {
const label = document.getElementById('dict-label').value.trim();
const value = document.getElementById('dict-value').value.trim();
const sort = parseInt(document.getElementById('dict-sort').value) || 1;
const status = document.getElementById('dict-status').value;
if (!label || !value) {
CommonUtils.showMessage('请填写必填项', 'error');
return false;
}
if (!dictData[currentDictType]) {
dictData[currentDictType] = [];
}
const maxId = dictData[currentDictType].length > 0
? Math.max(...dictData[currentDictType].map(d => d.id))
: 0;
dictData[currentDictType].push({
id: maxId + 1,
label: label,
value: value,
sort: sort,
status: status
});
// 按排序排序
dictData[currentDictType].sort((a, b) => a.sort - b.sort);
renderDictData();
localStorage.setItem('dictData', JSON.stringify(dictData));
CommonUtils.showMessage('字典数据添加成功');
return true;
});
}
function editDictData(id) {
const data = dictData[currentDictType] || [];
const item = data.find(d => d.id === id);
if (!item) return;
const content = `
<form style="padding: 10px 0;">
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">字典标签 <span style="color: #f56c6c;">*</span></label>
<input type="text" id="dict-label" class="form-input" value="${item.label}" required>
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">字典值 <span style="color: #f56c6c;">*</span></label>
<input type="text" id="dict-value" class="form-input" value="${item.value}" required>
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">排序</label>
<input type="number" id="dict-sort" class="form-input" value="${item.sort}">
</div>
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; color: #606266;">状态</label>
<select id="dict-status" class="form-select">
<option ${item.status === '启用' ? 'selected' : ''}>启用</option>
<option ${item.status === '禁用' ? 'selected' : ''}>禁用</option>
</select>
</div>
</form>
`;
CommonUtils.createModal('编辑字典数据', content, () => {
const label = document.getElementById('dict-label').value.trim();
const value = document.getElementById('dict-value').value.trim();
const sort = parseInt(document.getElementById('dict-sort').value) || 1;
const status = document.getElementById('dict-status').value;
if (!label || !value) {
CommonUtils.showMessage('请填写必填项', 'error');
return false;
}
Object.assign(item, { label, value, sort, status });
dictData[currentDictType].sort((a, b) => a.sort - b.sort);
renderDictData();
localStorage.setItem('dictData', JSON.stringify(dictData));
CommonUtils.showMessage('字典数据更新成功');
return true;
});
}
function deleteDictData(id) {
CommonUtils.createModal('确认删除', '确定要删除该字典数据吗?删除后无法恢复。', () => {
const data = dictData[currentDictType] || [];
const index = data.findIndex(d => d.id === id);
if (index > -1) {
data.splice(index, 1);
renderDictData();
localStorage.setItem('dictData', JSON.stringify(dictData));
CommonUtils.showMessage('字典数据已删除');
}
return true;
});
}
// 初始化
window.addEventListener('DOMContentLoaded', () => {
const saved = localStorage.getItem('dictData');
if (saved) {
try {
dictData = JSON.parse(saved);
} catch (e) {
console.error('加载字典数据失败', e);
}
}
renderDictData();
});
</script>
<script src="unified-layout.js"></script>
<script>
initUnifiedLayout('settings');
</script>
</body>
</html>