update 2025-02-09 16:14:09
This commit is contained in:
parent
7c322735ed
commit
6b8c92ac4f
|
@ -816,7 +816,7 @@ gen_dns(){
|
|||
rm -f $O
|
||||
[ $(find $DNS_DIR -name \* -exec cat {} \; 2>/dev/null | wc -l) = 0 ] && rm -rf $DNS_DIR || echo conf-dir=$DNS_DIR >>$DNS_FILE
|
||||
[ $run_mode = router ] && chinadns_flag=1
|
||||
killall -q -9 smartdns
|
||||
killall -q smartdns
|
||||
start_dns
|
||||
/etc/init.d/dnsmasq restart >/dev/null 2>&1
|
||||
preload
|
||||
|
@ -1011,7 +1011,7 @@ stop(){
|
|||
kill -9 $(ps -w | grep by-monitor | grep -v grep | awk '{print$1}') 2>/dev/null
|
||||
kill -9 $(ps -w | grep by-preload | grep -v grep | awk '{print$1}') 2>/dev/null
|
||||
kill -9 $(ps -w | grep $VAR | grep -v grep | awk '{print$1}') 2>/dev/null
|
||||
killall -q -9 smartdns chinadns-ng kcptun-client microsocks
|
||||
killall -q smartdns chinadns-ng kcptun-client microsocks
|
||||
rm -rf $DNS_DIR $VAR $DNS_FILE $CON_T /var/lock/bypass-update.lock
|
||||
[ -z "$GLOBAL_SERVER" ] && grep -q bypass $CRON_FILE && sed -i '/bypass/d' $CRON_FILE && /etc/init.d/cron restart
|
||||
if [ $STATUS = Y -o -z "$GLOBAL_SERVER" ];then
|
||||
|
|
|
@ -444,10 +444,6 @@ restart(){
|
|||
fi
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "dnsfilter"
|
||||
}
|
||||
|
||||
boot(){
|
||||
gen;start
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ function index()
|
|||
end
|
||||
|
||||
local page
|
||||
entry({"admin", "services", "appfilter"}, alias("admin", "services", "appfilter", "user_list"),_("App Filter"), 10).dependent = true
|
||||
entry({"admin", "services", "appfilter"}, alias("admin", "services", "appfilter", "app_filter"),_("App Filter"), 10).dependent = true
|
||||
|
||||
|
||||
entry({"admin", "services", "appfilter", "user_list"},
|
||||
|
|
|
@ -32,10 +32,10 @@ if nixio.fs.access("/tmp/feature.cfg") then
|
|||
rule_count = tonumber(SYS.exec("cat /tmp/feature.cfg | grep -v ^$ |grep -v ^# | wc -l"))
|
||||
version = SYS.exec("cat /tmp/feature.cfg |grep \"#version\" | awk '{print $2}'")
|
||||
end
|
||||
format=SYS.exec("uci get appfilter.feature.format")
|
||||
if format == "" then
|
||||
format="v3.0"
|
||||
end
|
||||
-- format=SYS.exec("uci get appfilter.feature.format")
|
||||
-- if format == "" then
|
||||
format="v3.0"
|
||||
-- end
|
||||
|
||||
local display_str = "<style>" ..
|
||||
".label-style {}" ..
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
.button-container {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
margin-top: 20px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
|
@ -236,7 +236,7 @@
|
|||
const container = document.getElementById('appContainer');
|
||||
container.innerHTML = '';
|
||||
|
||||
data.class_list.forEach(category => {
|
||||
data.class_list.forEach((category, index) => {
|
||||
const categoryTitle = document.createElement('div');
|
||||
categoryTitle.className = 'category-title';
|
||||
|
||||
|
@ -267,7 +267,13 @@
|
|||
|
||||
const appList = document.createElement('div');
|
||||
appList.className = 'app-list';
|
||||
appList.style.display = 'none';
|
||||
|
||||
if (index === 1 || index === 2) {
|
||||
appList.style.display = 'flex';
|
||||
arrow.classList.add('expanded');
|
||||
} else {
|
||||
appList.style.display = 'none';
|
||||
}
|
||||
|
||||
categoryTitle.onclick = function() {
|
||||
if (appList.style.display === 'none') {
|
||||
|
|
|
@ -17,77 +17,76 @@
|
|||
.app-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start; /* 左对齐 */
|
||||
margin-top: 10px; /* 增加与标题的间距 */
|
||||
justify-content: flex-start;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.app-item {
|
||||
width: 140px; /* 固定宽度 */
|
||||
width: 140px;
|
||||
box-sizing: border-box;
|
||||
padding: 5px;
|
||||
display: flex; /* 使用flex布局 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.app-item label {
|
||||
display: flex; /* 使用flex布局 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
width: 100%; /* 确保标签占满整个宽度 */
|
||||
text-align: left; /* 左对齐文本 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
.app-item input[type="checkbox"] {
|
||||
margin-left: 2px; /* 勾选按钮离左侧2px */
|
||||
margin-right: 8px; /* 应用程序名称离按钮8px */
|
||||
margin-left: 2px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.category-title {
|
||||
display: flex; /* 使用flex布局 */
|
||||
justify-content: space-between; /* 两端对齐 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
width: 100%; /* 设置宽度为100% */
|
||||
cursor: pointer; /* 鼠标悬停时显示为可点击 */
|
||||
margin-bottom: 10px; /* 增加下方间距 */
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.category-name {
|
||||
font-size: 14px; /* 设置字体大小为16px */
|
||||
font-weight: normal; /* 设置字体为正常,不加粗 */
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.arrow {
|
||||
width: 12px; /* 图标宽度 */
|
||||
height: 12px; /* 图标高度 */
|
||||
/* background-image: url('path/to/your/icon.svg'); 替换为你的图标路径 */
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
||||
background-image: url('<%=resource%>/icons/arrow.png'); /* 使用LuCI资源路径 */
|
||||
background-size: contain; /* 确保图标适应容器 */
|
||||
background-repeat: no-repeat; /* 防止重复 */
|
||||
transition: transform 0.3s ease; /* 添加过渡效果 */
|
||||
display: inline-block; /* 使旋转生效 */
|
||||
transform: rotate(0deg); /* 初始状态箭头向右 */
|
||||
background-image: url('<%=resource%>/icons/arrow.png');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
transition: transform 0.3s ease;
|
||||
display: inline-block;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.arrow.expanded {
|
||||
transform: rotate(90deg); /* 展开状态箭头向下 */
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.category-title div {
|
||||
gap: 6px; /* 设置子元素之间的间距为20px */
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.app-item {
|
||||
width: 25%; /* 屏幕小于600px时每行显示4个 */
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: right; /* 使按钮居中 */
|
||||
margin-top: 20px; /* 上方留出一些空间 */
|
||||
justify-content: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
margin-top: 30px;
|
||||
width: 150px; /* 设置按钮宽度 */
|
||||
height: 30px; /* 设置按钮高度 */
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
background-color: #2885e8;
|
||||
color: white;
|
||||
border: none;
|
||||
|
@ -98,7 +97,6 @@
|
|||
background-color: #0f77e6;
|
||||
}
|
||||
|
||||
/* Add new styles for time rules */
|
||||
.time-rules {
|
||||
margin-top: 20px;
|
||||
border: 1px solid #ddd;
|
||||
|
@ -147,7 +145,7 @@
|
|||
}
|
||||
.setting-item label {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
width: 170px;
|
||||
}
|
||||
.setting-item input {
|
||||
width: 100px;
|
||||
|
@ -209,11 +207,9 @@
|
|||
|
||||
|
||||
function init_data() {
|
||||
// getAppFilterData().then(() => {
|
||||
// getClassListData();
|
||||
// });
|
||||
// getAppFilterBaseData(); // 新增调用获取过滤开关和工作模式数据的函数
|
||||
getAppFilterTimeData();
|
||||
getAppFilterTimeData().then(() => {
|
||||
renderTimeData();
|
||||
});
|
||||
}
|
||||
|
||||
function getAppFilterTimeData() {
|
||||
|
@ -222,8 +218,7 @@
|
|||
function (x, data) {
|
||||
time_data = data.data;
|
||||
console.log(data.data);
|
||||
renderTimeData();
|
||||
resolve(); // 请求完成后调用 resolve
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -232,19 +227,34 @@
|
|||
|
||||
function submitHandle() {
|
||||
const time_data = getTimeFormData();
|
||||
const maxEntries = 64;
|
||||
|
||||
if (!time_data.time_list || time_data.time_list.length === 0) {
|
||||
const errorContainer = document.getElementById('errorContainer');
|
||||
errorContainer.innerHTML = '至少添加一个时间段';
|
||||
return;
|
||||
}
|
||||
|
||||
if (time_data.time_list.length > maxEntries) {
|
||||
const errorContainer = document.getElementById('errorContainer');
|
||||
errorContainer.innerHTML = '时间段不能超过64条';
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Time Rules:', time_data);
|
||||
const data = {
|
||||
data: time_data
|
||||
}
|
||||
new XHR().post('<%=url('admin/network/set_app_filter_time')%>', data,
|
||||
function (x, data) {
|
||||
init_data();
|
||||
const modal = document.getElementById('modal');
|
||||
modal.style.display = 'flex'; // 显示模态框
|
||||
setTimeout(() => {
|
||||
modal.style.display = 'none'; // 3秒后自动隐藏模态框
|
||||
}, 1000); }
|
||||
);
|
||||
const data = {
|
||||
data: time_data
|
||||
};
|
||||
new XHR().post('<%=url('admin/network/set_app_filter_time')%>', data,
|
||||
function (x, data) {
|
||||
init_data();
|
||||
const modal = document.getElementById('modal');
|
||||
modal.style.display = 'flex';
|
||||
setTimeout(() => {
|
||||
modal.style.display = 'none';
|
||||
}, 1000);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
|
@ -255,7 +265,6 @@
|
|||
document.getElementById('modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// 新增获取过滤开关和工作模式数据的函数
|
||||
function getAppFilterBaseData() {
|
||||
console.log("getAppFilterBaseData");
|
||||
new XHR().get('<%=url('admin/network/get_app_filter_base')%>', null,
|
||||
|
@ -265,7 +274,6 @@
|
|||
} else {
|
||||
document.getElementById('filterSwitch').checked = false;
|
||||
}
|
||||
// 直接使用接口返回的work_mode值来设置选中的选项
|
||||
document.getElementById('workMode').value = data.data.work_mode;
|
||||
console.log("Base filter settings loaded");
|
||||
}
|
||||
|
@ -278,9 +286,18 @@
|
|||
row.innerHTML = `
|
||||
<td><input type="time" class="start-time" required></td>
|
||||
<td><input type="time" class="end-time" required></td>
|
||||
<td><button class="delete-time-btn" onclick="deleteTimeRow(this)">删除</button></td>
|
||||
<td><button type="button" class="delete-time-btn" onclick="deleteTimeRow(this)">删除</button></td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
|
||||
setTimeout(() => {
|
||||
const startTimeInput = row.querySelector('.start-time');
|
||||
const endTimeInput = row.querySelector('.end-time');
|
||||
startTimeInput.value = "00:00";
|
||||
endTimeInput.value = "23:59";
|
||||
}, 0);
|
||||
|
||||
addTimeValidation();
|
||||
}
|
||||
|
||||
function deleteTimeRow(btn) {
|
||||
|
@ -317,14 +334,14 @@
|
|||
weekday_list: weekdays
|
||||
};
|
||||
|
||||
if (mode === "0") { // 固定时间模式
|
||||
if (mode === "0") {
|
||||
const time_list = Array.from(document.getElementById('timeTableBody').rows)
|
||||
.map(row => ({
|
||||
start: row.querySelector('.start-time').value,
|
||||
end: row.querySelector('.end-time').value
|
||||
}));
|
||||
timeData.time_list = time_list;
|
||||
} else { // 动态时间模式
|
||||
} else {
|
||||
timeData.start_time = document.getElementById('startTime').value;
|
||||
timeData.end_time = document.getElementById('endTime').value;
|
||||
timeData.allow_time = parseInt(document.getElementById('allowTime').value);
|
||||
|
@ -339,30 +356,66 @@
|
|||
element.nextElementSibling.classList.toggle('expanded');
|
||||
}
|
||||
|
||||
function addTimeValidation() {
|
||||
document.querySelectorAll('.start-time, .end-time').forEach(input => {
|
||||
input.addEventListener('blur', validateTime);
|
||||
});
|
||||
}
|
||||
|
||||
function validateTime(event) {
|
||||
const row = event.target.closest('tr');
|
||||
const startTimeInput = row.querySelector('.start-time');
|
||||
const endTimeInput = row.querySelector('.end-time');
|
||||
|
||||
const startTime = startTimeInput.value;
|
||||
const endTime = endTimeInput.value;
|
||||
|
||||
const errorContainer = document.getElementById('errorContainer');
|
||||
errorContainer.innerHTML = '';
|
||||
|
||||
let errorMessage = '';
|
||||
|
||||
if (!isValidTimeFormat(startTime) || !isValidTimeFormat(endTime)) {
|
||||
errorMessage = '时间格式不合法,请输入有效的时间格式 (HH:MM)';
|
||||
} else if (startTime >= endTime) {
|
||||
errorMessage = '结束时间必须大于开始时间';
|
||||
}
|
||||
|
||||
if (errorMessage) {
|
||||
const errorElement = document.createElement('div');
|
||||
errorElement.className = 'error-message';
|
||||
errorElement.style.color = 'red';
|
||||
errorElement.style.fontSize = '12px';
|
||||
errorElement.textContent = errorMessage;
|
||||
errorContainer.appendChild(errorElement);
|
||||
}
|
||||
}
|
||||
|
||||
function isValidTimeFormat(time) {
|
||||
const timePattern = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
||||
return timePattern.test(time);
|
||||
}
|
||||
|
||||
function renderTimeData() {
|
||||
// Set mode
|
||||
const timeMode = document.getElementById('timeMode');
|
||||
timeMode.value = time_data.mode
|
||||
toggleModeContent();
|
||||
timeMode.value = time_data.mode;
|
||||
|
||||
// Set weekday checkboxes based on mode
|
||||
// Clear previous selections
|
||||
document.querySelectorAll('input[name="weekday"]').forEach(cb => cb.checked = false);
|
||||
|
||||
// Set weekday checkboxes for both modes
|
||||
time_data.weekday_list.forEach(day => {
|
||||
if (time_data.mode === 0) {
|
||||
// For static mode, set checkboxes in staticWeekdaySelector
|
||||
const checkbox = document.querySelector('#staticWeekdaySelector input[name="weekday"][value="' + day + '"]');
|
||||
if (checkbox) checkbox.checked = true;
|
||||
} else {
|
||||
// For dynamic mode, set checkboxes in advanced-content
|
||||
const checkbox = document.querySelector('.advanced-content input[name="weekday"][value="' + day + '"]');
|
||||
if (checkbox) checkbox.checked = true;
|
||||
}
|
||||
const staticCheckbox = document.querySelector(`#staticWeekdaySelector input[name="weekday"][value="${day}"]`);
|
||||
const dynamicCheckbox = document.querySelector(`.advanced-content input[name="weekday"][value="${day}"]`);
|
||||
if (staticCheckbox) staticCheckbox.checked = true;
|
||||
if (dynamicCheckbox) dynamicCheckbox.checked = true;
|
||||
});
|
||||
|
||||
if (time_data.mode === 0) {
|
||||
// Render time ranges
|
||||
const tbody = document.getElementById('timeTableBody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
// Render static mode data
|
||||
const tbody = document.getElementById('timeTableBody');
|
||||
tbody.innerHTML = '';
|
||||
if (time_data.time_list) {
|
||||
time_data.time_list.forEach(timeRange => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
|
@ -372,27 +425,60 @@
|
|||
`;
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
} else { // 动态时间模式
|
||||
if (time_data.start_time || time_data.end_time) {
|
||||
// If we have time data, expand the advanced settings
|
||||
const advancedToggle = document.querySelector('.advanced-toggle');
|
||||
if (advancedToggle) {
|
||||
toggleAdvanced(advancedToggle);
|
||||
}
|
||||
}
|
||||
if (time_data.start_time) {
|
||||
document.getElementById('startTime').value = time_data.start_time;
|
||||
}
|
||||
if (time_data.end_time) {
|
||||
document.getElementById('endTime').value = time_data.end_time;
|
||||
}
|
||||
if (time_data.allow_time) {
|
||||
document.getElementById('allowTime').value = time_data.allow_time;
|
||||
}
|
||||
if (time_data.deny_time) {
|
||||
document.getElementById('denyTime').value = time_data.deny_time;
|
||||
}
|
||||
}
|
||||
|
||||
// Render dynamic mode data
|
||||
if (time_data.start_time) {
|
||||
document.getElementById('startTime').value = time_data.start_time;
|
||||
}
|
||||
if (time_data.end_time) {
|
||||
document.getElementById('endTime').value = time_data.end_time;
|
||||
}
|
||||
if (time_data.allow_time) {
|
||||
document.getElementById('allowTime').value = time_data.allow_time;
|
||||
}
|
||||
if (time_data.deny_time) {
|
||||
document.getElementById('denyTime').value = time_data.deny_time;
|
||||
}
|
||||
|
||||
// Ensure the correct content is displayed based on the mode
|
||||
toggleModeContent();
|
||||
|
||||
// Add validation to time inputs
|
||||
addTimeValidation();
|
||||
|
||||
|
||||
}
|
||||
|
||||
function validateDynamicTime() {
|
||||
const startTimeInput = document.getElementById('startTime');
|
||||
const endTimeInput = document.getElementById('endTime');
|
||||
const dynamicErrorContainer = document.getElementById('dynamicErrorContainer');
|
||||
dynamicErrorContainer.innerHTML = ''; // 清空之前的错误信息
|
||||
|
||||
const startTime = startTimeInput.value;
|
||||
const endTime = endTimeInput.value;
|
||||
let errorMessage = '';
|
||||
|
||||
if (!isValidTimeFormat(startTime) || !isValidTimeFormat(endTime)) {
|
||||
errorMessage = '时间格式不合法,请输入有效的时间格式 (HH:MM)';
|
||||
} else if (startTime >= endTime) {
|
||||
errorMessage = '结束时间必须大于开始时间';
|
||||
}
|
||||
|
||||
if (errorMessage) {
|
||||
const errorElement = document.createElement('div');
|
||||
errorElement.className = 'error-message';
|
||||
errorElement.style.color = 'red';
|
||||
errorElement.style.fontSize = '12px';
|
||||
errorElement.textContent = errorMessage;
|
||||
dynamicErrorContainer.appendChild(errorElement);
|
||||
}
|
||||
}
|
||||
|
||||
function isValidTimeFormat(time) {
|
||||
const timePattern = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
||||
return timePattern.test(time);
|
||||
}
|
||||
|
||||
window.onload = init_data;
|
||||
|
@ -434,7 +520,7 @@
|
|||
<div class="weekday-item"><input type="checkbox" name="weekday" value="6"> 周六</div>
|
||||
<div class="weekday-item"><input type="checkbox" name="weekday" value="0"> 周日</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 固定时间模式内容 -->
|
||||
<div id="staticTimeContent">
|
||||
<table class="time-table">
|
||||
|
@ -447,26 +533,28 @@
|
|||
</thead>
|
||||
<tbody id="timeTableBody">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</table>
|
||||
<div id="errorContainer" style="color: red; font-size: 12px; margin-top: 10px;"></div>
|
||||
<button class="add-time-btn" onclick="addTimeRow()">添加时间段</button>
|
||||
</div>
|
||||
|
||||
<!-- 动态时间模式内容 -->
|
||||
<div id="dynamicTimeContent" style="display: none;">
|
||||
<div style="color: #666; font-size: 13px; margin-bottom: 15px;">
|
||||
动态时间是指动态调整应用过滤开关,比如小孩学习1个小时后奖励20分钟玩游戏
|
||||
动态时间模式是指动态调整应用过滤开关,比如小孩学习1个小时后奖励20分钟玩游戏,超过娱乐时间后自动开启过滤,反复循环。
|
||||
</div>
|
||||
|
||||
<div class="dynamic-time-settings">
|
||||
<div class="setting-item">
|
||||
<label>每次启用时长(学习时间):</label>
|
||||
<input type="number" id="denyTime" min="1" value="5">
|
||||
<input type="number" id="denyTime" min="1" value="60">
|
||||
<span>分钟</span>
|
||||
</div>
|
||||
<div class="setting-item" style="margin-bottom: 15px;">
|
||||
<label>每次关闭时长(课余时间):</label>
|
||||
<input type="number" id="allowTime" min="1" value="30">
|
||||
<input type="number" id="allowTime" min="1" value="10">
|
||||
<span>分钟</span>
|
||||
</div>
|
||||
|
||||
|
@ -490,9 +578,9 @@
|
|||
|
||||
<div class="setting-item">
|
||||
<label>每天学习时间范围:</label>
|
||||
<input type="time" id="startTime" required style="margin-right: 5px;">
|
||||
<input type="time" id="startTime" required style="margin-right: 5px;" onchange="validateDynamicTime()">
|
||||
<span>-</span>
|
||||
<input type="time" id="endTime" required style="margin-left: 5px;">
|
||||
<input type="time" id="endTime" required style="margin-left: 5px;" onchange="validateDynamicTime()">
|
||||
</div>
|
||||
<div class="setting-item" style="color: #666; font-size: 12px; margin-top: 5px;">
|
||||
<span>该时间范围表示每天上学的时间段,是一段连续时间,在该时间段内实行过滤规则动态开启关闭,时间范围外默认关闭过滤</span>
|
||||
|
@ -500,6 +588,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dynamicErrorContainer" style="color: red; font-size: 12px; margin-top: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -359,7 +359,7 @@
|
|||
|
||||
|
||||
<div id="modal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 1000; justify-content: center; align-items: center;">
|
||||
<div style="background-color: rgba(0, 0, 0, 0.5); padding: 10px; border-radius: 5px; text-align: center; width: 100px; height: 70px; color: white; display: flex; justify-content: center; align-items: center;">
|
||||
<div style="background-color: rgba(0, 0, 0, 0.5); padding: 10px; border-radius: 5px; text-align: center; width: 130px; height: 70px; color: white; display: flex; justify-content: center; align-items: center;">
|
||||
<p style="margin: 0;">设置成功</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -106,6 +106,9 @@
|
|||
|
||||
var tr = tb.insertRow(-1);
|
||||
tr.className = 'tr';
|
||||
if (user_list[i].online != 1) {
|
||||
tr.style.color = '#A9A9A9'; // 设置离线行的字体颜色为浅灰色
|
||||
}
|
||||
tr.insertCell(-1).innerHTML = `
|
||||
<div style="display: flex; align-items: center;">
|
||||
<div>
|
||||
|
@ -123,7 +126,9 @@
|
|||
return `<img src="<%=resource%>/app_icons/${app.id}.png" alt="${app.name}" title="${app.name}" style="width: 20px; height: 20px; border-radius: 5px; margin-right: 8px;">`;
|
||||
}).join("") || "--";
|
||||
tr.insertCell(-1).innerHTML = app_list_str;
|
||||
tr.insertCell(-1).innerHTML = user_list[i].online == 1 ? "<%:Online%>" : "<%:Offline%>";
|
||||
tr.insertCell(-1).innerHTML = user_list[i].online == 1
|
||||
? `<span style="color: green;"><%:Online%></span>`
|
||||
: "<%:Offline%>";
|
||||
tr.insertCell(-1).innerHTML = `
|
||||
<button type="button" class="cbi-button cbi-button-add" onclick="showDetails('${user_list[i].mac}')" style="margin-right: 5px;">查看详情</button>
|
||||
<button type="button" class="cbi-button cbi-button-add" onclick="showModifyNickname('${user_list[i].mac}')">修改备注</button>
|
||||
|
|
|
@ -122,7 +122,6 @@ int validate_range_value(char *range_str)
|
|||
}
|
||||
else
|
||||
{
|
||||
printk("error, invalid char %x\n", *p);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +316,7 @@ int add_app_feature(int appid, char *name, char *feature)
|
|||
proto = IPPROTO_UDP;
|
||||
else
|
||||
{
|
||||
printk("proto %s is not support\n", proto_str);
|
||||
printk("proto %s is not support, feature = %s\n", proto_str, feature);
|
||||
return -1;
|
||||
}
|
||||
sscanf(src_port_str, "%d", &src_port);
|
||||
|
@ -827,7 +826,7 @@ int af_match_by_pos(flow_info_t *flow, af_feature_node_t *node)
|
|||
}
|
||||
if (strlen(node->search_str) > 0){
|
||||
if (k_memstr(flow->l4_data, node->search_str, flow->l4_len)){
|
||||
printk("match by search str, appid=%d, search_str=%s\n", node->app_id, node->search_str);
|
||||
AF_DEBUG("match by search str, appid=%d, search_str=%s\n", node->app_id, node->search_str);
|
||||
return AF_TRUE;
|
||||
}
|
||||
else{
|
||||
|
@ -938,7 +937,7 @@ int match_feature(flow_info_t *flow)
|
|||
{
|
||||
if (af_match_one(flow, node))
|
||||
{
|
||||
printk("match feature, appid=%d, feature = %s\n", node->app_id, node->feature);
|
||||
AF_LMT_INFO("match feature, appid=%d, feature = %s\n", node->app_id, node->feature);
|
||||
flow->app_id = node->app_id;
|
||||
flow->feature = node;
|
||||
strncpy(flow->app_name, node->app_name, sizeof(flow->app_name) - 1);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
config global global
|
||||
option enable '0'
|
||||
option work_mode '0'
|
||||
option record_enable '1'
|
||||
|
||||
config appfilter appfilter
|
||||
|
||||
|
|
|
@ -170,7 +170,6 @@ appfilter_handle_dev_visit_list(struct ubus_context *ctx, struct ubus_object *ob
|
|||
printf("mac is null\n");
|
||||
return 0;
|
||||
}
|
||||
printf("%s %d\n", __func__, __LINE__);
|
||||
|
||||
char *mac = json_object_get_string(mac_obj);
|
||||
dev_node_t *node = find_dev_node(mac);
|
||||
|
@ -330,6 +329,33 @@ appfilter_handle_visit_list(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
ubus_send_reply(ctx, req, b.head);
|
||||
return 0;
|
||||
}
|
||||
static int handle_debug(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
int ret;
|
||||
blob_buf_init(&b, 0);
|
||||
char *msg_obj_str = blobmsg_format_json(msg, true);
|
||||
if (!msg_obj_str)
|
||||
{
|
||||
printf("format json failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct json_object *req_obj = json_tokener_parse(msg_obj_str);
|
||||
struct json_object *debug_obj = json_object_object_get(req_obj, "debug");
|
||||
|
||||
if (debug_obj)
|
||||
{
|
||||
current_log_level = json_object_get_int(debug_obj);
|
||||
LOG_WARN("debug level set to %d\n", current_log_level);
|
||||
}
|
||||
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct app_visit_time_info
|
||||
{
|
||||
|
@ -992,7 +1018,9 @@ void all_users_callback(void *arg, dev_node_t *dev)
|
|||
|
||||
struct json_object *user_obj = json_object_new_object();
|
||||
json_object_object_add(user_obj, "mac", json_object_new_string(dev->mac));
|
||||
json_object_object_add(user_obj, "online", json_object_new_int(1));
|
||||
json_object_object_add(user_obj, "online", json_object_new_int(dev->online));
|
||||
json_object_object_add(user_obj, "online_time", json_object_new_int(dev->online_time));
|
||||
json_object_object_add(user_obj, "offline_time", json_object_new_int(dev->offline_time));
|
||||
|
||||
if (flag > 0) {
|
||||
json_object_object_add(user_obj, "ip", json_object_new_string(dev->ip));
|
||||
|
@ -1025,11 +1053,46 @@ void all_users_callback(void *arg, dev_node_t *dev)
|
|||
json_object_array_add(users_array, user_obj);
|
||||
}
|
||||
|
||||
int compare_users(const void *a, const void *b)
|
||||
{
|
||||
struct json_object *user_a = *(struct json_object **)a;
|
||||
struct json_object *user_b = *(struct json_object **)b;
|
||||
|
||||
struct json_object *online_a, *online_b;
|
||||
json_object_object_get_ex(user_a, "online", &online_a);
|
||||
json_object_object_get_ex(user_b, "online", &online_b);
|
||||
|
||||
int online_val_a = json_object_get_int(online_a);
|
||||
int online_val_b = json_object_get_int(online_b);
|
||||
|
||||
if (online_val_a != online_val_b)
|
||||
return online_val_b - online_val_a;
|
||||
|
||||
struct json_object *online_time_a, *online_time_b;
|
||||
json_object_object_get_ex(user_a, "online_time", &online_time_a);
|
||||
json_object_object_get_ex(user_b, "online_time", &online_time_b);
|
||||
|
||||
int online_time_val_a = json_object_get_int(online_time_a);
|
||||
int online_time_val_b = json_object_get_int(online_time_b);
|
||||
|
||||
if (online_val_a == 1 && online_val_b == 1) {
|
||||
// Both are online, sort by online_time
|
||||
return online_time_val_a - online_time_val_b;
|
||||
} else {
|
||||
// Both are offline, sort by offline_time
|
||||
struct json_object *offline_time_a, *offline_time_b;
|
||||
json_object_object_get_ex(user_a, "offline_time", &offline_time_a);
|
||||
json_object_object_get_ex(user_b, "offline_time", &offline_time_b);
|
||||
|
||||
int offline_time_val_a = json_object_get_int(offline_time_a);
|
||||
int offline_time_val_b = json_object_get_int(offline_time_b);
|
||||
|
||||
return offline_time_val_a - offline_time_val_b;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_get_all_users(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
|
||||
struct blob_attr *msg) {
|
||||
struct json_object *response = json_object_new_object();
|
||||
struct json_object *data_obj = json_object_new_object();
|
||||
|
@ -1065,6 +1128,9 @@ static int handle_get_all_users(struct ubus_context *ctx, struct ubus_object *ob
|
|||
update_dev_nickname();
|
||||
|
||||
dev_foreach(&au_info, all_users_callback);
|
||||
|
||||
// 对 users_array 进行排序
|
||||
json_object_array_sort(au_info.users_array, compare_users);
|
||||
|
||||
json_object_object_add(data_obj, "list", au_info.users_array);
|
||||
|
||||
|
@ -1409,8 +1475,12 @@ static struct ubus_method appfilter_object_methods[] = {
|
|||
UBUS_METHOD("add_app_filter_user", handle_add_app_filter_user, empty_policy),
|
||||
UBUS_METHOD("set_nickname", handle_set_nickname, empty_policy),
|
||||
UBUS_METHOD("get_oaf_status", handle_get_oaf_status, empty_policy),
|
||||
UBUS_METHOD("debug", handle_debug, empty_policy),
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static struct ubus_object_type main_object_type =
|
||||
UBUS_OBJECT_TYPE("appfilter", appfilter_object_methods);
|
||||
|
||||
|
|
|
@ -177,8 +177,14 @@ void update_dev_hostname(void)
|
|||
sscanf(line_buf, "%*s %s %s %s", mac_buf, ip_buf, hostname_buf);
|
||||
dev_node_t *node = find_dev_node(mac_buf);
|
||||
if (!node)
|
||||
continue;
|
||||
if (strlen(hostname_buf) > 0)
|
||||
{
|
||||
node = add_dev_node(mac_buf);
|
||||
strncpy(node->ip, ip_buf, sizeof(node->ip));
|
||||
node->online = 0;
|
||||
node->offline_time = get_timestamp();
|
||||
}
|
||||
|
||||
if (strlen(hostname_buf) > 0 && hostname_buf[0] != '*')
|
||||
{
|
||||
strncpy(node->hostname, hostname_buf, sizeof(node->hostname));
|
||||
}
|
||||
|
@ -365,7 +371,7 @@ int check_dev_expire(void)
|
|||
}
|
||||
}
|
||||
expire_count++;
|
||||
printf("dev:%s expired, offline time = %ds, count=%d, visit_count=%d\n",
|
||||
LOG_WARN("dev:%s expired, offline time = %ds, count=%d, visit_count=%d\n",
|
||||
node->mac, offline_time, expire_count, visit_count);
|
||||
}
|
||||
NEXT:
|
||||
|
@ -430,8 +436,6 @@ void dump_dev_list(void)
|
|||
char hostname_buf[MAX_HOSTNAME_SIZE] = {0};
|
||||
char ip_buf[MAX_IP_LEN] = {0};
|
||||
|
||||
|
||||
|
||||
FILE *fp = fopen(OAF_DEV_LIST_FILE, "w");
|
||||
if (!fp)
|
||||
{
|
||||
|
|
|
@ -126,6 +126,12 @@ void af_load_global_config(af_global_config_t *config){
|
|||
else
|
||||
config->enable = ret;
|
||||
|
||||
ret = af_uci_get_int_value(ctx, "appfilter.global.record_enable");
|
||||
if (ret < 0)
|
||||
config->record_enable = 0;
|
||||
else
|
||||
config->record_enable = ret;
|
||||
|
||||
ret = af_uci_get_int_value(ctx, "appfilter.global.user_mode");
|
||||
if (ret < 0)
|
||||
config->user_mode = 0;
|
||||
|
@ -291,7 +297,6 @@ void dev_list_timeout_handler(struct uloop_timeout *t)
|
|||
count++;
|
||||
if (count % 10 == 0){
|
||||
update_dev_list();
|
||||
dump_dev_list();
|
||||
}
|
||||
if (count % 60 == 0){
|
||||
check_dev_visit_info_expire();
|
||||
|
@ -301,6 +306,7 @@ void dev_list_timeout_handler(struct uloop_timeout *t)
|
|||
}
|
||||
flush_expire_visit_info();
|
||||
update_oaf_status();
|
||||
dump_dev_list();
|
||||
}
|
||||
if (g_oaf_config_change == 1){
|
||||
update_lan_ip();
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=v2rayA
|
||||
PKG_VERSION:=2.2.6.3
|
||||
PKG_VERSION:=2.2.6.4
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/v2rayA/v2rayA/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=62add8605c42e8e91b5fae22e3b05d146cdeea8fec44089fc1bf0ae29fc76dc0
|
||||
PKG_HASH:=801873bb5d8f3fe3d27b26b8b9b4876d7dbd4ffee433344169cc5ebf8070499d
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/service
|
||||
|
||||
PKG_LICENSE:=AGPL-3.0-only
|
||||
|
@ -60,7 +60,7 @@ define Download/v2raya-web
|
|||
URL:=https://github.com/v2rayA/v2rayA/releases/download/v$(PKG_VERSION)/
|
||||
URL_FILE:=web.tar.gz
|
||||
FILE:=$(WEB_FILE)
|
||||
HASH:=e8bca04deaec72e3323310bc114fa4936474adcbb6638ec2e31dbdf88beabdae
|
||||
HASH:=7625e71d9592855dc283b28eabd740d2c2851c7755e893005fc57aca03f9760f
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
|
|
Loading…
Reference in New Issue