feat(notice): 通知公告功能增加附件上传和查看

- 在通知公告表单中添加附件上传功能
- 在通知公告列表中显示附件图标,点击可下载- 在通知公告查看页面展示附件列表,可点击下载
- 修改数据库,将 files 字段从 string 类型改为 text 类型
This commit is contained in:
2025-08-22 12:05:28 +08:00
parent 87c27c94b9
commit 272c887486
4 changed files with 171 additions and 3 deletions

View File

@@ -20,9 +20,16 @@
<label class="layui-form-item relative block">
<span class="help-label"><b>内容</b></span>
<textarea class="layui-textarea" name="content" style="width: 100%" placeholder="请输入内容">
{$vo.title|default=""}
{$vo.content|default=""}
</textarea>
</label>
<label class="layui-form-item relative block">
<span class="help-label"><b>附件</b></span>
<input type="hidden" name="files" value="{$vo.files|default=''}" class="layui-input" placeholder="请上传附件">
<a data-file='mut' data-type="*" data-field="files" class="layui-btn layui-btn-primary layui-btn-sm" style="margin-top: 5px;">上传文件</a>
<!-- 附件展示区域 -->
<div id="files-display" style="margin-top: 10px;"></div>
</label>
</fieldset>
<fieldset class="layui-bg-gray">
<legend><b class="layui-badge think-bg-violet">通知人</b></legend>
@@ -59,7 +66,80 @@
</div>
</form>
<script>
// 初始化附件上传功能
$('input[name="files"]').uploadFile();
// 附件处理功能
function renderFiles() {
var filesValue = $('input[name="files"]').val();
var displayDiv = $('#files-display');
displayDiv.empty();
if (filesValue && filesValue.trim()) {
var files = filesValue.split('|').filter(function(url) {
return url.trim() !== '';
});
if (files.length > 0) {
var html = '<div style="border: 1px solid #e6e6e6; border-radius: 4px; padding: 10px; background-color: #fafafa;">';
html += '<div style="font-weight: bold; margin-bottom: 8px; color: #666;">已上传附件 (' + files.length + '):</div>';
files.forEach(function(url, index) {
if (url.trim()) {
var fileName = '附件' + (index + 1);
// 尝试从URL参数中获取attname作为文件名
try {
var urlObj = new URL(url, window.location.origin);
var attname = urlObj.searchParams.get('attname');
if (attname) {
fileName = decodeURIComponent(attname);
} else {
// 如果没有attname参数,则使用URL路径的最后部分
fileName = url.split('/').pop() || '附件' + (index + 1);
}
} catch (e) {
// 如果URL解析失败,使用默认方式
fileName = url.split('/').pop() || '附件' + (index + 1);
}
html += '<div style="margin-bottom: 6px; padding: 6px; background-color: #fff; border: 1px solid #ddd; border-radius: 3px; display: flex; align-items: center; justify-content: space-between;">';
html += '<div style="flex: 1; display: flex; align-items: center;">';
html += '<i class="layui-icon layui-icon-file" style="margin-right: 8px; color: #1E9FFF;"></i>';
html += '<a href="' + url + '" target="_blank" style="color: #1E9FFF; text-decoration: none; word-break: break-all;">' + fileName + '</a>';
html += '</div>';
html += '<button type="button" class="layui-btn layui-btn-xs layui-btn-danger" onclick="removeFile(\'' + url + '\')" style="margin-left: 10px;">删除</button>';
html += '</div>';
}
});
html += '</div>';
displayDiv.html(html);
}
}
}
// 删除附件
function removeFile(urlToRemove) {
var filesValue = $('input[name="files"]').val();
if (filesValue) {
var files = filesValue.split('|').filter(function(url) {
return url.trim() !== '' && url !== urlToRemove;
});
$('input[name="files"]').val(files.join('|'));
renderFiles();
}
}
// 监听附件字段变化
$('input[name="files"]').on('input change', function() {
renderFiles();
});
$(function () {
// 页面加载时初始化附件显示
renderFiles();
layui.use(['form'], function () {
const Form = layui.form;
Form.on('checkbox(to_all)', function (data) {

View File

@@ -35,6 +35,35 @@
{ field: 'title', title: '标题', width: 200 },
{ field: 'type', title: '类型', width: 120 },
{ field: 'content', title: '内容' },
{ field: 'files', title: '附件', width: 120, align: 'center', templet: function(d){
if(d.files && d.files.trim()) {
var files = d.files.split('|').filter(function(url) {
return url.trim() !== '';
});
if(files.length > 0) {
var html = '';
files.forEach(function(url, index) {
if(url.trim()) {
var fileName = '附件' + (index + 1);
try {
var urlObj = new URL(url, window.location.origin);
var attname = urlObj.searchParams.get('attname');
if (attname) {
fileName = decodeURIComponent(attname);
} else {
fileName = url.split('/').pop() || '附件' + (index + 1);
}
} catch (e) {
fileName = url.split('/').pop() || '附件' + (index + 1);
}
html += '<i class="layui-icon layui-icon-file" style="color: #1E9FFF; cursor: pointer; margin-right: 5px;" title="' + fileName + '" onclick="window.open(\'' + url + '\', \'_blank\')"></i>';
}
});
return html;
}
}
return '';
}},
{ field: 'to', title: '通知用户' },
{ field: 'create_at', title: '创建时间', width: 200, sort: true },
{ fixed: "right", title: "操作", width: 200, align: "center", toolbar: "#ToolbarTpl"}

View File

@@ -4,8 +4,67 @@
<h1>{$vo.title}</h1>
<hr>
<p>{$vo.content}</p>
{notempty name='vo.files'}
<hr>
<div style="margin-top: 15px;">
<h4>附件下载:</h4>
<div id="files-display"></div>
</div>
{/notempty}
<hr>
<p style="text-align: right">通知时间:{$vo.create_at}</p>
<p style="text-align: right">通知人:{$vo.creator.name|default='通知人员'}</p>
</div>
</div>
</div>
<script>
$(function() {
// 渲染附件显示
function renderFiles() {
var filesValue = '{$vo.files|default=""}';
var displayDiv = $('#files-display');
displayDiv.empty();
if (filesValue && filesValue.trim()) {
var files = filesValue.split('|').filter(function(url) {
return url.trim() !== '';
});
if (files.length > 0) {
var html = '';
files.forEach(function(url, index) {
if (url.trim()) {
var fileName = '附件' + (index + 1);
// 尝试从URL参数中获取attname作为文件名
try {
var urlObj = new URL(url, window.location.origin);
var attname = urlObj.searchParams.get('attname');
if (attname) {
fileName = decodeURIComponent(attname);
} else {
// 如果没有attname参数,则使用URL路径的最后部分
fileName = url.split('/').pop() || '附件' + (index + 1);
}
} catch (e) {
// 如果URL解析失败,使用默认方式
fileName = url.split('/').pop() || '附件' + (index + 1);
}
html += '<div style="margin-bottom: 8px; padding: 8px; background-color: #f8f8f8; border: 1px solid #e6e6e6; border-radius: 4px; display: flex; align-items: center;">';
html += '<i class="layui-icon layui-icon-file" style="margin-right: 8px; color: #1E9FFF; font-size: 16px;"></i>';
html += '<a href="' + url + '" target="_blank" style="color: #1E9FFF; text-decoration: none; word-break: break-all;">' + fileName + '</a>';
html += '</div>';
}
});
displayDiv.html(html);
}
}
}
// 页面加载时初始化附件显示
renderFiles();
});
</script>

View File

@@ -71,7 +71,7 @@ class InstallNoticeTable extends Migrator
['title', 'string', ['limit' => 255, 'default' => NULL, 'null' => false, 'comment' => '标题']],
['type', 'string', ['limit' => 255, 'default' => NULL, 'null' => true, 'comment' => '类型']],
['content', 'text', ['default' => NULL, 'null' => true, 'comment' => '内容']],
['files', 'string', ['limit' => 255, 'default' => NULL, 'null' => true, 'comment' => '附件']],
['files', 'text', ['default' => NULL, 'null' => true, 'comment' => '附件']],
['create_at', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'null' => false, 'comment' => '']],
['create_by', 'integer', ['limit' => 11, 'default' => 0, 'null' => false, 'comment' => '创建人ID']],
['is_deleted', 'tinyinteger', ['limit' => 4, 'default' => 0, 'null' => false, 'comment' => '是否已删除']],