diff --git a/api/channel/plan_list.php b/api/channel/plan_list.php index 9871a7a..161fe6c 100644 --- a/api/channel/plan_list.php +++ b/api/channel/plan_list.php @@ -41,7 +41,7 @@ $total = (int)$stmt->fetchColumn(); $offset = ($page - 1) * $limit; $stmt = $pdo->prepare( - "SELECT id, channel_type, source_detail, industry, start_date, end_date, remark, status, created_at, updated_at + "SELECT id, channel_type, source_detail, industry, start_date, end_date, remark, status, cost, created_at, updated_at FROM channel_plans WHERE $whereSql ORDER BY id DESC @@ -58,6 +58,8 @@ foreach ($list as &$row) { $diff = (int)ceil((strtotime($row['end_date']) - $today) / 86400); $row['remaining_days'] = max(0, $diff); } + // cost 转数字(空为 null) + $row['cost'] = ($row['cost'] === null || $row['cost'] === '') ? null : (float)$row['cost']; } unset($row); diff --git a/api/channel/plan_save.php b/api/channel/plan_save.php index e32431f..df39fe9 100644 --- a/api/channel/plan_save.php +++ b/api/channel/plan_save.php @@ -1,8 +1,9 @@ getPdo(); -$fields = [ - 'channel_type' => $channelType, - 'source_detail' => trim($_POST['source_detail'] ?? '') !== '' ? trim($_POST['source_detail']) : null, - 'industry' => trim($_POST['industry'] ?? '') !== '' ? trim($_POST['industry']) : null, - 'start_date' => trim($_POST['start_date'] ?? '') !== '' ? $_POST['start_date'] : null, - 'end_date' => trim($_POST['end_date'] ?? '') !== '' ? $_POST['end_date'] : null, - 'remark' => trim($_POST['remark'] ?? '') !== '' ? trim($_POST['remark']) : null, - 'status' => $status, -]; +/** 从 POST 收集需要写入的字段(空串转 null) */ +$fields = []; +$collect = function ($key) use (&$fields) { + if (isset($_POST[$key])) { + $v = trim((string)$_POST[$key]); + $fields[$key] = $v !== '' ? $v : null; + } +}; if ($id > 0) { - $check = $pdo->prepare("SELECT id FROM channel_plans WHERE id = ? AND is_active = 1"); + $check = $pdo->prepare("SELECT id, status FROM channel_plans WHERE id = ? AND is_active = 1"); $check->execute([$id]); - if (!$check->fetch()) { + $cur = $check->fetch(); + if (!$cur) { Response::error('计划不存在'); } + // 只更新提交的字段 + foreach (['channel_type', 'source_detail', 'industry', 'start_date', 'end_date', 'remark', 'status'] as $k) { + $collect($k); + } + if (isset($_POST['cost'])) { + $c = trim((string)$_POST['cost']); + $fields['cost'] = $c !== '' ? round((float)$c, 2) : null; + } + // 若只改了状态为「已执行」而原费用为空,前端会单独提交 cost;此处不自动置值 + if (!$fields) { + Response::error('没有需要更新的字段', 400); + } [$sets, $params] = buildUpdate($fields); $params[] = $id; $pdo->prepare("UPDATE channel_plans SET $sets WHERE id = ?")->execute($params); @@ -48,6 +70,21 @@ if ($id > 0) { Response::success(null, '更新成功'); } +// 新增:渠道类别必填 +$channelType = trim($_POST['channel_type'] ?? ''); +if ($channelType === '') { + Response::error('渠道类别(channel_type)为必填项', 400); +} +$fields = [ + 'channel_type' => $channelType, + 'source_detail' => strOrNull($_POST['source_detail'] ?? null), + 'industry' => strOrNull($_POST['industry'] ?? null), + 'start_date' => strOrNull($_POST['start_date'] ?? null), + 'end_date' => strOrNull($_POST['end_date'] ?? null), + 'remark' => strOrNull($_POST['remark'] ?? null), + 'status' => $status !== '' ? $status : '待启动', + 'cost' => $cost !== '' ? round((float)$cost, 2) : null, +]; [$sql, $params] = buildInsert($fields); $pdo->prepare("INSERT INTO channel_plans $sql")->execute($params); $newId = (int)$pdo->lastInsertId(); diff --git a/api/common/auth.php b/api/common/auth.php index c35a179..a0d71cc 100644 --- a/api/common/auth.php +++ b/api/common/auth.php @@ -45,6 +45,23 @@ function checkPermission($module) } } +/** + * 校验当前用户是否拥有多个模块权限中的任意一个(同时校验登录态) + * 用途:功能迁移场景(如文件管理内容迁入竞品资料,document 与 competitor_data 任一权限可访问) + * @param array $modules 菜单标识数组 + */ +function checkAnyPermission($modules) +{ + requireLogin(); + $perms = $_SESSION['permissions'] ?? []; + foreach ((array)$modules as $m) { + if (in_array($m, $perms, true)) { + return; + } + } + Response::error('无权操作', 403); +} + /** 仅超级管理员可操作(如操作日志查询) */ function requireSuperAdmin() { diff --git a/api/company/list.php b/api/company/list.php index 0023d2d..ba26a63 100644 --- a/api/company/list.php +++ b/api/company/list.php @@ -34,6 +34,75 @@ if ($active !== null) { $where = ['is_active = ?']; $params = [$active]; } + +// 筛选弹窗多字段条件:filters=JSON数组 [{field,op,value}],filter_logic=and|or +// 注意:必须在此处($where/$params 初始化后)追加,否则会被上面的赋值覆盖 +$filtersJson = trim($_REQUEST['filters'] ?? ''); +$filterLogic = strtoupper(trim($_REQUEST['filter_logic'] ?? 'and')) === 'OR' ? 'OR' : 'AND'; +$filterConds = []; +if ($filtersJson !== '') { + $decoded = json_decode($filtersJson, true); + if (is_array($decoded)) { + foreach ($decoded as $c) { + $fField = trim($c['field'] ?? ''); + $fOp = trim($c['op'] ?? ''); + $fVal = trim((string)($c['value'] ?? '')); + if ($fField === '' || !in_array($fField, $searchableFields, true)) { + continue; + } + switch ($fOp) { + case 'contains': + $filterConds[] = "$fField LIKE ?"; + $params[] = "%$fVal%"; + break; + case 'eq': + $filterConds[] = "$fField = ?"; + $params[] = $fVal; + break; + case 'neq': + $filterConds[] = "$fField <> ?"; + $params[] = $fVal; + break; + case 'starts_with': + $filterConds[] = "$fField LIKE ?"; + $params[] = "$fVal%"; + break; + case 'ends_with': + $filterConds[] = "$fField LIKE ?"; + $params[] = "%$fVal"; + break; + case 'gt': + $filterConds[] = "$fField > ?"; + $params[] = $fVal; + break; + case 'lt': + $filterConds[] = "$fField < ?"; + $params[] = $fVal; + break; + case 'gte': + $filterConds[] = "$fField >= ?"; + $params[] = $fVal; + break; + case 'lte': + $filterConds[] = "$fField <= ?"; + $params[] = $fVal; + break; + case 'is_empty': + $filterConds[] = "($fField IS NULL OR $fField = '')"; + break; + case 'is_not_empty': + $filterConds[] = "($fField IS NOT NULL AND $fField <> '')"; + break; + default: + break; + } + } + } +} +if ($filterConds) { + $where[] = '(' . implode(" $filterLogic ", $filterConds) . ')'; +} + if ($keyword !== '') { if ($field !== '' && in_array($field, $searchableFields, true)) { $where[] = "$field LIKE ?"; diff --git a/api/document/delete.php b/api/document/delete.php index 28d37a5..80fbb32 100644 --- a/api/document/delete.php +++ b/api/document/delete.php @@ -9,7 +9,7 @@ require_once __DIR__ . '/../common/auth.php'; require_once __DIR__ . '/../common/logger.php'; checkAjax(); -checkPermission('document'); +checkAnyPermission(['document', 'competitor_data']); $id = (int)($_POST['id'] ?? 0); $ids = trim($_POST['ids'] ?? ''); diff --git a/api/document/list.php b/api/document/list.php index 5e1f559..1bfcac4 100644 --- a/api/document/list.php +++ b/api/document/list.php @@ -8,7 +8,7 @@ require_once __DIR__ . '/../common/db.php'; require_once __DIR__ . '/../common/response.php'; require_once __DIR__ . '/../common/auth.php'; -checkPermission('document'); +checkAnyPermission(['document', 'competitor_data']); [$page, $limit] = pageParams(); $keyword = trim($_REQUEST['keyword'] ?? ''); diff --git a/api/document/upload.php b/api/document/upload.php index a3dba51..bec9786 100644 --- a/api/document/upload.php +++ b/api/document/upload.php @@ -11,7 +11,7 @@ require_once __DIR__ . '/../common/auth.php'; require_once __DIR__ . '/../common/logger.php'; checkAjax(); -checkPermission('document'); +checkAnyPermission(['document', 'competitor_data']); if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) { Response::error('请选择要上传的文件', 400); diff --git a/competitor_data.html b/competitor_data.html index 2682138..98dbee8 100644 --- a/competitor_data.html +++ b/competitor_data.html @@ -1,4 +1,4 @@ - + @@ -12,7 +12,6 @@ - - + - \ No newline at end of file + diff --git a/sql/migration_v1.0.20.sql b/sql/migration_v1.0.20.sql new file mode 100644 index 0000000..4a52f4b --- /dev/null +++ b/sql/migration_v1.0.20.sql @@ -0,0 +1,9 @@ +-- ============================================================ +-- SuperLink Web - v1.0.20 数据库结构变更 +-- 需求文档:0808---62b20256-32fc-48ce-9164-4d05b6e83f36.docx +-- 渠道新增计划增加「费用(元)」字段(仅已执行状态可填写) +-- ============================================================ +SET NAMES utf8mb4; + +ALTER TABLE `channel_plans` + ADD COLUMN `cost` DECIMAL(12,2) NULL DEFAULT NULL COMMENT '费用(元),仅已执行状态可填写' AFTER `status`; diff --git a/static/css/style.css b/static/css/style.css index dba5178..5516f46 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -287,6 +287,64 @@ body { .toolbar input:focus, .toolbar select:focus { border-color: #4fa3ff; } .toolbar .spacer { flex: 1; } +/* 搜索框:框内左侧字段选择 + 框内右侧搜索图标 */ +.toolbar .search-wrap { + display: inline-flex; + align-items: center; + height: 34px; + border: 1px solid #d9dee8; + border-radius: 4px; + background: #fff; + overflow: hidden; +} +.toolbar .search-wrap:focus-within { border-color: #4fa3ff; } +.toolbar .search-wrap select { + border: none; + height: 100%; + min-width: 108px; + max-width: 150px; + border-right: 1px solid #eef0f4; + border-radius: 0; + background: #f7f9fc; + font-size: 12px; + padding: 0 8px; +} +.toolbar .search-wrap input[type="text"] { + border: none; + height: 100%; + min-width: 220px; + border-radius: 0; + box-shadow: none; + outline: none; +} +.toolbar .search-wrap .search-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 34px; + height: 100%; + color: #8a94a6; + cursor: pointer; + background: #fff; +} +.toolbar .search-wrap .search-icon:hover { color: #2a5298; } + +/* 筛选弹窗条件行 */ +.filter-row { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 8px; +} + +/* 渠道效能分析-来源明细:单行显示,过长用…占位(不分行) */ +.ana-detail .src-cell { + max-width: 200px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + /* ---------- 按钮 ---------- */ .btn { display: inline-block; diff --git a/static/js/channel.js b/static/js/channel.js index 99e7723..bf77716 100644 --- a/static/js/channel.js +++ b/static/js/channel.js @@ -58,7 +58,6 @@ $(function () { ' 根据历史数据有计划地拓展高效渠道' + ' ' + '
' + - ' ' + ' ' + ' ' + @@ -68,7 +67,7 @@ $(function () { ' ' + '
' + '
' + - ' ' + + ' ' + ' ' + '
ID渠道类别来源详情所属行业时间窗口剩余天数备注说明状态反馈创建时间操作
ID渠道类别来源详情所属行业时间窗口剩余天数备注说明状态反馈费用(元)创建时间
' + ' ' + @@ -168,8 +167,7 @@ $(function () { var html = ''; (r.details || []).forEach(function (item) { var src = item.source || ''; - var short = src.length > 8 ? src.substring(0, 8) + '…' : src; - html += '' + escHtml(short) + '' + (item.count !== undefined ? item.count : item.cnt) + ''; + html += '' + escHtml(src) + '' + (item.count !== undefined ? item.count : item.cnt) + ''; }); if (!(r.details || []).length) { html = '暂无明细'; @@ -217,6 +215,12 @@ $(function () { var win = r.start_date && r.end_date ? fmtWin(r.start_date) + ' 至 ' + fmtWin(r.end_date) : (r.start_date || r.end_date || '-'); + var statusSel = ''; + var costInput = ''; html += '' + '' + r.id + '' + '' + escHtml(r.channel_type) + '' + @@ -225,19 +229,55 @@ $(function () { '' + escHtml(win) + '' + '' + (r.remaining_days > 0 ? '' + r.remaining_days + ' 天' : '已到期') + '' + '' + escHtml((r.remark || '-').substring(0, 20)) + '' + - '' + statusTag(r.status) + '' + - '' + fmtDate(r.created_at) + '' + - '编辑' + - '删除'; + '' + statusSel + '' + + '' + costInput + '' + + '' + fmtDate(r.created_at) + ''; }); if (!rows.length) { html = '暂无渠道新增计划'; } $('#plan-tbody').html(html); + bindPlanInlineEdit(); renderPagination($('#plan-pagination'), data, loadPlans); }); } + /** 行内实时编辑:状态下拉随时改;费用(元)仅在「已执行」时激活可输入 */ + function bindPlanInlineEdit() { + $('.plan-status').off('change.plan').on('change.plan', function () { + var id = $(this).data('id'); + var status = $(this).val(); + var $row = $(this).closest('tr'); + var $cost = $row.find('.plan-cost'); + if (status === '已执行') { + $cost.prop('disabled', false).css({ background: '#fff', color: '#1e2a3a' }); + } else { + $cost.prop('disabled', true).css({ background: '#f2f4f8', color: '#8a94a6' }); + } + httpPost('channel/plan_save.php', { id: id, status: status }).then(function () { + Dialog.toast('状态已更新为「' + status + '」'); + }).catch(function () { + loadPlans(currentPage); + }); + }); + $('.plan-cost').off('change.plan').on('change.plan', function () { + var id = $(this).data('id'); + var val = $.trim($(this).val()); + if (val === '') return; + if (isNaN(parseFloat(val))) { + Dialog.error('费用(元)请输入数字'); + return; + } + var cost = Math.round(parseFloat(val) * 100) / 100; + $(this).val(cost); + httpPost('channel/plan_save.php', { id: id, cost: cost }).then(function () { + Dialog.toast('费用已更新:¥' + cost.toFixed(2)); + }).catch(function () { + loadPlans(currentPage); + }); + }); + } + /** 时间窗口显示格式:2025-4-1 */ function fmtWin(d) { if (!d) return ''; @@ -295,6 +335,8 @@ $(function () { ' ' + ' ' + ' ' + + '
' + '
' + '
' + '
' + @@ -312,6 +354,15 @@ $(function () { $('#plan-form-cancel').on('click', function () { Dialog.close(idx); }); + // 状态反馈 → 费用(元) 联动:仅「已执行」可填写 + $('#plan-form select[name="status"]').on('change', function () { + var enabled = $(this).val() === '已执行'; + var $cost = $('#plan-form input[name="cost"]'); + $cost.prop('disabled', !enabled); + $cost.css({ background: enabled ? '#fff' : '#f2f4f8', color: enabled ? '#1e2a3a' : '#8a94a6' }); + if (!enabled) $cost.val(''); + }); + $('#plan-form').on('submit', function (e) { e.preventDefault(); var data = {}; diff --git a/static/js/company.js b/static/js/company.js index ebc7626..d2acffe 100644 --- a/static/js/company.js +++ b/static/js/company.js @@ -28,17 +28,20 @@ $(function () { $('#page-content').html( '
' + '
' + - ' ' + - ' ' + + ' ' + + '
' + + ' ' + + ' ' + + ' ' + + '
' + ' ' + - ' ' + - ' ' + + ' ' + ' ' + ' ' + ' ' + @@ -71,6 +74,8 @@ $(function () { } /* ---------- 列表 ---------- */ + var companyFilters = { logic: 'and', conditions: [] }; // 筛选弹窗条件(多字段 + 且/或) + function loadList(page) { currentPage = page; var params = { @@ -81,6 +86,11 @@ $(function () { page: page, limit: PAGE_SIZE }; + // 筛选弹窗条件(多字段 + 逻辑关系) + if (companyFilters.conditions.length) { + params.filters = JSON.stringify(companyFilters.conditions); + params.filter_logic = companyFilters.logic; + } // 空值不传 Object.keys(params).forEach(function (k) { if (params[k] === '') delete params[k]; @@ -118,17 +128,110 @@ $(function () { }); } - /* ---------- 筛选 ---------- */ + /* ---------- 检索:搜索(字段范围+关键词) / 筛选弹窗 / 行业+业务类型快速筛选 ---------- */ $('#btn-search').on('click', function () { loadList(1); }); $('#search-keyword').on('keydown', function (e) { if (e.keyCode === 13) loadList(1); }); + $('#search-industry, #search-company-type').on('change', function () { loadList(1); }); $('#btn-reset').on('click', function () { $('#search-field').val(''); $('#search-keyword').val(''); $('#search-industry').val(''); $('#search-company-type').val(''); + companyFilters = { logic: 'and', conditions: [] }; loadList(1); }); + /* ---------- 筛选弹窗:多字段条件 + 且/或 逻辑关系 ---------- */ + var FILTER_FIELDS = [ + ['name_zh', '企业名称'], ['name_en', '英文名称'], ['registration_number', '注册号'], + ['legal_representative', '法定代表人'], ['address', '注册地址'], ['country', '国家/地区'], + ['industry', '行业'], ['industry_subdivision', '行业细分'], ['legal_form', '企业类型'], + ['business_role', '业务角色'], ['website', '官网'], ['source_channel', '来源渠道'], + ['source_detail', '来源详情'], ['business_scope', '经营范围'], ['stock_code', '股票代码'], + ['established_date', '成立日期'], ['latest_employee_count', '最新员工数'], + ['latest_annual_revenue', '最新年营收'] + ]; + var FILTER_OPS = [ + ['contains', '包含'], ['eq', '等于'], ['neq', '不等于'], + ['starts_with', '开头是'], ['ends_with', '结尾是'], + ['gt', '大于'], ['lt', '小于'], ['gte', '大于等于'], ['lte', '小于等于'], + ['is_empty', '为空'], ['is_not_empty', '不为空'] + ]; + + function filterFieldOptions(cur) { + var h = ''; + FILTER_FIELDS.forEach(function (f) { + h += ''; + }); + return h; + } + function filterOpOptions(cur) { + var h = ''; + FILTER_OPS.forEach(function (o) { + h += ''; + }); + return h; + } + function filterRowHtml(c) { + c = c || {}; + var valInput = (c.op === 'is_empty' || c.op === 'is_not_empty') + ? '' + : ''; + return '
' + + ' ' + + ' ' + + valInput + + ' ' + + '
'; + } + + window.openFilterDialog = function () { + var logicHtml = + '' + + ''; + var rowsHtml = ''; + if (companyFilters.conditions.length) { + companyFilters.conditions.forEach(function (c) { rowsHtml += filterRowHtml(c); }); + } else { + rowsHtml = filterRowHtml(null); + } + var content = + '
' + + '
每个字段是一个筛选条件,不同条件之间可为「且」「或」关系:
' + + '
' + logicHtml + '
' + + '
' + rowsHtml + '
' + + ' ' + + '
' + + ''; + var idx = Dialog.open({ + title: '设置筛选条件', + area: ['620px', 'auto'], + content: content, + btn: false + }); + $('#btn-add-filter').on('click', function () { $('#filter-rows').append(filterRowHtml(null)); }); + $('#filter-cancel').on('click', function () { Dialog.close(idx); }); + $('#filter-apply').on('click', function () { + var logic = $('input[name="f-logic"]:checked').val() || 'and'; + var conds = []; + $('#filter-rows .filter-row').each(function () { + var field = $(this).find('.f-field').val(); + var op = $(this).find('.f-op').val(); + var value = $.trim($(this).find('input[type="text"]').val()); + if (!field || !op) return; + if (op !== 'is_empty' && op !== 'is_not_empty' && value === '') return; // 无值且需要值的条件跳过 + conds.push({ field: field, op: op, value: value }); + }); + companyFilters = { logic: logic, conditions: conds }; + Dialog.close(idx); + loadList(1); + }); + }; + $('#btn-filter').on('click', function () { openFilterDialog(); }); + /* ---------- 新增/编辑 ---------- */ $('#btn-add').on('click', function () { httpGet('company/cert_types.php').then(function (d) { diff --git a/static/js/competitor_data.js b/static/js/competitor_data.js new file mode 100644 index 0000000..f477734 --- /dev/null +++ b/static/js/competitor_data.js @@ -0,0 +1,106 @@ +/** + * competitor_data.js - 竞品资料页(v1.0.20 起承载原「文件管理」内容) + * 需求:左侧导航删掉「文件管理」,其呈现内容迁移到「竞品管理 > 竞品资料」, + * 即「竞品资料」=「文件管理」(表格展示 / 上传 / 删除)。 + */ +$(function () { + renderShell('竞品资料', '竞品管理 / 竞品资料'); + renderPage(); + initPage('competitor_data', function (user) { + if (!checkPagePermission('competitor_data')) return; + loadList(1); + }); + + var currentPage = 1; + + /** 渲染页面内容(工具栏+表格+分页) */ + function renderPage() { + $('#page-content').html( + '
' + + '
' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '
' + + '
' + + ' ' + + ' ' + + '
ID文档名称文件类型文件版本发布日期上传时间操作
' + + ' ' + + '
' + ); + $('#check-all').on('change', function () { $('.row-check').prop('checked', this.checked); }); + } + + function loadList(page) { + currentPage = page; + var params = buildFilterParam(); + params.page = page; + params.limit = PAGE_SIZE; + + httpGet('document/list.php', params).then(function (data) { + var rows = data.list || []; + var html = ''; + rows.forEach(function (r) { + var isLocal = (r.storage_path || '').indexOf('static/uploads/') === 0; + var link = isLocal ? r.storage_path : (r.storage_path || '#'); + html += '' + + '' + + '' + r.id + '' + + '' + escHtml(r.doc_name) + '' + + '' + escHtml(r.file_type || '-') + '' + + '查看/下载' + + '' + (r.is_current ? '当前版本' : '历史') + '' + + '' + escHtml(r.publish_date || '-') + '' + + '' + fmtDate(r.created_at) + '' + + '删除'; + }); + if (!rows.length) { + html = '暂无文件'; + } + $('#doc-tbody').html(html); + renderPagination($('#pagination'), data, loadList); + }); + } + + $('#btn-search').on('click', function () { loadList(1); }); + $('#btn-reset').on('click', function () { + $('.toolbar [data-filter]').val(''); + loadList(1); + }); + + /* ---------- 上传 ---------- */ + $('#btn-upload').on('click', function () { + triggerFileInput('.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.csv,.png,.jpg,.jpeg,.gif,.zip,.rar', function (file) { + var fd = new FormData(); + fd.append('file', file); + httpPost('document/upload.php', fd, true).then(function () { + Dialog.success('上传成功', function () { loadList(1); }); + }); + }); + }); + + /* ---------- 删除(同时删除物理文件) ---------- */ + window.delDoc = function (id) { + Dialog.confirm('确定删除该文件吗?将同时删除物理文件,不可恢复!', function () { + httpPost('document/delete.php', { id: id }).then(function () { + Dialog.success('删除成功', function () { loadList(currentPage); }); + }); + }); + }; + + $('#btn-del-batch').on('click', function () { + var ids = []; + $('.row-check:checked').each(function () { ids.push($(this).val()); }); + if (!ids.length) { Dialog.error('请先勾选记录'); return; } + Dialog.confirm('确定删除选中的 ' + ids.length + ' 个文件吗?将同时删除物理文件,不可恢复!', function () { + httpPost('document/delete.php', { ids: ids.join(',') }).then(function () { + Dialog.success('删除成功', function () { loadList(currentPage); }); + }); + }); + }); +}); diff --git a/static/js/config.js b/static/js/config.js index 741f990..8b2fe5d 100644 --- a/static/js/config.js +++ b/static/js/config.js @@ -5,7 +5,7 @@ var BASE_URL = '/api/'; var PAGE_SIZE = 20; /** 系统版本号(logo旁展示):修改代码后运行 tools/bump_version.php 自动递增 */ -var APP_VERSION = 'v1.0.19'; +var APP_VERSION = 'v1.0.20'; /** 页脚版权/备案信息(在 config.js 中修改) */ var FOOTER_TEXT = '© 2026 SuperLink 管理系统 版权所有 | 备案号:请替换为真实备案号'; @@ -86,7 +86,6 @@ var MENU_GROUPS = [ ] }, { key: 'channel', name: '渠道管理', icon: 'channel', url: 'channel.html' }, - { key: 'document', name: '文件管理', icon: 'document', url: 'document.html' }, { key: 'system', name: '权限管理', icon: 'system', children: [ { key: 'system', name: '用户管理', icon: 'users', url: 'user.html' },