define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { var Controller = { index: function () { Table.api.init({ extend: { index_url: 'split.link/index' + location.search, add_url: 'split.link/add', edit_url: 'split.link/edit', del_url: 'split.link/del', multi_url: 'split.link/multi', table: 'split_link', } }); var table = $("#table"); table.bootstrapTable({ url: $.fn.bootstrapTable.defaults.extend.index_url, pk: 'id', sortName: 'id', sortOrder: 'desc', fixedColumns: true, fixedRightNumber: 1, columns: [ [ {checkbox: true}, {field: 'countries_text', title: __('Countries'), operate: false, formatter: Table.api.formatter.content}, { field: 'link_code', title: __('Link_code'), operate: 'LIKE', formatter: Controller.api.formatter.linkCode }, {field: 'description', title: __('Description'), operate: 'LIKE', class: 'autocontent', formatter: Table.api.formatter.content}, { field: 'auto_reply_text', title: __('Reply statements column'), operate: false, formatter: Controller.api.formatter.autoReplyText }, {field: 'ip_protect', title: __('Ip_protect'), searchList: Config.ipProtectList, formatter: Table.api.formatter.status}, {field: 'random_shuffle', title: __('Random_shuffle'), searchList: Config.randomShuffleList, formatter: Table.api.formatter.status}, {field: 'status', title: __('Status'), searchList: Config.statusList, formatter: Table.api.formatter.status}, {field: 'createtime', title: __('Createtime'), operate: 'RANGE', addclass: 'datetimerange', autocomplete: false, formatter: Table.api.formatter.datetime, sortable: true}, { field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, buttons: [ { name: 'autoreply', text: __('Auto reply'), title: __('Auto reply'), icon: 'fa fa-commenting-o', classname: 'btn btn-warning btn-xs btn-split-autoreply', url: 'javascript:;' }, { name: 'pixel', text: __('Pixel config'), title: __('Pixel config'), icon: 'fa fa-bullseye', classname: 'btn btn-info btn-xs btn-split-pixel', url: 'javascript:;' } ], formatter: Table.api.formatter.operate } ] ] }); table.on('click', '.btn-copy-split-link', function (e) { e.preventDefault(); e.stopPropagation(); var linkCode = $.trim($(this).data('link-code') || ''); if (!linkCode) { return false; } Controller.api.openCopyModal(linkCode); }); table.on('click', '.btn-copy-link-code-inline', function (e) { e.preventDefault(); e.stopPropagation(); var linkCode = $.trim($(this).data('link-code') || ''); if (linkCode) { Controller.api.copyText(linkCode); } }); table.on('click', '.btn-split-autoreply', function (e) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); var rowIndex = $(this).data('row-index'); var row = Table.api.getrowbyindex(table, rowIndex); if (!row || !row.id) { return false; } Controller.api.openAutoReplyModal(row); }); table.on('click', '.btn-split-pixel', function (e) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); var rowIndex = $(this).data('row-index'); var row = Table.api.getrowbyindex(table, rowIndex); if (!row || !row.id) { return false; } Controller.api.openPixelModal(row); }); Controller.api.bindAutoReplyPreviewTips(table); Table.api.bindevent(table); }, add: function () { Controller.api.bindevent(); Controller.api.bindLinkCodeInput(); }, edit: function () { Controller.api.bindevent(); }, api: { /** * 规范化后台跨模块跳转 URL,避免在 split.link 页面内相对解析成 split.link/domain * * @param {string} url API 返回的地址 * @param {string} fallback 相对 admin 模块根路径,如 domain / domain/add * @return {string} */ normalizeAdminRouteUrl: function (url, fallback) { fallback = fallback || 'domain'; url = $.trim(url || ''); if (url === '' || /split\.link\/domain/i.test(url)) { return fallback; } var modulePrefix = (Config.moduleurl || '').replace(/\/+$/, ''); if (url.indexOf('://') !== -1) { try { var parsed = new URL(url, window.location.origin); var path = (parsed.pathname || '').replace(/\/+$/, ''); if (modulePrefix && path.indexOf(modulePrefix) === 0) { path = path.slice(modulePrefix.length); } path = path.replace(/^\/+/, ''); return /^split\.link\/domain/i.test(path) ? fallback : (path || fallback); } catch (e) { return fallback; } } if (url.charAt(0) === '/') { url = url.replace(/^\/+/, ''); var moduleKey = modulePrefix.replace(/^\/+/, ''); if (moduleKey && url.indexOf(moduleKey + '/') === 0) { url = url.slice(moduleKey.length + 1); } } return /^split\.link\/domain/i.test(url) ? fallback : url; }, /** 弹窗样式(仅注入一次) */ modalStyleInjected: false, pixelModalStyleInjected: false, injectModalStyles: function () { if (Controller.api.modalStyleInjected) { return; } Controller.api.modalStyleInjected = true; var css = [ '.split-link-copy-modal{padding:16px 20px;box-sizing:border-box;}', '.split-link-copy-modal .form-group{margin-bottom:16px;}', '.split-link-copy-modal .control-label{display:block;font-weight:600;color:#444;margin-bottom:8px;}', '.split-link-copy-modal .split-link-code-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px;}', '.split-link-copy-modal .split-link-code-value{font-size:18px;font-weight:600;color:#337ab7;text-decoration:underline;word-break:break-all;}', '.split-link-copy-modal .split-domain-tabs{margin-bottom:0;border-bottom:1px solid #ddd;}', '.split-link-copy-modal .split-domain-tab-box{border:1px solid #ddd;border-top:none;border-radius:0 0 4px 4px;background:#fafafa;overflow:hidden;}', '.split-link-copy-modal .split-domain-tab-box .tab-pane{max-height:280px;overflow-y:auto;overflow-x:hidden;padding:10px 12px;margin:0;}', '.split-link-copy-modal .split-domain-list{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;align-items:stretch;}', '.split-link-copy-modal .split-domain-item{border:1px solid #e8e8e8;border-radius:4px;background:#fff;transition:border-color .2s,box-shadow .2s;height:100%;min-width:0;}', '.split-link-copy-modal .split-domain-item:hover{border-color:#b8d4f0;}', '.split-link-copy-modal .split-domain-item.is-checked{border-color:#337ab7;box-shadow:0 0 0 1px rgba(51,122,183,.15);}', '.split-link-copy-modal .split-domain-item-label{display:flex;align-items:flex-start;gap:8px;margin:0;padding:8px 10px;cursor:pointer;font-weight:normal;width:100%;height:100%;box-sizing:border-box;}', '.split-link-copy-modal .split-domain-item-label input[type=radio]{margin:3px 0 0;flex-shrink:0;}', '.split-link-copy-modal .split-domain-item-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px;}', '.split-link-copy-modal .split-domain-name{font-size:13px;font-weight:600;color:#333;word-break:break-all;line-height:1.4;}', '.split-link-copy-modal .split-domain-status{display:flex;flex-direction:column;align-items:flex-start;gap:4px;}', '.split-link-copy-modal .split-domain-status .label{font-size:10px;font-weight:normal;padding:2px 6px;line-height:1.3;white-space:nowrap;margin:0;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;}', '.split-link-copy-modal .split-domain-empty{margin:0;padding:20px 12px;color:#999;text-align:center;line-height:1.6;grid-column:1/-1;}', '.split-link-copy-modal .split-tip-box{margin:12px 0;padding:10px 12px;background:#f8f9fa;border-left:3px solid #337ab7;border-radius:0 4px 4px 0;line-height:1.6;color:#666;}', '.split-link-copy-modal .split-generated-url{font-size:12px;}', '.split-link-copy-modal .split-modal-footer{margin-top:16px;padding-top:12px;border-top:1px solid #eee;}' ].join(''); $('').text(css).appendTo('head'); }, injectPixelModalStyles: function () { if (Controller.api.pixelModalStyleInjected) { return; } Controller.api.pixelModalStyleInjected = true; var css = [ '.split-pixel-layer .layui-layer-content{padding:0;overflow:hidden;max-height:calc(86vh - 108px);}', '.split-pixel-layer .layui-layer-btn{border-top:1px solid #e8e8e8;background:#fafafa;}', '.split-pixel-modal{padding:18px 22px 14px;box-sizing:border-box;display:flex;flex-direction:column;min-height:480px;height:calc(86vh - 108px);max-height:720px;}', '.split-pixel-modal .split-pixel-tip{margin:0 0 14px;padding:10px 14px;background:#f0f7ff;border-left:3px solid #337ab7;border-radius:0 4px 4px 0;color:#555;font-size:13px;line-height:1.65;}', '.split-pixel-modal .split-pixel-tabs{margin-bottom:0;border-bottom:1px solid #ddd;}', '.split-pixel-modal .split-pixel-tabs>li>a{padding:9px 18px;font-weight:600;color:#666;}', '.split-pixel-modal .split-pixel-tabs>li.active>a{color:#337ab7;border-bottom-color:#fff;}', '.split-pixel-modal .split-pixel-tab-content{flex:1;display:flex;flex-direction:column;min-height:0;padding-top:14px;}', '.split-pixel-modal .split-pixel-tab-content>.tab-pane{display:none;flex:1;flex-direction:column;min-height:0;}', '.split-pixel-modal .split-pixel-tab-content>.tab-pane.active{display:flex;}', '.split-pixel-modal .split-pixel-list{flex:1;display:flex;flex-direction:column;min-height:0;}', '.split-pixel-modal .split-pixel-toolbar{margin-bottom:12px;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;}', '.split-pixel-modal .split-pixel-toolbar .btn-add-pixel-row{font-weight:600;padding:6px 14px;}', '.split-pixel-modal .split-pixel-table-wrap{flex:1;min-height:320px;overflow:auto;border:1px solid #dce3eb;border-radius:6px;background:#fff;box-shadow:inset 0 1px 2px rgba(0,0,0,.03);}', '.split-pixel-modal .split-pixel-table{margin-bottom:0;font-size:13px;table-layout:auto;width:100%;}', '.split-pixel-modal .split-pixel-table thead th{background:linear-gradient(180deg,#f8fafc 0%,#eef2f6 100%);white-space:nowrap;vertical-align:middle;text-align:center;font-weight:600;color:#444;border-bottom:2px solid #dce3eb;padding:10px 8px;position:sticky;top:0;z-index:3;box-shadow:0 1px 0 #dce3eb;}', '.split-pixel-modal .split-pixel-table tbody td{vertical-align:middle;padding:10px 8px;border-color:#edf1f5;}', '.split-pixel-modal .split-pixel-table tbody tr.split-pixel-row:hover{background:#f7fbff;}', '.split-pixel-modal .split-pixel-table tbody tr.split-pixel-row:nth-child(even){background:#fbfcfd;}', '.split-pixel-modal .split-pixel-table tbody tr.split-pixel-row:nth-child(even):hover{background:#f7fbff;}', '.split-pixel-modal .split-pixel-table .form-control{min-width:0;height:32px;line-height:1.42857143;padding:6px 10px;border-radius:4px;}', '.split-pixel-modal .split-pixel-table .pixel-id{min-width:130px;}', '.split-pixel-modal .split-pixel-table .pixel-access-token{min-width:150px;}', '.split-pixel-modal .split-pixel-table .pixel-test-code{min-width:100px;}', '.split-pixel-modal .split-pixel-table th.pixel-event-col,.split-pixel-modal .split-pixel-table td.pixel-event-cell{min-width:148px;width:148px;}', '.split-pixel-modal .split-pixel-table .pixel-event{width:100%;min-width:132px;max-width:none;padding-right:28px;text-overflow:clip;overflow:visible;white-space:nowrap;cursor:pointer;}', '.split-pixel-modal .split-pixel-empty-row td{padding:48px 16px;color:#999;text-align:center;font-size:13px;background:#fafbfc;}', '.split-pixel-modal .split-pixel-sort-group{width:118px;margin:0 auto;}', '.split-pixel-modal .split-pixel-sort-group .form-control{text-align:center;padding-left:4px;padding-right:4px;}', '.split-pixel-modal .pixel-switch-wrap{text-align:center;}', '.split-pixel-modal .pixel-switch-wrap input[type=checkbox]{width:17px;height:17px;margin:0;cursor:pointer;vertical-align:middle;}', '.split-pixel-modal .pixel-row-index{display:inline-block;min-width:26px;height:26px;line-height:26px;border-radius:13px;background:#e8eef5;color:#4a6785;font-weight:600;font-size:12px;}', '.split-pixel-modal .btn-pixel-row-remove{padding:4px 8px;border-radius:4px;}', '.split-pixel-modal .col-token{min-width:160px;}' ].join(''); $('').text(css).appendTo('head'); }, formatter: { /** * 回复语:列表最多 50 字 + ...,悬停保留换行显示全文 */ autoReplyText: function (value, row, index) { var full = (row.auto_reply != null && row.auto_reply !== '') ? String(row.auto_reply) : ''; if (full === '') { return '-'; } var preview = value != null && value !== '' ? String(value) : full; var safePreview = Fast.api.escape(preview); var encFull = encodeURIComponent(full); return ''; }, /** * 分流链接列:链接样式 + COPY 图标,点击链接打开弹窗 */ linkCode: function (value) { value = value == null ? '' : value.toString(); if (value === '') { return '-'; } var safe = Fast.api.escape(value); return '' + '' + safe + '' + ' ' + ''; } }, openCopyModal: function (linkCode) { Controller.api.loadCopyModalData(function (data) { Controller.api.renderCopyModal(linkCode, data); }); }, /** 回复语列悬停提示(保留换行) */ autoReplyTipIndex: null, bindAutoReplyPreviewTips: function (table) { table.off('mouseenter.splitAutoReply mouseleave.splitAutoReply') .on('mouseenter.splitAutoReply', '.split-auto-reply-preview', function () { var enc = $(this).attr('data-full'); if (!enc) { return; } var full = ''; try { full = decodeURIComponent(enc); } catch (e) { return; } var html = '
| ' + __('Pixel row index') + ' | ', '' + __('Pixel enabled') + ' | ', '' + __('Server postback') + ' | ', '' + __('Pixel ID') + ' * | ', '' + __('Pixel event') + ' | ', '' + __('Access Token') + ' | ', '' + __('Test code') + ' | ', '' + __('Pixel sort') + ' | ', '' + __('Operate') + ' | ', '
|---|---|---|---|---|---|---|---|---|
| ' + __('Pixel list empty') + ' | ||||||||
' + __('Split platform domain empty') + ' ' + __('Go system config') + '' + '
'; } var myDomainsHtml = ''; if (myDomains.length) { var items = []; $.each(myDomains, function (i, item) { items.push(Controller.api.buildDomainRadio({ domain: item.domain, type: 'my', checked: defaultType === 'my' && item.domain === defaultDomain, nsText: item.ns_status_text || '', dnsText: item.dns_status_text || '', nsStatus: item.ns_status || '', dnsStatus: item.dns_status || '', showStatus: true })); }); myDomainsHtml = '' + __('Split my domain empty') + '
'; } var initialUrl = Controller.api.buildSplitUrl(defaultDomain, linkCode); var safeLinkCode = Fast.api.escape(linkCode); var html = [ '