首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,661 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<div class="border-b border-slate-200 px-6 py-4 bg-slate-50">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="font-semibold text-slate-800 flex items-center gap-2">
|
||||
<i class="fas fa-file-alt text-purple-500"></i> 简历管理
|
||||
</h3>
|
||||
<p class="text-sm text-slate-500 mt-1">管理所有用户的简历</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button onclick="openUploadDocumentModal()" class="btn btn-success">
|
||||
<i class="fas fa-upload"></i> 上传文档生成简历
|
||||
</button>
|
||||
<a href="{{$.AdminPath}}/resume/add" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> 添加简历
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-6 py-4 border-b border-slate-100 bg-white">
|
||||
<form id="filterForm" method="GET" action="{{$.AdminPath}}/resumes" class="flex flex-wrap items-center gap-3">
|
||||
<div class="flex-1 min-w-[11.25rem]">
|
||||
<input type="text" name="keyword" value="{{.FilterKeyword}}" placeholder="搜索姓名/路由..." class="w-full px-3 py-2 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
</div>
|
||||
<select name="user_id" class="px-3 py-2 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
<option value="">全部人员</option>
|
||||
{{ range .Users }}
|
||||
<option value="{{.ID}}" {{ if eq $.FilterUserID .ID }}selected{{ end }}>{{.Name}}({{.Username}})</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
<select name="template" class="px-3 py-2 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
<option value="">全部模板</option>
|
||||
<option value="modern" {{ if eq .FilterTemplate "modern" }}selected{{ end }}>现代商务</option>
|
||||
<option value="classic" {{ if eq .FilterTemplate "classic" }}selected{{ end }}>传统经典</option>
|
||||
<option value="tech" {{ if eq .FilterTemplate "tech" }}selected{{ end }}>科技极客</option>
|
||||
<option value="sidebar" {{ if eq .FilterTemplate "sidebar" }}selected{{ end }}>经典侧边栏</option>
|
||||
<option value="elegant" {{ if eq .FilterTemplate "elegant" }}selected{{ end }}>优雅轻奢</option>
|
||||
<option value="fresh" {{ if eq .FilterTemplate "fresh" }}selected{{ end }}>清新自然</option>
|
||||
<option value="minimalist" {{ if eq .FilterTemplate "minimalist" }}selected{{ end }}>极简风格</option>
|
||||
<option value="professional" {{ if eq .FilterTemplate "professional" }}selected{{ end }}>专业商务</option>
|
||||
</select>
|
||||
<select name="show_in_home" class="px-3 py-2 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
<option value="">首页展示</option>
|
||||
<option value="1" {{ if eq .FilterShowInHome "1" }}selected{{ end }}>已展示</option>
|
||||
<option value="0" {{ if eq .FilterShowInHome "0" }}selected{{ end }}>未展示</option>
|
||||
</select>
|
||||
<button type="submit" class="btn btn-primary btn-sm">
|
||||
<i class="fas fa-search"></i> 筛选
|
||||
</button>
|
||||
<a href="{{$.AdminPath}}/resumes" class="btn btn-secondary btn-sm">
|
||||
<i class="fas fa-redo"></i> 重置
|
||||
</a>
|
||||
</form>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr class="bg-slate-50 border-b border-slate-200">
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">姓名</th>
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">职位</th>
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">所属人员</th>
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">访问路由</th>
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">首页展示</th>
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600">更新时间</th>
|
||||
<th class="text-left px-6 py-4 text-sm font-semibold text-slate-600 actions-col">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .Resumes }}
|
||||
<tr class="border-b border-slate-100 hover:bg-slate-50 transition-colors">
|
||||
<td class="px-6 py-4">
|
||||
<span class="font-medium text-slate-800">{{.BasicInfo.Name}}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-slate-600">{{.BasicInfo.Title}}</td>
|
||||
<td class="px-6 py-4">
|
||||
{{ if .UserID }}
|
||||
{{ $user := index $.UserMap .UserID }}
|
||||
{{ if $user }}
|
||||
<span class="badge badge-success">{{$user.Name}}({{$user.Username}})</span>
|
||||
{{ else }}
|
||||
<span class="badge badge-warning">已失效</span>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<span class="badge badge-danger">未绑定</span>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td class="px-6 py-4 text-slate-600">/{{.Route}}</td>
|
||||
<td class="px-6 py-4">
|
||||
{{ if .ShowInHome }}
|
||||
<span class="badge badge-success">是</span>
|
||||
{{ else }}
|
||||
<span class="badge badge-slate">否</span>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td class="px-6 py-4 text-slate-500 text-sm">{{.UpdatedAt}}</td>
|
||||
<td class="px-6 py-4 actions-col">
|
||||
<div class="btn-group flex-wrap gap-1">
|
||||
<a href="/{{.Route}}" target="_blank" class="btn btn-info btn-xs" title="预览">
|
||||
<i class="fas fa-eye"></i> 预览
|
||||
</a>
|
||||
{{ if .UserID }}
|
||||
<a href="{{$.AdminPath}}/user/{{.UserID}}/resume/{{.ID}}/edit" class="btn btn-primary btn-xs" title="编辑">
|
||||
<i class="fas fa-edit"></i> 编辑
|
||||
</a>
|
||||
{{ else }}
|
||||
<a href="{{$.AdminPath}}/resume/{{.ID}}/edit" class="btn btn-primary btn-xs" title="编辑">
|
||||
<i class="fas fa-edit"></i> 编辑
|
||||
</a>
|
||||
{{ end }}
|
||||
<button onclick="toggleShowInHome('{{.ID}}', {{.ShowInHome}})" class="btn btn-warning btn-xs" title="{{if .ShowInHome}}取消展示{{else}}展示{{end}}">
|
||||
<i class="fas fa-home"></i> {{if .ShowInHome}}取消{{else}}展示{{end}}
|
||||
</button>
|
||||
<button onclick="updatePassword('{{.ID}}')" class="btn btn-secondary btn-xs" title="密码">
|
||||
<i class="fas fa-lock"></i> 密码
|
||||
</button>
|
||||
{{ if .UserID }}
|
||||
<button onclick="unbindUser('{{.ID}}')" class="btn btn-orange btn-xs" title="解绑人员">
|
||||
<i class="fas fa-unlink"></i> 解绑
|
||||
</button>
|
||||
{{ else }}
|
||||
<button onclick="bindUser('{{.ID}}')" class="btn btn-success btn-xs" title="绑定人员">
|
||||
<i class="fas fa-link"></i> 绑定
|
||||
</button>
|
||||
{{ end }}
|
||||
<button onclick="deleteResume('{{.ID}}')" class="btn btn-danger btn-xs" title="删除">
|
||||
<i class="fas fa-trash"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{ else }}
|
||||
<tr>
|
||||
<td colspan="7" class="px-6 py-12 text-center text-slate-500">
|
||||
<div class="w-16 h-16 mx-auto mb-4 rounded-full bg-slate-100 flex items-center justify-center">
|
||||
<i class="fas fa-file-alt text-slate-400 text-2xl"></i>
|
||||
</div>
|
||||
<p>暂无简历</p>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{ if gt .TotalPages 1 }}
|
||||
<div class="border-t border-slate-200 px-6 py-4 bg-slate-50 flex items-center justify-between">
|
||||
<div class="text-sm text-slate-500">共 {{ .Total }} 条记录,第 {{ .Page }} / {{ .TotalPages }} 页</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<a href="?page=1{{ .FilterQuery }}" class="btn btn-sm btn-slate {{ if eq .Page 1 }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page 1 }}onclick="return false"{{ end }}>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</a>
|
||||
<a href="?page={{ if eq .Page 1 }}1{{ else }}{{ subtract .Page 1 }}{{ end }}{{ .FilterQuery }}" class="btn btn-sm btn-slate {{ if eq .Page 1 }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page 1 }}onclick="return false"{{ end }}>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</a>
|
||||
{{ if gt .TotalPages 7 }}
|
||||
{{ if gt .Page 3 }}
|
||||
<a href="?page=1{{ .FilterQuery }}" class="btn btn-sm btn-slate">1</a>
|
||||
{{ if gt .Page 4 }}
|
||||
<span class="text-slate-400 text-sm">...</span>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ range $i := to 1 .TotalPages }}
|
||||
{{ if and (ge $i (subtract $.Page 2)) (le $i (add $.Page 2)) }}
|
||||
<a href="?page={{ $i }}{{ $.FilterQuery }}" class="btn btn-sm {{ if eq $i $.Page }}btn-primary{{ else }}btn-slate{{ end }}">{{ $i }}</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if gt .TotalPages 7 }}
|
||||
{{ if lt .Page (subtract .TotalPages 2) }}
|
||||
{{ if lt .Page (subtract .TotalPages 3) }}
|
||||
<span class="text-slate-400 text-sm">...</span>
|
||||
{{ end }}
|
||||
<a href="?page={{ .TotalPages }}{{ .FilterQuery }}" class="btn btn-sm btn-slate">{{ .TotalPages }}</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<a href="?page={{ if eq .Page .TotalPages }}{{ .TotalPages }}{{ else }}{{ add .Page 1 }}{{ end }}{{ .FilterQuery }}" class="btn btn-sm btn-slate {{ if eq .Page .TotalPages }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page .TotalPages }}onclick="return false"{{ end }}>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</a>
|
||||
<a href="?page={{ .TotalPages }}{{ .FilterQuery }}" class="btn btn-sm btn-slate {{ if eq .Page .TotalPages }}opacity-50 cursor-not-allowed{{ end }}" {{ if eq .Page .TotalPages }}onclick="return false"{{ end }}>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="modal" id="addResumeModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" id="addResumeModalTitle">
|
||||
<i class="fas fa-file-plus text-blue-500"></i> 添加简历
|
||||
</h3>
|
||||
<div class="modal-close" onclick="closeAddResumeModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="addResumeForm" onsubmit="saveResume(event)">
|
||||
<input type="hidden" id="resumeId">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="form-label">姓名</label>
|
||||
<input type="text" id="resumeName" class="form-input" required>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">职位</label>
|
||||
<input type="text" id="resumeTitle" class="form-input" required>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">访问路由(如 zhangsan)</label>
|
||||
<input type="text" id="resumeRoute" class="form-input" required>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">绑定人员(可选,可后续绑定)</label>
|
||||
<select id="resumeUserId" class="form-input">
|
||||
<option value="">不绑定人员</option>
|
||||
{{ range .Users }}
|
||||
<option value="{{.ID}}">{{.Name}} - {{.Username}}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button onclick="closeAddResumeModal()" class="btn btn-secondary">
|
||||
<i class="fas fa-times"></i> 取消
|
||||
</button>
|
||||
<button type="submit" form="addResumeForm" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> 保存
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" id="bindUserModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">
|
||||
<i class="fas fa-link text-green-500"></i> 绑定人员
|
||||
</h3>
|
||||
<div class="modal-close" onclick="closeBindUserModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-4">
|
||||
<label class="form-label">选择要绑定的人员</label>
|
||||
<select id="bindUserId" class="form-input">
|
||||
{{ range .Users }}
|
||||
<option value="{{.ID}}">{{.Name}} - {{.Username}}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button onclick="closeBindUserModal()" class="btn btn-secondary">
|
||||
<i class="fas fa-times"></i> 取消
|
||||
</button>
|
||||
<button onclick="confirmBindUser()" class="btn btn-primary">
|
||||
<i class="fas fa-check"></i> 确认绑定
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" id="passwordModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">
|
||||
<i class="fas fa-lock text-yellow-500"></i> 设置访问密码
|
||||
</h3>
|
||||
<div class="modal-close" onclick="closePasswordModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="form-label">访问密码(留空则取消密码保护)</label>
|
||||
<input type="password" id="resumePassword" class="form-input" placeholder="请输入密码">
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">确认密码</label>
|
||||
<input type="password" id="resumePasswordConfirm" class="form-input" placeholder="请再次输入密码">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button onclick="closePasswordModal()" class="btn btn-secondary">
|
||||
<i class="fas fa-times"></i> 取消
|
||||
</button>
|
||||
<button onclick="confirmUpdatePassword()" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> 保存
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" id="uploadDocumentModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">
|
||||
<i class="fas fa-upload text-green-500"></i> 上传文档生成简历
|
||||
</h3>
|
||||
<div class="modal-close" onclick="closeUploadDocumentModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="uploadDocumentForm" enctype="multipart/form-data" onsubmit="uploadDocument(event)">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="form-label">选择文档</label>
|
||||
<div class="border-2 border-dashed border-slate-300 rounded-lg p-8 text-center hover:border-green-500 transition-colors" id="fileDropArea">
|
||||
<i class="fas fa-file-upload text-4xl text-slate-400 mb-4"></i>
|
||||
<p class="text-slate-600 mb-2">点击或拖拽文件到此处</p>
|
||||
<p class="text-sm text-slate-400">支持格式:PDF、DOCX、XLSX、MD、TXT</p>
|
||||
<input type="file" id="documentFile" name="file" accept=".pdf,.docx,.xlsx,.md,.txt" class="hidden" onchange="handleFileSelect(this)">
|
||||
</div>
|
||||
<div id="selectedFileInfo" class="mt-2 hidden">
|
||||
<div class="flex items-center gap-2 text-sm text-slate-600">
|
||||
<i class="fas fa-file"></i>
|
||||
<span id="selectedFileName"></span>
|
||||
<button type="button" onclick="clearFileSelection()" class="text-red-500 hover:text-red-700">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">绑定人员(可选)</label>
|
||||
<select id="documentUserId" class="form-input">
|
||||
<option value="">不绑定人员</option>
|
||||
{{ range .Users }}
|
||||
<option value="{{.ID}}">{{.Name}} - {{.Username}}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button onclick="closeUploadDocumentModal()" class="btn btn-secondary">
|
||||
<i class="fas fa-times"></i> 取消
|
||||
</button>
|
||||
<button type="submit" form="uploadDocumentForm" class="btn btn-success" id="uploadSubmitBtn">
|
||||
<i class="fas fa-upload"></i> 上传生成
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var currentBindResumeId = '';
|
||||
var currentPasswordResumeId = '';
|
||||
|
||||
function openUploadDocumentModal() {
|
||||
document.getElementById('uploadDocumentModal').classList.add('active');
|
||||
document.getElementById('documentFile').value = '';
|
||||
document.getElementById('selectedFileInfo').classList.add('hidden');
|
||||
document.getElementById('selectedFileName').textContent = '';
|
||||
document.getElementById('uploadSubmitBtn').disabled = false;
|
||||
document.getElementById('uploadSubmitBtn').innerHTML = '<i class="fas fa-upload"></i> 上传生成';
|
||||
}
|
||||
|
||||
function closeUploadDocumentModal() {
|
||||
document.getElementById('uploadDocumentModal').classList.remove('active');
|
||||
}
|
||||
|
||||
document.getElementById('fileDropArea').addEventListener('click', function() {
|
||||
document.getElementById('documentFile').click();
|
||||
});
|
||||
|
||||
document.getElementById('fileDropArea').addEventListener('dragover', function(e) {
|
||||
e.preventDefault();
|
||||
this.classList.add('border-green-500');
|
||||
});
|
||||
|
||||
document.getElementById('fileDropArea').addEventListener('dragleave', function(e) {
|
||||
e.preventDefault();
|
||||
this.classList.remove('border-green-500');
|
||||
});
|
||||
|
||||
document.getElementById('fileDropArea').addEventListener('drop', function(e) {
|
||||
e.preventDefault();
|
||||
this.classList.remove('border-green-500');
|
||||
var files = e.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
document.getElementById('documentFile').files = files;
|
||||
handleFileSelect(document.getElementById('documentFile'));
|
||||
}
|
||||
});
|
||||
|
||||
function handleFileSelect(input) {
|
||||
if (input.files.length > 0) {
|
||||
var file = input.files[0];
|
||||
document.getElementById('selectedFileName').textContent = file.name;
|
||||
document.getElementById('selectedFileInfo').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function clearFileSelection() {
|
||||
document.getElementById('documentFile').value = '';
|
||||
document.getElementById('selectedFileInfo').classList.add('hidden');
|
||||
document.getElementById('selectedFileName').textContent = '';
|
||||
}
|
||||
|
||||
function uploadDocument(event) {
|
||||
event.preventDefault();
|
||||
var fileInput = document.getElementById('documentFile');
|
||||
var userId = document.getElementById('documentUserId').value;
|
||||
|
||||
if (fileInput.files.length === 0) {
|
||||
showCustomAlert('error', '错误', '请选择要上传的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
var file = fileInput.files[0];
|
||||
var allowedExts = ['.pdf', '.docx', '.xlsx', '.md', '.txt'];
|
||||
var fileExt = file.name.toLowerCase().substring(file.name.lastIndexOf('.'));
|
||||
|
||||
if (!allowedExts.includes(fileExt)) {
|
||||
showCustomAlert('error', '错误', '不支持的文件格式,支持:PDF、DOCX、XLSX、MD、TXT');
|
||||
return;
|
||||
}
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
if (userId) {
|
||||
formData.append('user_id', userId);
|
||||
}
|
||||
|
||||
var submitBtn = document.getElementById('uploadSubmitBtn');
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 处理中...';
|
||||
|
||||
fetch('/dashboard/api/resume/generate-from-document', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('HTTP ' + response.status);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(result => {
|
||||
console.log('API Response:', result);
|
||||
if (result.success) {
|
||||
showCustomAlert('success', '成功', result.message || '简历生成成功!');
|
||||
closeUploadDocumentModal();
|
||||
setTimeout(() => location.reload(), 2000);
|
||||
} else {
|
||||
showCustomAlert('error', '错误', result.message || '生成失败');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Upload error:', error);
|
||||
showCustomAlert('error', '错误', '上传失败: ' + error.message);
|
||||
})
|
||||
.finally(() => {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = '<i class="fas fa-upload"></i> 上传生成';
|
||||
});
|
||||
}
|
||||
|
||||
function openAddResumeModal() {
|
||||
document.getElementById('resumeId').value = '';
|
||||
document.getElementById('resumeName').value = '';
|
||||
document.getElementById('resumeTitle').value = '';
|
||||
document.getElementById('resumeRoute').value = '';
|
||||
document.getElementById('resumeUserId').value = '';
|
||||
document.getElementById('addResumeModal').classList.add('active');
|
||||
}
|
||||
|
||||
function closeAddResumeModal() {
|
||||
document.getElementById('addResumeModal').classList.remove('active');
|
||||
}
|
||||
|
||||
function saveResume(event) {
|
||||
event.preventDefault();
|
||||
const id = document.getElementById('resumeId').value;
|
||||
const name = document.getElementById('resumeName').value;
|
||||
const title = document.getElementById('resumeTitle').value;
|
||||
const route = document.getElementById('resumeRoute').value;
|
||||
const userId = document.getElementById('resumeUserId').value;
|
||||
|
||||
if (!name || !title || !route) {
|
||||
showCustomAlert('error', '错误', '请填写完整信息');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/dashboard/api/resume/create', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
user_id: userId,
|
||||
route: route,
|
||||
basic_info: {
|
||||
name: name,
|
||||
title: title
|
||||
}
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
showCustomAlert('success', '成功', '添加成功');
|
||||
closeAddResumeModal();
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else {
|
||||
showCustomAlert('error', '错误', '添加失败:' + (result.message || '未知错误'));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showCustomAlert('error', '错误', '添加失败');
|
||||
});
|
||||
}
|
||||
|
||||
function bindUser(resumeId) {
|
||||
currentBindResumeId = resumeId;
|
||||
document.getElementById('bindUserModal').classList.add('active');
|
||||
}
|
||||
|
||||
function closeBindUserModal() {
|
||||
document.getElementById('bindUserModal').classList.remove('active');
|
||||
currentBindResumeId = '';
|
||||
}
|
||||
|
||||
function confirmBindUser() {
|
||||
const userId = document.getElementById('bindUserId').value;
|
||||
if (!userId) {
|
||||
showCustomAlert('error', '错误', '请选择要绑定的人员');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/dashboard/api/resume/' + currentBindResumeId + '/user', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ user_id: userId })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
showCustomAlert('success', '成功', '绑定成功');
|
||||
closeBindUserModal();
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else {
|
||||
showCustomAlert('error', '错误', '绑定失败:' + (result.message || '未知错误'));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showCustomAlert('error', '错误', '绑定失败');
|
||||
});
|
||||
}
|
||||
|
||||
function unbindUser(resumeId) {
|
||||
showCustomConfirm('确认解绑', '确定要解绑该简历与人员的关联吗?', function(confirmed) {
|
||||
if (!confirmed) return;
|
||||
|
||||
fetch('/dashboard/api/resume/' + resumeId + '/user', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ user_id: '' })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
showCustomAlert('success', '成功', '解绑成功');
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else {
|
||||
showCustomAlert('error', '错误', '解绑失败:' + (result.message || '未知错误'));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showCustomAlert('error', '错误', '解绑失败');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function toggleShowInHome(resumeId, currentState) {
|
||||
fetch('/dashboard/api/resume/' + resumeId + '/show_in_home', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ show_in_home: !currentState })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success !== undefined) {
|
||||
showCustomAlert('success', '成功', currentState ? '已取消首页展示' : '已设置首页展示');
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else {
|
||||
showCustomAlert('error', '错误', '操作失败');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showCustomAlert('error', '错误', '操作失败');
|
||||
});
|
||||
}
|
||||
|
||||
function updatePassword(resumeId) {
|
||||
currentPasswordResumeId = resumeId;
|
||||
document.getElementById('resumePassword').value = '';
|
||||
document.getElementById('resumePasswordConfirm').value = '';
|
||||
document.getElementById('passwordModal').classList.add('active');
|
||||
}
|
||||
|
||||
function closePasswordModal() {
|
||||
document.getElementById('passwordModal').classList.remove('active');
|
||||
currentPasswordResumeId = '';
|
||||
}
|
||||
|
||||
function confirmUpdatePassword() {
|
||||
const password = document.getElementById('resumePassword').value;
|
||||
const confirmPassword = document.getElementById('resumePasswordConfirm').value;
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
showCustomAlert('error', '错误', '两次输入的密码不一致');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/dashboard/api/resume/' + currentPasswordResumeId + '/password', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password: password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
showCustomAlert('success', '成功', password ? '密码设置成功' : '密码已取消');
|
||||
closePasswordModal();
|
||||
} else {
|
||||
showCustomAlert('error', '错误', '设置失败:' + (result.message || '未知错误'));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showCustomAlert('error', '错误', '设置失败');
|
||||
});
|
||||
}
|
||||
|
||||
function deleteResume(resumeId) {
|
||||
showCustomConfirm('确认删除', '确定要删除该简历吗?此操作不可恢复。', function(confirmed) {
|
||||
if (!confirmed) return;
|
||||
|
||||
fetch('/dashboard/api/resume/' + resumeId, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
showCustomAlert('success', '成功', '删除成功');
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else {
|
||||
showCustomAlert('error', '错误', '删除失败:' + (result.message || '未知错误'));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
showCustomAlert('error', '错误', '删除失败');
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user