mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-11-10 13:00:49 +08:00
feat(notice): 我的消息与订阅设置个人域页面
This commit is contained in:
14
app/admin/controller/Notice.php
Normal file
14
app/admin/controller/Notice.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\service\annotation\ControllerAnnotation;
|
||||||
|
use base\admin\controller\NoticeBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ControllerAnnotation(title="消息中心", module="通用")
|
||||||
|
* Class Notice
|
||||||
|
*/
|
||||||
|
class Notice extends NoticeBase
|
||||||
|
{
|
||||||
|
}
|
||||||
267
extend/base/admin/controller/NoticeBase.php
Normal file
267
extend/base/admin/controller/NoticeBase.php
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace base\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\model\SystemNoticeTarget;
|
||||||
|
use app\admin\service\annotation\ControllerAnnotation;
|
||||||
|
use app\admin\service\annotation\NodeAnotation;
|
||||||
|
use app\common\controller\AdminController;
|
||||||
|
use app\common\service\NoticeService;
|
||||||
|
use think\App;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息中心(个人域).
|
||||||
|
*
|
||||||
|
* 我的站内信、订阅设置等个人数据动作,登录即可访问(auth=false)。
|
||||||
|
* 安全铁律:一切查询与写入强制 admin_id=当前会话管理员,杜绝越权。
|
||||||
|
*
|
||||||
|
* @ControllerAnnotation(title="消息中心", module="通用")
|
||||||
|
*/
|
||||||
|
class NoticeBase extends AdminController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 订阅设置矩阵提供的渠道(列).
|
||||||
|
*/
|
||||||
|
protected const SUBSCRIBE_CHANNELS = [
|
||||||
|
NoticeService::CHANNEL_INMAIL => '站内信',
|
||||||
|
NoticeService::CHANNEL_EMAIL => '邮箱',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param App $app
|
||||||
|
*/
|
||||||
|
public function __construct(App $app)
|
||||||
|
{
|
||||||
|
parent::__construct($app);
|
||||||
|
|
||||||
|
$this->model = new SystemNoticeTarget();
|
||||||
|
|
||||||
|
// 场景中文映射(mine 列表场景下拉/展示用)
|
||||||
|
$sceneOptions = [];
|
||||||
|
foreach (NoticeService::scenes() as $scene => $info) {
|
||||||
|
$sceneOptions[$scene] = $info['title'];
|
||||||
|
}
|
||||||
|
$this->assign('select_list_notice_scene', $sceneOptions, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的站内信列表.
|
||||||
|
* @NodeAnotation(title="我的消息", auth=false)
|
||||||
|
*/
|
||||||
|
public function mine()
|
||||||
|
{
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
if (input('selectFields')) {
|
||||||
|
return $this->selectList();
|
||||||
|
}
|
||||||
|
list($page, $limit, $where) = $this->buildTableParames();
|
||||||
|
$adminId = (int) $this->getAdminId();
|
||||||
|
$count = $this->model
|
||||||
|
->withJoin('notice', 'LEFT')
|
||||||
|
->where('system_notice_target.admin_id', $adminId)
|
||||||
|
->where('system_notice_target.channel', NoticeService::CHANNEL_INMAIL)
|
||||||
|
->where($where)
|
||||||
|
->count();
|
||||||
|
$list = $this->model
|
||||||
|
->withJoin('notice', 'LEFT')
|
||||||
|
->where('system_notice_target.admin_id', $adminId)
|
||||||
|
->where('system_notice_target.channel', NoticeService::CHANNEL_INMAIL)
|
||||||
|
->where($where)
|
||||||
|
->page($page, $limit)
|
||||||
|
->order($this->sort)
|
||||||
|
->select();
|
||||||
|
$data = [
|
||||||
|
'code' => 0,
|
||||||
|
'msg' => '',
|
||||||
|
'count' => $count,
|
||||||
|
'data' => $list,
|
||||||
|
];
|
||||||
|
|
||||||
|
return json($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息详情(进入即自动标记已读;先校验归属再标记,防越权).
|
||||||
|
* @NodeAnotation(title="消息详情", auth=false)
|
||||||
|
*/
|
||||||
|
public function read($id)
|
||||||
|
{
|
||||||
|
$adminId = (int) $this->getAdminId();
|
||||||
|
$row = $this->model
|
||||||
|
->withJoin('notice', 'LEFT')
|
||||||
|
->where('system_notice_target.id', (int) $id)
|
||||||
|
->where('system_notice_target.admin_id', $adminId)
|
||||||
|
->find();
|
||||||
|
if (empty($row)) {
|
||||||
|
$this->error('消息不存在或无权查看');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($row->read_time)) {
|
||||||
|
NoticeService::markRead([(int) $id], $adminId);
|
||||||
|
$row->read_time = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取平铺变量供模板渲染(notice 关联模型直接取值,规避模板链式访问歧义)
|
||||||
|
$notice = $row->notice;
|
||||||
|
$sceneTitleMap = [];
|
||||||
|
foreach (NoticeService::scenes() as $scene => $info) {
|
||||||
|
$sceneTitleMap[$scene] = $info['title'];
|
||||||
|
}
|
||||||
|
$msg = [
|
||||||
|
'id' => (int) $row->id,
|
||||||
|
'title' => (string) ($notice->title ?? '(通知已删除)'),
|
||||||
|
'scene_title' => $sceneTitleMap[(string) ($notice->scene ?? '')] ?? (string) ($notice->scene ?? '-'),
|
||||||
|
'content' => (string) ($notice->content ?? ''),
|
||||||
|
'read_time' => (int) $row->read_time,
|
||||||
|
'create_time' => (int) $row->create_time,
|
||||||
|
];
|
||||||
|
$this->assign('msg', $msg);
|
||||||
|
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记已读(批量).
|
||||||
|
* @NodeAnotation(title="标记已读", auth=false)
|
||||||
|
*/
|
||||||
|
public function markRead()
|
||||||
|
{
|
||||||
|
$this->checkPostRequest();
|
||||||
|
$targetIds = $this->request->post('target_ids');
|
||||||
|
if (empty($targetIds)) {
|
||||||
|
// 表格勾选批量提交(data-request+checkbox)的默认字段名是 id
|
||||||
|
$targetIds = $this->request->post('id');
|
||||||
|
}
|
||||||
|
$targetIds = is_array($targetIds) ? $targetIds : explode(',', (string) $targetIds);
|
||||||
|
$targetIds = array_values(array_filter(array_map('intval', $targetIds)));
|
||||||
|
|
||||||
|
$count = NoticeService::markRead($targetIds, (int) $this->getAdminId());
|
||||||
|
|
||||||
|
$this->success('已标记 ' . $count . ' 条消息为已读');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全部站内信标记已读.
|
||||||
|
* @NodeAnotation(title="全部标记已读", auth=false)
|
||||||
|
*/
|
||||||
|
public function markAllRead()
|
||||||
|
{
|
||||||
|
$this->checkPostRequest();
|
||||||
|
NoticeService::markAllRead((int) $this->getAdminId());
|
||||||
|
|
||||||
|
$this->success('已全部标记为已读');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未读站内信数(顶栏铃铛轮询接口).
|
||||||
|
* @NodeAnotation(title="未读消息数", auth=false)
|
||||||
|
*/
|
||||||
|
public function unreadCount()
|
||||||
|
{
|
||||||
|
$count = NoticeService::unreadCount((int) $this->getAdminId());
|
||||||
|
|
||||||
|
$this->success(null, ['count' => $count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅设置页(场景×渠道矩阵,纯渲染不写库).
|
||||||
|
*
|
||||||
|
* 无记录=默认订阅;locked 场景恒选中且置灰(必选)。
|
||||||
|
* @NodeAnotation(title="订阅设置", auth=false)
|
||||||
|
*/
|
||||||
|
public function subscribe()
|
||||||
|
{
|
||||||
|
$adminId = (int) $this->getAdminId();
|
||||||
|
|
||||||
|
$rows = Db::name('system_notice_subscribe')
|
||||||
|
->where('admin_id', $adminId)
|
||||||
|
->select();
|
||||||
|
$subscribeMap = [];
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$subscribeMap[$row['scene'] . '|' . $row['channel']] = (int) $row['status'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$matrix = [];
|
||||||
|
foreach (NoticeService::scenes() as $scene => $info) {
|
||||||
|
$locked = !empty($info['locked']);
|
||||||
|
$cells = [];
|
||||||
|
foreach (array_keys(self::SUBSCRIBE_CHANNELS) as $channel) {
|
||||||
|
$checked = $locked || ($subscribeMap[$scene . '|' . $channel] ?? 1) === 1;
|
||||||
|
$cells[] = [
|
||||||
|
'name' => 'matrix[' . $scene . '][' . $channel . ']',
|
||||||
|
'checked' => $checked ? 'checked' : '',
|
||||||
|
'disabled' => $locked ? 'disabled' : '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$matrix[] = [
|
||||||
|
'scene' => $scene,
|
||||||
|
'title' => $info['title'],
|
||||||
|
'locked' => $locked,
|
||||||
|
'cells' => $cells,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign('matrix', $matrix);
|
||||||
|
$this->assign('channels', self::SUBSCRIBE_CHANNELS);
|
||||||
|
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存订阅设置(POST matrix:逐场景×渠道 upsert).
|
||||||
|
*
|
||||||
|
* locked 场景直接忽略不入库(不可关闭语义,不报错);
|
||||||
|
* 仅写当前会话管理员的订阅记录。
|
||||||
|
* @NodeAnotation(title="保存订阅设置", auth=false)
|
||||||
|
*/
|
||||||
|
public function saveSubscribe()
|
||||||
|
{
|
||||||
|
$this->checkPostRequest();
|
||||||
|
$adminId = (int) $this->getAdminId();
|
||||||
|
$matrix = (array) $this->request->post('matrix');
|
||||||
|
if ($matrix === []) {
|
||||||
|
$this->error('没有需要保存的订阅设置');
|
||||||
|
}
|
||||||
|
|
||||||
|
$scenes = NoticeService::scenes();
|
||||||
|
$now = time();
|
||||||
|
|
||||||
|
foreach ($matrix as $scene => $channels) {
|
||||||
|
// 仅注册场景可保存;locked 场景忽略(不写任何记录)
|
||||||
|
if (!isset($scenes[$scene]) || !empty($scenes[$scene]['locked'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ((array) $channels as $channel => $value) {
|
||||||
|
if (!isset(self::SUBSCRIBE_CHANNELS[$channel])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$status = ((int) $value === 1) ? 1 : 0;
|
||||||
|
$row = Db::name('system_notice_subscribe')
|
||||||
|
->where('admin_id', $adminId)
|
||||||
|
->where('scene', (string) $scene)
|
||||||
|
->where('channel', (string) $channel)
|
||||||
|
->find();
|
||||||
|
if ($row) {
|
||||||
|
Db::name('system_notice_subscribe')
|
||||||
|
->where('id', $row['id'])
|
||||||
|
->update(['status' => $status, 'update_time' => $now]);
|
||||||
|
} else {
|
||||||
|
Db::name('system_notice_subscribe')->insert([
|
||||||
|
'admin_id' => $adminId,
|
||||||
|
'scene' => (string) $scene,
|
||||||
|
'channel' => (string) $channel,
|
||||||
|
'status' => $status,
|
||||||
|
'create_time' => $now,
|
||||||
|
'update_time' => $now,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->success('订阅设置已保存');
|
||||||
|
}
|
||||||
|
}
|
||||||
11
extend/base/admin/view/notice/_common.js
Normal file
11
extend/base/admin/view/notice/_common.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var init = {
|
||||||
|
tableElem: '#currentTable',
|
||||||
|
tableRenderId: 'currentTableRenderId',
|
||||||
|
indexUrl: 'notice/mine',
|
||||||
|
addUrl: '',
|
||||||
|
editUrl: '',
|
||||||
|
readUrl: 'notice/read',
|
||||||
|
deleteUrl: '',
|
||||||
|
exportUrl: '',
|
||||||
|
modifyUrl: '',
|
||||||
|
};
|
||||||
7
extend/base/admin/view/notice/mine.html
Normal file
7
extend/base/admin/view/notice/mine.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="layuimini-container">
|
||||||
|
<div class="layuimini-main">
|
||||||
|
<table id="currentTable" class="layui-table layui-hide"
|
||||||
|
lay-filter="currentTable">
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
99
extend/base/admin/view/notice/mine.js
Normal file
99
extend/base/admin/view/notice/mine.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
$(function(){
|
||||||
|
// HTML 转义(标题/场景等来自发送方输入,防注入)
|
||||||
|
var escapeHtml = function(text) {
|
||||||
|
return String(text).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,''');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 标题:关联 notice,通知主体被删时兜底;未读加粗强调
|
||||||
|
var titleTemplet = function(d) {
|
||||||
|
var notice = d.notice || {};
|
||||||
|
if (notice.title) {
|
||||||
|
var title = escapeHtml(notice.title);
|
||||||
|
if (d.read_time == 0) {
|
||||||
|
return '<strong>' + title + '</strong>';
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
return '<span style="color:#999">(通知已删除)#' + d.notice_id + '</span>';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 场景中文映射
|
||||||
|
var sceneTemplet = function(d) {
|
||||||
|
var notice = d.notice || {};
|
||||||
|
var map = ua.getDataBrage('select_list_notice_scene') || {};
|
||||||
|
var text = map[notice.scene] || notice.scene || '-';
|
||||||
|
return escapeHtml(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 未读/已读徽章(未读行同时以加粗标题高亮)
|
||||||
|
var readTemplet = function(d) {
|
||||||
|
if (d.read_time == 0) {
|
||||||
|
return '<span class="layui-badge">未读</span>';
|
||||||
|
}
|
||||||
|
return '<span class="layui-badge layui-bg-gray">已读</span>';
|
||||||
|
};
|
||||||
|
|
||||||
|
ua.table.render({
|
||||||
|
init: init,
|
||||||
|
toolbar: [
|
||||||
|
'refresh',
|
||||||
|
[{
|
||||||
|
text: '标记已读',
|
||||||
|
title: '确定将勾选的消息标记为已读?',
|
||||||
|
url: 'notice/mark_read',
|
||||||
|
method: 'request',
|
||||||
|
auth: 'notice/markRead',
|
||||||
|
class: 'layui-btn layui-btn-normal layui-btn-sm',
|
||||||
|
icon: 'fa fa-check',
|
||||||
|
checkbox: true,
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
text: '全部已读',
|
||||||
|
title: '确定将全部站内信标记为已读?',
|
||||||
|
url: 'notice/mark_all_read',
|
||||||
|
method: 'request',
|
||||||
|
auth: 'notice/markAllRead',
|
||||||
|
class: 'layui-btn layui-btn-warm layui-btn-sm',
|
||||||
|
icon: 'fa fa-check-square-o',
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
cols: [[
|
||||||
|
{type: 'checkbox'},
|
||||||
|
{field: 'id', title: 'ID', width: 80, search: false},
|
||||||
|
{field: 'title', title: '标题', minWidth: 220, fieldAlias: 'notice.title', templet: titleTemplet},
|
||||||
|
{field: 'scene', title: '场景', width: 110, align: 'center', search: 'select', searchOp: '=', selectList: ua.getDataBrage('select_list_notice_scene'), templet: sceneTemplet},
|
||||||
|
{field: 'read_time', title: '状态', width: 80, align: 'center', search: false, templet: readTemplet},
|
||||||
|
{field: 'create_time', title: '接收时间', width: 170, templet: ua.table.date, search: 'range'},
|
||||||
|
{
|
||||||
|
width: 90, title: '操作', fixed: 'right', templet: ua.table.tool,
|
||||||
|
operat: [[
|
||||||
|
{
|
||||||
|
class: 'layui-btn layui-btn-primary layui-btn-xs notice-mine-read-btn',
|
||||||
|
method: 'none',
|
||||||
|
field: 'id',
|
||||||
|
text: '查看',
|
||||||
|
title: '查看消息',
|
||||||
|
auth: 'notice/read',
|
||||||
|
url: init.readUrl,
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
]],
|
||||||
|
});
|
||||||
|
|
||||||
|
ua.listen();
|
||||||
|
|
||||||
|
// 查看:弹窗打开详情,关闭后刷新列表以更新未读状态
|
||||||
|
$(document).on('click', '.notice-mine-read-btn', function () {
|
||||||
|
var id = $(this).attr('data-id');
|
||||||
|
layui.layer.open({
|
||||||
|
type: 2,
|
||||||
|
title: '查看消息',
|
||||||
|
area: ['760px', '560px'],
|
||||||
|
content: ua.url(init.readUrl + '?id=' + id),
|
||||||
|
end: function () {
|
||||||
|
ua.table.reloadData(init.tableRenderId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
39
extend/base/admin/view/notice/read.html
Normal file
39
extend/base/admin/view/notice/read.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<div class="layuimini-container">
|
||||||
|
<div class="layuimini-main">
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-header">
|
||||||
|
<span style="font-size:16px;font-weight:bold;">{$msg.title}</span>
|
||||||
|
{if condition="$msg.read_time eq 0"}
|
||||||
|
<span class="layui-badge" style="margin-left:8px;">未读</span>
|
||||||
|
{else /}
|
||||||
|
<span class="layui-badge layui-bg-gray" style="margin-left:8px;">已读</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<table class="layui-table">
|
||||||
|
<colgroup>
|
||||||
|
<col width="120">
|
||||||
|
<col>
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>场景</td>
|
||||||
|
<td>{$msg.scene_title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>接收时间</td>
|
||||||
|
<td>{$msg.create_time|date="Y-m-d H:i:s"}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>内容</td>
|
||||||
|
<td style="white-space:pre-wrap;">{$msg.content}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="text-center">
|
||||||
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm" id="notice-read-close">关闭</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
16
extend/base/admin/view/notice/read.js
Normal file
16
extend/base/admin/view/notice/read.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
$(function(){
|
||||||
|
ua.listen();
|
||||||
|
|
||||||
|
// 关闭按钮:弹窗内关闭当前 iframe;非弹窗场景(直接以标签页打开)返回上一页
|
||||||
|
$('#notice-read-close').on('click', function () {
|
||||||
|
var parentLayer = (window.parent && window.parent.layui) ? window.parent.layui.layer : null;
|
||||||
|
if (parentLayer) {
|
||||||
|
var index = parentLayer.getFrameIndex(window.name);
|
||||||
|
if (index !== undefined && index !== null) {
|
||||||
|
parentLayer.close(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
history.back();
|
||||||
|
});
|
||||||
|
})
|
||||||
52
extend/base/admin/view/notice/subscribe.html
Normal file
52
extend/base/admin/view/notice/subscribe.html
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<div class="layuimini-container">
|
||||||
|
<form id="app-form" class="layui-form layuimini-form">
|
||||||
|
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">订阅设置</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<div style="color:#999;font-size:12px;line-height:20px;padding:4px 0 8px 0;">
|
||||||
|
选择每类通知通过哪个渠道发送给您;未保存过的组合默认为订阅。标注「必选」的场景为系统强制通知,不可关闭。
|
||||||
|
</div>
|
||||||
|
<table class="layui-table" lay-size="sm" id="subscribe-matrix">
|
||||||
|
<colgroup>
|
||||||
|
<col>
|
||||||
|
{volist name="channels" id="channelTitle"}
|
||||||
|
<col width="180">
|
||||||
|
{/volist}
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>场景</th>
|
||||||
|
{volist name="channels" id="channelTitle"}
|
||||||
|
<th class="text-center">{$channelTitle}</th>
|
||||||
|
{/volist}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="matrix" id="sceneRow"}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{$sceneRow.title}
|
||||||
|
{if condition="$sceneRow.locked"}
|
||||||
|
<span class="layui-badge layui-bg-gray">必选</span>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
{volist name="sceneRow.cells" id="cell"}
|
||||||
|
<td class="text-center">
|
||||||
|
<input type="checkbox" name="{$cell.name}" value="1" lay-skin="switch" lay-text="开|关" lay-filter="subscribe-switch" {$cell.checked} {$cell.disabled}>
|
||||||
|
</td>
|
||||||
|
{/volist}
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hr-line"></div>
|
||||||
|
<div class="layui-form-item text-center">
|
||||||
|
<button type="submit" class="layui-btn layui-btn-normal layui-btn-sm" lay-submit="notice/save_subscribe" data-close="false" data-refresh="false">保存设置</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
16
extend/base/admin/view/notice/subscribe.js
Normal file
16
extend/base/admin/view/notice/subscribe.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
$(function(){
|
||||||
|
// 提交前补齐矩阵:layui 只序列化勾选的开关,
|
||||||
|
// 这里把全部未禁用开关按当前状态补齐为 1/0,保证逐格显式 upsert
|
||||||
|
function buildMatrix(dataField) {
|
||||||
|
$('#subscribe-matrix input[type="checkbox"][name^="matrix["]').each(function () {
|
||||||
|
var $input = $(this);
|
||||||
|
if ($input.prop('disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dataField[$input.attr('name')] = $input.prop('checked') ? 1 : 0;
|
||||||
|
});
|
||||||
|
return dataField;
|
||||||
|
}
|
||||||
|
|
||||||
|
ua.listen(buildMatrix);
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user