增加模式

This commit is contained in:
snltty
2024-04-04 01:46:14 +08:00
parent fbb35a6518
commit 6cbb14901e
85 changed files with 1795 additions and 1649 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="D:\desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.19" ProductVersion="0.0.0.19" publishDir="/dist/" dstrip="false">
<project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="D:\desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.22" ProductVersion="0.0.0.22" publishDir="/dist/" dstrip="false">
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true"/>
<folder name="窗体文件" path="dlg" comment="目录" embed="true"/>

View File

@@ -3,10 +3,12 @@ using cmonitor.viewer.server.win.Properties;
using common.libs;
using Microsoft.Win32;
using RDPCOMAPILib;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Resources;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace cmonitor.viewer.server.win
{
@@ -152,6 +154,16 @@ namespace cmonitor.viewer.server.win
IRDPSRAPIInvitation invitation = session.Invitations.CreateInvitation(Guid.NewGuid().ToString(), "snltty", "snltty", 1024);
string invitationString = invitation.ConnectionString;
/*
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(invitationString);
XmlElement newLNode = xmlDoc.CreateElement("L");
newLNode.SetAttribute("P", "12345");
newLNode.SetAttribute("N", "192.168.1.35");
xmlDoc.DocumentElement["C"]["T"].AppendChild(newLNode);
Debug.WriteLine(xmlDoc.OuterXml);
*/
Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", invitationString);
notifyIcon.Icon = Icon.FromHandle(Resources.logo_share_green.GetHicon());

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>net7.0-windows;net8.0-windows</TargetFrameworks>
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
<Nullable>disable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>

View File

@@ -10,29 +10,15 @@ export const getActiveWindows = (name) => {
export const activeTimesClear = (name) => {
return sendWebsocketMsg('active/clear', name);
}
export const activeDisallow = (names, filenames, ids) => {
export const activeDisallow = (names, filenames, ids1, ids2) => {
return sendWebsocketMsg('active/disallow', {
usernames: names, filenames, ids: ids || []
devices: names, data: filenames, ids1: ids1 || [], ids2: ids2 || []
});
}
export const activeAddGroup = (data) => {
return sendWebsocketMsg('active/AddGroup', data);
}
export const activeDelGroup = (username, id) => {
return sendWebsocketMsg('active/DeleteGroup', {
username, id
});
}
export const activeAdd = (data) => {
return sendWebsocketMsg('active/add', data);
}
export const activeDel = (username, groupid, id) => {
return sendWebsocketMsg('active/del', {
username, groupid, id
});
export const activeUpdate = (data) => {
return sendWebsocketMsg('active/update', data);
}
export const activeKill = (username, pid) => {

View File

@@ -0,0 +1,5 @@
import { sendWebsocketMsg } from './request'
export const updateDevices = (data) => {
return sendWebsocketMsg('devices/Update', data);
}

View File

@@ -6,31 +6,16 @@ export const getRules = () => {
export const addName = (data) => {
return sendWebsocketMsg('hijack/addName', data);
}
export const addProcessGroup = (data) => {
return sendWebsocketMsg('hijack/addProcessGroup', data);
}
export const deleteProcessGroup = (data) => {
return sendWebsocketMsg('hijack/deleteProcessGroup', data);
}
export const addProcess = (data) => {
return sendWebsocketMsg('hijack/addProcess', data);
}
export const deleteProcess = (data) => {
return sendWebsocketMsg('hijack/deleteProcess', data);
export const updateProcess = (data) => {
return sendWebsocketMsg('hijack/UpdateProcess', data);
}
export const addRule = (data) => {
return sendWebsocketMsg('hijack/AddRule', data);
}
export const deleteRule = (data) => {
return sendWebsocketMsg('hijack/deleteRule', data);
export const updateRule = (data) => {
return sendWebsocketMsg('hijack/UpdateRule', data);
}
export const updateDevices = (data) => {
return sendWebsocketMsg('hijack/UpdateDevices', data);
}
export const setRules = (data) => {
return sendWebsocketMsg('hijack/setRules', data);
return sendWebsocketMsg('hijack/UseHijackRules', data);
}

View File

@@ -0,0 +1,10 @@
import { sendWebsocketMsg } from './request'
export const updateModes = (data) => {
return sendWebsocketMsg('modes/update', data);
}
export const useModes = (names, data, ids1, ids2, path) => {
return sendWebsocketMsg(path, {
devices: names, data: data, ids1: ids1, ids2: ids2
});
}

View File

@@ -0,0 +1,8 @@
import { sendWebsocketMsg } from './request'
export const getRules = () => {
return sendWebsocketMsg('rule/info');
}
export const addName = (data) => {
return sendWebsocketMsg('rule/addname', data);
}

View File

@@ -1,8 +0,0 @@
import { sendWebsocketMsg } from './request'
export const getSetting = () => {
return sendWebsocketMsg('setting/get');
}
export const saveSetting = (setting) => {
return sendWebsocketMsg('setting/set', setting);
}

View File

@@ -1,23 +1,9 @@
import { sendWebsocketMsg } from './request'
export const addGroup = (data) => {
return sendWebsocketMsg('snatch/AddGroup', data);
}
export const delGroup = (username, id) => {
return sendWebsocketMsg('snatch/DeleteGroup', {
username, id
});
export const updateSnatch = (data) => {
return sendWebsocketMsg('snatch/update', data);
}
export const add = (data) => {
return sendWebsocketMsg('snatch/add', data);
}
export const del = (username, groupid, id) => {
return sendWebsocketMsg('snatch/del', {
username, groupid, id
});
}
export const getQuestion = (name) => {
return sendWebsocketMsg('snatch/getQuestion', name);
@@ -25,18 +11,11 @@ export const getQuestion = (name) => {
export const addQuestion = (question) => {
return sendWebsocketMsg('snatch/addQuestion', question);
}
export const removeQuestion = (name) => {
return sendWebsocketMsg('snatch/removeQuestion', name);
}
export const randomQuestion = (length) => {
return sendWebsocketMsg('snatch/RandomQuestion', length);
}
export const updateQuestion = (userName, items) => {
return sendWebsocketMsg('snatch/UpdateQuestion', {
userName, items
});
}
export const removeQuestion = (name) => {
return sendWebsocketMsg('snatch/removeQuestion', name);
}

View File

@@ -1,9 +1,7 @@
import { sendWebsocketMsg } from './request'
export const updateRegistryOptions = (names, keys, value) => {
export const updateRegistryOptions = (names, keys) => {
return sendWebsocketMsg('system/RegistryOptions', {
names, registry: {
keys: keys, value: value
}
devices: names, data: keys
});
}

View File

@@ -24,7 +24,7 @@
<script>
import { computed, onMounted, reactive, watch } from 'vue';
import { initWebsocket, subWebsocketState } from '../apis/request'
import { getRules, addName } from '../apis/hijack'
import { getRules, addName } from '../apis/rule'
import { useRoute } from 'vue-router';
import { injectGlobalData } from './provide';
export default {
@@ -41,6 +41,7 @@ export default {
});
localStorage.setItem('api', state.api);
globalData.value.username = state.username;
const showSelectUsername = computed(() => !!!globalData.value.username && globalData.value.connected);
const showPort = computed(() => globalData.value.connected == false && state.showPort);
@@ -54,8 +55,13 @@ export default {
const _getRules = () => {
getRules().then((res) => {
globalData.value.usernames = res;
state.usernames = Object.keys(res);
for (let j in res.Data) {
for (let jj in res.Data[j]) {
res.Data[j][jj] = JSON.parse(res.Data[j][jj]);
}
}
globalData.value.usernames = res.Data;
state.usernames = Object.keys(res.Data);
}).catch(() => { });
}
const handleConnect = () => {

View File

@@ -45,12 +45,11 @@ export default {
checkAll: false,
isIndeterminate: false
});
/*
watch(() => props.items, () => {
state.checkList = props.items.map(c => c[props.label]);
updateCheckAll(state.checkList);
})
*/
const handleCheckAllChange = (value) => {
if (value) {

View File

@@ -6,7 +6,7 @@
<p>文件:{{state.filename}}</p>
<p class="t-c">
<el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem">
<el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" />
<el-option v-for="item in state.groups" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
</p>
</div>
@@ -23,7 +23,7 @@ import { computed, onMounted, watch } from '@vue/runtime-core';
import { injectPluginState } from '../../provide'
import { injectGlobalData } from '@/views/provide';
import { ElMessage } from 'element-plus';
import { activeAdd } from '@/apis/active';
import { activeUpdate } from '@/apis/active';
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
@@ -34,15 +34,15 @@ export default {
const globalData = injectGlobalData();
const state = reactive({
show: props.modelValue,
group: 0,
group: '',
title: '',
desc: '',
filename: '',
groups: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user) {
if (user.Windows.length > 0 && state.group == 0) {
state.group = user.Windows[0].ID;
if (user.Windows.length > 0 && state.group == '') {
state.group = user.Windows[0].Name;
}
return user.Windows;
}
@@ -80,25 +80,33 @@ export default {
state.show = false;
}
const handleSubmit = () => {
activeAdd({
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
const group = windows.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Name);
if (names.indexOf(state.filename) >= 0) {
ElMessage.error('已存在同名');
return;
}
items.push({ Name: state.filename, Desc: state.desc });
globalData.value.usernames[globalData.value.username].Windows = windows;
activeUpdate({
username: globalData.value.username,
GroupID: state.group,
Item: {
ID: 0,
Name: state.filename,
Desc: state.desc
}
Data: windows
}).then((error) => {
if (!error) {
ElMessage.success('操作成功');
state.show = false;
globalData.value.updateRuleFlag = Date.now();
state.show = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.error(`操作失败:${error}`);
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
}).catch(() => {
ElMessage.error('操作失败');
});
}).catch((e) => {
ElMessage.error('操作失败!');
})
}
return {

View File

@@ -8,12 +8,12 @@
<div class="flex-1"></div>
<div class="Exes flex flex-column">
<div class="private">
<CheckBoxWrap ref="privateExes" :data="state.privateExes" :items="state.currentPrivate" label="ID" text="Name" title="私有窗口">
<CheckBoxWrap ref="privateExes" :data="state.privateExes" :items="state.currentPrivate" label="Name" text="Name" title="私有窗口">
</CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="public">
<CheckBoxWrap ref="publicExes" :data="state.publicExes" :items="state.currentPublic" label="ID" text="Name" title="公共窗口">
<CheckBoxWrap ref="publicExes" :data="state.publicExes" :items="state.currentPublic" label="Name" text="Name" title="公共窗口">
</CheckBoxWrap>
</div>
</div>
@@ -27,7 +27,7 @@
<script>
import { reactive, ref } from '@vue/reactivity';
import { computed, onMounted, watch } from '@vue/runtime-core';
import { computed, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { ElMessage, ElMessageBox } from 'element-plus';
import { activeDisallow } from '@/apis/active'
@@ -50,12 +50,16 @@ export default {
show: props.modelValue,
items: computed(() => {
const devices = pluginState.value.activeWindow.devices;
let ids = devices.reduce((arr, value) => {
arr.push(...value.ActiveWindow.DisallowRunIds);
let ids1 = devices.reduce((arr, value) => {
arr.push(...value.ActiveWindow.DisallowRunIds1);
return arr;
}, []);
state.currentPrivate = state.privateExes.filter(c => ids.indexOf(c.ID) >= 0);
state.currentPublic = state.publicExes.filter(c => ids.indexOf(c.ID) >= 0);
let ids2 = devices.reduce((arr, value) => {
arr.push(...value.ActiveWindow.DisallowRunIds2);
return arr;
}, []);
state.currentPrivate = state.privateExes.filter(c => ids1.indexOf(c.Name) >= 0);
state.currentPublic = state.publicExes.filter(c => ids2.indexOf(c.Name) >= 0);
return devices;
}),
privateExes: computed(() => user.value ? user.value.Windows : []),
@@ -76,10 +80,10 @@ export default {
const privateExes = ref(null);
const publicExes = ref(null);
const parseRule = () => {
const _privateIds = privateExes.value.getData().map(c => c.ID);
const _privateExes = state.privateExes.filter(c => _privateIds.indexOf(c.ID) >= 0);
const _publicIds = publicExes.value.getData().map(c => c.ID);
const _publicExes = state.publicExes.filter(c => _publicIds.indexOf(c.ID) >= 0);
const _privateIds = privateExes.value.getData().map(c => c.Name);
const _privateExes = state.privateExes.filter(c => _privateIds.indexOf(c.Name) >= 0);
const _publicIds = publicExes.value.getData().map(c => c.Name);
const _publicExes = state.publicExes.filter(c => _publicIds.indexOf(c.Name) >= 0);
const exes = _privateExes.concat(_publicExes).reduce((data, item, index) => {
let arr = item.List.reduce((val, item, index) => {
val = val.concat(item.Name.split(','));
@@ -94,7 +98,8 @@ export default {
}, []);
return {
ids: _privateIds.concat(_publicIds),
ids1: _privateIds,
ids2: _publicIds,
exes: exes
};
}
@@ -112,11 +117,12 @@ export default {
}).then(() => {
state.loading = true;
const exes = parseRule();
activeDisallow(_devices.map(c => c.MachineName), exes.exes, exes.ids).then((res) => {
activeDisallow(_devices.map(c => c.MachineName), exes.exes, exes.ids1, exes.ids2).then((res) => {
state.loading = false;
ElMessage.success('操作成功!');
globalData.value.devices.filter(c => _devices.indexOf(c.MachineName) >= 0).forEach(device => {
device.ActiveWindow.DisallowRunIds = exes.ids;
device.ActiveWindow.DisallowRunIds1 = exes.ids1;
device.ActiveWindow.DisallowRunIds2 = exes.ids2;
});
}).catch((e) => {
state.loading = false;

View File

@@ -0,0 +1,99 @@
<template>
<div class="absolute flex flex-column flex-nowrap">
<div class="flex">
<el-checkbox v-model="state.use">使用规则</el-checkbox>
</div>
<div class="flex flex-1">
<div class="private">
<CheckBoxWrap ref="privateExes" :data="state.privateExes" :items="state.ids1" label="Name" text="Name" title="私有窗口">
</CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="public">
<CheckBoxWrap ref="publicExes" :data="state.publicExes" :items="state.ids2" label="Name" text="Name" title="公共窗口">
</CheckBoxWrap>
</div>
</div>
</div>
</template>
<script>
import { reactive, ref } from '@vue/reactivity';
import { computed, getCurrentInstance, inject, onMounted, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { injectGlobalData } from '@/views/provide';
export default {
label: '窗口',
components: { CheckBoxWrap },
setup(props, { emit }) {
const globalData = injectGlobalData();
const user = computed(() => globalData.value.usernames[globalData.value.username]);
const publicUserName = globalData.value.publicUserName;
const publicUser = computed(() => globalData.value.usernames[publicUserName]);
const usePublic = publicUser.value && globalData.value.username != publicUserName;
const current = getCurrentInstance();
const modeState = inject('mode-state');
const state = reactive({
use: false,
privateExes: computed(() => user.value ? user.value.Windows : []),
publicExes: computed(() => usePublic ? publicUser.value.Windows : []),
ids1: [],
ids2: [],
});
watch(() => modeState.value, () => {
parseMode();
});
onMounted(() => { parseMode(); });
const parseMode = () => {
const json = JSON.parse(modeState.value)[current.type.label] || {};
state.use = json.use || false;
state.ids1 = (json.ids1 || []).map(c => { return { Name: c }; });
state.ids2 = (json.ids2 || []).map(c => { return { Name: c }; });
}
const privateExes = ref(null);
const publicExes = ref(null);
const parseRule = () => {
const _privateIds = privateExes.value.getData().map(c => c.Name);
const _privateExes = state.privateExes.filter(c => _privateIds.indexOf(c.Name) >= 0);
const _publicIds = publicExes.value.getData().map(c => c.Name);
const _publicExes = state.publicExes.filter(c => _publicIds.indexOf(c.Name) >= 0);
const exes = _privateExes.concat(_publicExes).reduce((data, item, index) => {
let arr = item.List.reduce((val, item, index) => {
val = val.concat(item.Name.split(','));
return val;
}, []);
for (let i = 0; i < arr.length; i++) {
if (arr[i] && data.indexOf(arr[i]) == -1) {
data.push(arr[i]);
}
}
return data;
}, []);
return {
path: 'active/disallow',
use: state.use,
ids1: _privateIds,
ids2: _publicIds,
list: exes
};
}
const getData = () => {
return parseRule();
}
return {
state, getData, privateExes, publicExes
}
}
}
</script>
<style lang="stylus" scoped>
.private, .public {
width: 49%;
position: relative;
}
</style>

View File

@@ -7,7 +7,8 @@ export default {
Desc: '',
Pid: 0,
DisallowCount: 0,
DisallowRunIds: [],
DisallowRunIds1: [],
DisallowRunIds2: [],
WindowCount: 0,
}
}
@@ -32,6 +33,7 @@ export default {
item.ActiveWindow.Pid = report.ActiveWindow.Pid;
item.ActiveWindow.DisallowCount = report.ActiveWindow.DisallowCount;
item.ActiveWindow.WindowCount = report.ActiveWindow.WindowCount || 0;
item.ActiveWindow.DisallowRunIds = report.ActiveWindow.Ids || [];
item.ActiveWindow.DisallowRunIds1 = report.ActiveWindow.Ids1 || [];
item.ActiveWindow.DisallowRunIds2 = report.ActiveWindow.Ids2 || [];
}
}

View File

@@ -9,28 +9,26 @@
<el-table-column prop="Name" label="名称" />
<el-table-column label="操作" width="110">
<template #default="scope">
<template v-if="scope.row.ID > 1">
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<el-dialog :title="`${state.currentItem.Name1?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<div>
<el-input v-model="state.currentItem.Name" size="large" placeholder="分组名称" />
</div>
@@ -46,7 +44,7 @@
import { reactive } from '@vue/reactivity';
import { computed } from '@vue/runtime-core';
import { ElMessage } from 'element-plus';
import { activeAddGroup, activeDelGroup } from '@/apis/active'
import { activeUpdate } from '@/apis/active'
import { injectGlobalData } from '@/views/provide';
export default {
setup() {
@@ -54,14 +52,11 @@ export default {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
currentItem: { ID: 0, Name: '' },
currentItem: { Name: '', Name1: '' },
showEdit: false,
list: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Windows) {
if (state.group == 0 && user.Windows.length > 0) {
state.group = user.Windows[0].ID;
}
return user.Windows;
}
return [];
@@ -69,18 +64,27 @@ export default {
});
const handleAdd = (item) => {
item = item || { Name: '', ID: 0 };
item = item || { Name: '', Name1: '' };
state.currentItem.Name = item.Name;
state.currentItem.ID = item.ID;
state.currentItem.Name1 = item.Name;
state.showEdit = true;
}
const handleDel = (item) => {
const handleEditCancel = () => {
state.showEdit = false;
}
const updateActiveGroup = () => {
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
state.loading = true;
activeDelGroup(globalData.value.username, item.ID).then((error) => {
activeUpdate({
username: globalData.value.username,
Data: windows
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
@@ -89,31 +93,33 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
const handleDel = (item) => {
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
const names = windows.map(c => c.Name);
windows.splice(names.indexOf(item.Name), 1);
globalData.value.usernames[globalData.value.username].Windows = windows;
updateActiveGroup();
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
state.loading = true;
activeAddGroup({
UserName: globalData.value.username,
Group: state.currentItem
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
globalData.value.updateRuleFlag = Date.now();
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
const names = windows.map(c => c.Name);
let index = names.indexOf(state.currentItem.Name1);
if (index == -1) {
if (names.indexOf(state.currentItem.Name) >= 0) {
ElMessage.error('已存在同名');
return;
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
})
windows.push({ Name: state.currentItem.Name })
} else {
windows[index].Name = state.currentItem.Name;
}
globalData.value.usernames[globalData.value.username].Windows = windows;
updateActiveGroup();
}
return { state, handleAdd, handleDel, handleEditCancel, handleEditSubmit }
}

View File

@@ -16,10 +16,9 @@
<script>
import { reactive } from '@vue/reactivity';
import { onMounted, watch } from '@vue/runtime-core';
import { watch } from '@vue/runtime-core';
import Groups from './Groups.vue'
import Items from './Items.vue'
import { injectGlobalData } from '@/views/provide';
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
@@ -38,13 +37,10 @@ export default {
}
});
const globalData = injectGlobalData();
const handleCancel = () => {
state.show = false;
}
return {
state, handleCancel
}

View File

@@ -2,7 +2,7 @@
<div class="windows-items-wrap flex flex-nowrap flex-column">
<div class="head t-c flex">
<el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem">
<el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" />
<el-option v-for="item in state.groups" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
<span class="flex-1"></span>
<el-button @click="handleAdd()">添加项</el-button>
@@ -33,7 +33,7 @@
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<el-dialog :title="`${state.currentItem.Name1==0?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<div>
<p><el-input v-model="state.currentItem.Desc" size="large" placeholder="名称" /></p>
<p style="padding-top:1rem"><el-input v-model="state.currentItem.Name" size="large" placeholder="规则" /></p>
@@ -55,75 +55,57 @@
import { reactive } from '@vue/reactivity';
import { computed } from '@vue/runtime-core';
import { ElMessage } from 'element-plus';
import { activeAdd, activeDel } from '@/apis/active'
import { activeUpdate } from '@/apis/active'
import { injectGlobalData } from '@/views/provide';
export default {
setup() {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
group: 0,
currentItem: { ID: 0, Name: '', Desc: '' },
group: '',
currentItem: { Name: '', Name1: '', Desc: '' },
showEdit: false,
groups: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Windows) {
if (state.group == 0 && user.Windows.length > 0) {
state.group = user.Windows[0].ID;
if (state.group == '' && user.Windows.length > 0) {
state.group = user.Windows[0].Name;
}
return user.Windows;
}
return [];
}),
list: computed(() => {
let group = state.groups.filter(c => c.ID == state.group)[0];
let group = state.groups.filter(c => c.Name == state.group)[0];
if (group) return group.List;
return [];
})
});
const handleAdd = (item) => {
item = item || { Name: '', ID: 0, Desc: '' };
item = item || { Name: '', Name1: '', Desc: '' };
state.currentItem.Name = item.Name;
state.currentItem.Name1 = item.Name;
state.currentItem.Desc = item.Desc;
state.currentItem.ID = item.ID;
state.showEdit = true;
}
const handleDel = (item) => {
state.loading = true;
activeDel(globalData.value.username, state.group, item.ID).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
const updateActiveGroup = () => {
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
state.loading = true;
activeAdd({
UserName: globalData.value.username,
GroupID: state.group,
Item: state.currentItem
activeUpdate({
username: globalData.value.username,
Data: windows
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
}).catch((e) => {
@@ -131,6 +113,45 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleDel = (item) => {
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
const group = windows.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Name);
items.splice(names.indexOf(item.Name), 1);
globalData.value.usernames[globalData.value.username].Windows = windows;
updateActiveGroup();
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
const windows = globalData.value.usernames[globalData.value.username].Windows || [];
const group = windows.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Name);
let index = names.indexOf(state.currentItem.Name1);
if (index == -1) {
if (names.indexOf(state.currentItem.Name) >= 0) {
ElMessage.error('已存在同名');
return;
}
items.push({ Name: state.currentItem.Name, Desc: state.currentItem.Desc })
} else {
items[index].Name = state.currentItem.Name;
items[index].Desc = state.currentItem.Desc;
}
globalData.value.usernames[globalData.value.username].Windows = windows;
updateActiveGroup();
}
return { state, handleAdd, handleDel, handleEditCancel, handleEditSubmit }
}
}

View File

@@ -114,6 +114,18 @@ export default {
&>div {
padding: 0.6rem 0;
}
.item {
padding: 0.6rem;
.subitem {
padding: 0.2rem;
.label {
margin-right: 0.6rem;
}
}
}
}
}

View File

@@ -28,7 +28,7 @@
import { reactive, ref } from '@vue/reactivity';
import { computed, onMounted, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { updateDevices } from '../../../../apis/hijack'
import { updateDevices } from '../../../../apis/devices'
import { delDevice } from '../../../../apis/signin'
import { ElMessage } from 'element-plus';
import { injectGlobalData } from '@/views/provide';
@@ -75,7 +75,7 @@ export default {
state.loading = true;
updateDevices({
username: globalData.value.username,
devices: _devices.map(c => c.MachineName)
data: _devices.map(c => c.MachineName)
}).then((error) => {
state.loading = false;
globalData.value.updateDeviceFlag = Date.now();

View File

@@ -14,11 +14,11 @@
<div class="flex-1"></div>
<div class="rules flex flex-column">
<div class="private">
<CheckBoxWrap ref="privateRules" :data="state.privateRules" :items="state.currentPrivate" label="ID" text="Name" title="私有限制"></CheckBoxWrap>
<CheckBoxWrap ref="privateRules" :data="state.privateRules" :items="state.currentPrivate" label="Name" text="Name" title="私有限制"></CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="public">
<CheckBoxWrap ref="publicRules" :data="state.publicRules" :items="state.currentPublic" label="ID" text="Name" title="公共限制"></CheckBoxWrap>
<CheckBoxWrap ref="publicRules" :data="state.publicRules" :items="state.currentPublic" label="Name" text="Name" title="公共限制"></CheckBoxWrap>
</div>
</div>
</div>
@@ -31,7 +31,7 @@
<script>
import { reactive, ref } from '@vue/reactivity';
import { computed, inject, onMounted, watch } from '@vue/runtime-core';
import { computed, onMounted, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { ElMessage, ElMessageBox } from 'element-plus';
import { setRules } from '../../../../apis/hijack'
@@ -49,21 +49,24 @@ export default {
const publicUserName = globalData.value.publicUserName;
const publicUser = computed(() => globalData.value.usernames[publicUserName]);
const usePublic = publicUser.value && globalData.value.username != publicUserName;
const state = reactive({
show: props.modelValue,
items: computed(() => {
const devices = pluginState.value.hijack.devices;
let ids = devices.reduce((arr, value) => {
arr.push(...value.Hijack.RuleIds);
let ids1 = devices.reduce((arr, value) => {
arr.push(...value.Hijack.RuleIds1);
return arr;
}, []);
state.currentPrivate = state.privateRules.filter(c => ids.indexOf(c.ID) >= 0);
state.currentPublic = state.publicRules.filter(c => ids.indexOf(c.ID) >= 0);
let ids2 = devices.reduce((arr, value) => {
arr.push(...value.Hijack.RuleIds2);
return arr;
}, []);
state.currentPrivate = state.privateRules.filter(c => ids1.indexOf(c.Name) >= 0);
state.currentPublic = state.publicRules.filter(c => ids2.indexOf(c.Name) >= 0);
return devices;
}),
privateRules: computed(() => user.value ? user.value.Rules : []),
publicRules: computed(() => usePublic ? publicUser.value.Rules : []),
privateRules: computed(() => user.value ? user.value.Processs : []),
publicRules: computed(() => usePublic ? publicUser.value.Processs : []),
loading: false,
currentPrivate: [],
currentPublic: [],
@@ -81,23 +84,16 @@ export default {
const privateRules = ref(null);
const publicRules = ref(null);
const parseRule = () => {
const _privateRules = privateRules.value.getData().map(c => c.ID);
const _publicRules = publicRules.value.getData().map(c => c.ID);
const _privateRules = privateRules.value.getData().map(c => c.Name);
const _publicRules = publicRules.value.getData().map(c => c.Name);
const _user = user.value;
const _publicUser = publicUser.value;
const publicList = _user.Rules.filter(c => _privateRules.indexOf(c.ID) >= 0).map(rule => {
return _user.Processs.filter(c => rule.PrivateProcesss.indexOf(c.ID) >= 0);
});
const privateList = _publicUser.Rules.filter(c => _publicRules.indexOf(c.ID) >= 0).map(rule => {
return _publicUser.Processs.filter(c => rule.PublicProcesss.indexOf(c.ID) >= 0);
});
const publicList = _user.Processs.filter(c => _privateRules.indexOf(c.Name) >= 0);
const privateList = _publicUser.Processs.filter(c => _publicRules.indexOf(c.Name) >= 0);
const origin = publicList.concat(privateList).reduce((arr, value, index) => {
arr = arr.concat(value.reduce((arr, value, index) => {
arr = arr.concat(value.List);
return arr;
}, []));
arr = arr.concat(value.List);
return arr;
}, []);
const res = [];
@@ -108,7 +104,8 @@ export default {
});
return {
ids: _privateRules.concat(_publicRules),
ids1: _privateRules,
ids2: _publicRules,
list: {
AllowProcesss: res.filter(c => c.DataType == 0 && c.AllowType == 0).map(c => c.Name),
DeniedProcesss: res.filter(c => c.DataType == 0 && c.AllowType == 1).map(c => c.Name),
@@ -136,9 +133,10 @@ export default {
state.loading = true;
const rules = parseRule();
setRules({
Devices: _devices.map(c => c.MachineName),
Rules: rules.list,
ids: rules.ids,
devices: _devices.map(c => c.MachineName),
data: rules.list,
ids1: rules.ids1,
ids2: rules.ids2,
}).then((errorDevices) => {
state.loading = false;
if (errorDevices && errorDevices.length > 0) {
@@ -146,7 +144,8 @@ export default {
} else {
ElMessage.success('操作成功!');
globalData.value.devices.filter(c => _devices.indexOf(c.MachineName) >= 0).forEach(device => {
device.Hijack.RuleIds = rules.ids;
device.Hijack.RuleIds1 = rules.ids1;
device.Hijack.RuleIds2 = rules.ids2;
});
}
}).catch((e) => {

View File

@@ -0,0 +1,116 @@
<template>
<div class="rule-wrap absolute flex flex-column flex-nowrap">
<div class="flex">
<el-checkbox v-model="state.use">使用规则</el-checkbox>
<el-checkbox v-model="state.domainKill">暴力强杀(关闭应用程序)</el-checkbox>
</div>
<div class="rules flex-1 flex">
<div class="private">
<CheckBoxWrap ref="privateRules" :data="state.privateRules" :items="state.ids1" label="Name" text="Name" title="私有限制"></CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="public">
<CheckBoxWrap ref="publicRules" :data="state.publicRules" :items="state.ids2" label="Name" text="Name" title="公共限制"></CheckBoxWrap>
</div>
</div>
</div>
</template>
<script>
import { reactive, ref } from '@vue/reactivity';
import { computed, getCurrentInstance, inject, onMounted, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { injectGlobalData } from '@/views/provide';
export default {
label: '网络',
components: { CheckBoxWrap },
setup(props, { emit }) {
const globalData = injectGlobalData();
const user = computed(() => globalData.value.usernames[globalData.value.username]);
const publicUserName = globalData.value.publicUserName;
const publicUser = computed(() => globalData.value.usernames[publicUserName]);
const usePublic = publicUser.value && globalData.value.username != publicUserName;
const current = getCurrentInstance();
const modeState = inject('mode-state');
const state = reactive({
use: false,
privateRules: computed(() => user.value ? user.value.Processs : []),
publicRules: computed(() => usePublic ? publicUser.value.Processs : []),
ids1: [],
ids2: [],
domainKill: false
});
watch(() => modeState.value, () => {
parseMode();
});
onMounted(() => { parseMode(); });
const parseMode = () => {
const json = JSON.parse(modeState.value)[current.type.label] || { list: {} };
state.use = json.use || false;
state.ids1 = (json.ids1 || []).map(c => { return { Name: c }; });
state.ids2 = (json.ids2 || []).map(c => { return { Name: c }; });
state.domainKill = json.list.DomainKill || false;
}
const privateRules = ref(null);
const publicRules = ref(null);
const parseRule = () => {
const _privateRules = privateRules.value.getData().map(c => c.Name);
const _publicRules = publicRules.value.getData().map(c => c.Name);
const _user = user.value;
const _publicUser = publicUser.value;
const publicList = _user.Processs.filter(c => _privateRules.indexOf(c.Name) >= 0);
const privateList = _publicUser.Processs.filter(c => _publicRules.indexOf(c.Name) >= 0);
const origin = publicList.concat(privateList).reduce((arr, value, index) => {
arr = arr.concat(value.List);
return arr;
}, []);
const res = [];
origin.forEach(element => {
if (res.filter(c => c.Name == element.Name && c.DataType == element.DataType && c.AllowType == element.AllowType).length == 0) {
res.push(element);
}
});
return {
path: 'hijack/usehijackrules',
use: state.use,
ids1: _privateRules,
ids2: _publicRules,
list: {
AllowProcesss: res.filter(c => c.DataType == 0 && c.AllowType == 0).map(c => c.Name),
DeniedProcesss: res.filter(c => c.DataType == 0 && c.AllowType == 1).map(c => c.Name),
AllowDomains: res.filter(c => c.DataType == 1 && c.AllowType == 0).map(c => c.Name),
DeniedDomains: res.filter(c => c.DataType == 1 && c.AllowType == 1).map(c => c.Name),
AllowIPs: res.filter(c => c.DataType == 2 && c.AllowType == 0).map(c => c.Name),
DeniedIPs: res.filter(c => c.DataType == 2 && c.AllowType == 1).map(c => c.Name),
DomainKill: state.domainKill
}
}
}
const getData = () => {
return parseRule();
}
return {
state, getData, globalData, privateRules, publicRules,
}
}
}
</script>
<style lang="stylus" scoped>
.rule-wrap {
.rules {
position: relative;
.private, .public {
width: 49%;
position: relative;
}
}
}
</style>

View File

@@ -8,7 +8,8 @@ export default {
Download: 0,
DownloadText: '',
Count: 0,
RuleIds: [],
RuleIds1: [],
RuleIds2: [],
DomainKill: false,
}
}
@@ -73,7 +74,8 @@ export default {
item.Hijack.Upload = report.Hijack.Upload;
item.Hijack.Download = report.Hijack.Download;
item.Hijack.Count = report.Hijack.Count;
item.Hijack.RuleIds = report.Hijack.Ids;
item.Hijack.RuleIds1 = report.Hijack.Ids1 || [];
item.Hijack.RuleIds2 = report.Hijack.Ids2 || [];
}
item.Hijack.DomainKill = report.Hijack.DomainKill || false;

View File

@@ -9,28 +9,26 @@
<el-table-column prop="Name" label="名称" />
<el-table-column label="操作" width="110">
<template #default="scope">
<template v-if="scope.row.ID > 1">
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<el-dialog :title="`${state.currentItem.Name1==0?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<div>
<el-input v-model="state.currentItem.Name" size="large" placeholder="分组名称" />
</div>
@@ -46,7 +44,7 @@
import { reactive } from '@vue/reactivity';
import { computed } from '@vue/runtime-core';
import { ElMessage } from 'element-plus';
import { addProcessGroup, deleteProcessGroup } from '../../../../../apis/hijack'
import { updateProcess } from '../../../../../apis/hijack'
import { injectGlobalData } from '@/views/provide';
export default {
setup() {
@@ -54,14 +52,11 @@ export default {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
currentItem: { ID: 0, Name: '' },
currentItem: { Name: '', Name1: '' },
showEdit: false,
list: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Processs) {
if (state.group == 0 && user.Processs.length > 0) {
state.group = user.Processs[0].ID;
}
return user.Processs;
}
return [];
@@ -69,21 +64,27 @@ export default {
});
const handleAdd = (item) => {
item = item || { Name: '', ID: 0 };
item = item || { Name: '', Name1: '' };
state.currentItem.Name = item.Name;
state.currentItem.ID = item.ID;
state.currentItem.Name1 = item.Name;
state.showEdit = true;
}
const handleDel = (item) => {
const handleEditCancel = () => {
state.showEdit = false;
}
const updateProcessGroup = () => {
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
state.loading = true;
deleteProcessGroup({
UserName: globalData.value.username,
ID: item.ID
updateProcess({
username: globalData.value.username,
Data: processs
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
@@ -92,31 +93,33 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
const handleDel = (item) => {
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
const names = processs.map(c => c.Name);
processs.splice(names.indexOf(item.Name), 1);
globalData.value.usernames[globalData.value.username].Processs = processs;
updateProcessGroup();
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
state.loading = true;
addProcessGroup({
UserName: globalData.value.username,
Group: state.currentItem
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
globalData.value.updateRuleFlag = Date.now();
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
const names = processs.map(c => c.Name);
let index = names.indexOf(state.currentItem.Name1);
if (index == -1) {
if (names.indexOf(state.currentItem.Name) >= 0) {
ElMessage.error('已存在同名');
return;
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
})
processs.push({ Name: state.currentItem.Name })
} else {
processs[index].Name = state.currentItem.Name;
}
globalData.value.usernames[globalData.value.username].Processs = processs;
updateProcessGroup();
}
return { state, handleAdd, handleDel, handleEditCancel, handleEditSubmit }
}

View File

@@ -2,7 +2,7 @@
<div class="process-items-wrap flex flex-nowrap flex-column">
<div class="head t-c flex">
<el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem">
<el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" />
<el-option v-for="item in state.groups" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
<span class="flex-1"></span>
<el-button @click="handleAdd()">添加项</el-button>
@@ -36,7 +36,7 @@
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<el-dialog :title="`${state.currentItem.Name1?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<div>
<div class="alert">
<p>1黑名单优先</p>
@@ -69,28 +69,28 @@
import { reactive } from '@vue/reactivity';
import { computed, watch } from '@vue/runtime-core';
import { ElMessage } from 'element-plus';
import { addProcess, deleteProcess } from '../../../../../apis/hijack'
import { updateProcess } from '../../../../../apis/hijack'
import { injectGlobalData } from '@/views/provide';
export default {
setup() {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
group: 0,
currentItem: { ID: 0, Name: '', AllowType: 1, DataType: 0 },
group: '',
currentItem: { Name: '', Name1: '', AllowType: 1, DataType: 0 },
showEdit: false,
groups: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Processs) {
if (state.group == 0 && user.Processs.length > 0) {
state.group = user.Processs[0].ID;
state.group = user.Processs[0].Name;
}
return user.Processs;
}
return [];
}),
list: computed(() => {
let group = state.groups.filter(c => c.ID == state.group)[0];
let group = state.groups.filter(c => c.Name == state.group)[0];
if (group) return group.List;
return [];
})
@@ -108,23 +108,29 @@ export default {
}
}
const handleAdd = (item) => {
item = item || { Name: '', ID: 0, AllowType: 1, DataType: 0 };
item = item || { Name: '', Name1: '', AllowType: 1, DataType: 0 };
state.currentItem.Name = item.Name;
state.currentItem.ID = item.ID;
state.currentItem.Name1 = item.Name;
state.currentItem.AllowType = item.AllowType;
state.currentItem.DataType = item.DataType;
state.showEdit = true;
}
const handleDel = (item) => {
const handleEditCancel = () => {
state.showEdit = false;
}
const updateProcessGroup = () => {
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
state.loading = true;
deleteProcess({
UserName: globalData.value.username,
GroupID: state.group,
ID: item.ID
updateProcess({
username: globalData.value.username,
Data: processs
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
@@ -133,32 +139,51 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
const handleDel = (item) => {
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
const group = processs.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Name);
items.splice(names.indexOf(item.Name), 1);
globalData.value.usernames[globalData.value.username].Processs = processs;
updateProcessGroup();
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
state.loading = true;
addProcess({
UserName: globalData.value.username,
GroupID: state.group,
Item: state.currentItem
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
globalData.value.updateRuleFlag = Date.now();
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
const group = processs.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Name);
let index = names.indexOf(state.currentItem.Name1);
if (index == -1) {
if (names.indexOf(state.currentItem.Name) >= 0) {
ElMessage.error('已存在同名');
return;
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
})
items.push({
Name: state.currentItem.Name,
Desc: state.currentItem.Desc,
AllowType: state.currentItem.AllowType,
DataType: state.currentItem.DataType,
})
} else {
items[index].Name = state.currentItem.Name;
items[index].Desc = state.currentItem.Desc;
items[index].AllowType = state.currentItem.AllowType;
items[index].DataType = state.currentItem.DataType;
}
globalData.value.usernames[globalData.value.username].Processs = processs;
updateProcessGroup();
}
return { state, handleNameChange, handleAdd, handleDel, handleEditCancel, handleEditSubmit }
}

View File

@@ -9,28 +9,26 @@
<el-table-column prop="Name" label="名称" />
<el-table-column label="操作" width="110">
<template #default="scope">
<template v-if="scope.row.ID > 1">
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<el-dialog :title="`${state.currentItem.Name1==0?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<div>
<el-input v-model="state.currentItem.Name" size="large" placeholder="分组名称" />
</div>
@@ -46,7 +44,7 @@
import { reactive } from '@vue/reactivity';
import { computed } from '@vue/runtime-core';
import { ElMessage } from 'element-plus';
import { addRule, deleteRule } from '../../../../../apis/hijack'
import { updateRule } from '../../../../../apis/hijack'
import { injectGlobalData } from '@/views/provide';
export default {
setup() {
@@ -54,13 +52,13 @@ export default {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
currentItem: { ID: 0, Name: '' },
currentItem: { Name: '', Name1: '' },
showEdit: false,
list: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Rules) {
if (state.group == 0 && user.Rules.length > 0) {
state.group = user.Rules[0].ID;
state.group = user.Rules[0].Name;
}
return user.Rules;
}
@@ -69,21 +67,28 @@ export default {
});
const handleAdd = (item) => {
item = item || { Name: '', ID: 0 };
item = item || { Name: '', Name1: '' };
state.currentItem.Name = item.Name;
state.currentItem.ID = item.ID;
state.currentItem.Name1 = item.Name;
state.showEdit = true;
}
const handleDel = (item) => {
const handleEditCancel = () => {
state.showEdit = false;
}
const _updateRule = () => {
const rules = globalData.value.usernames[globalData.value.username].Rules || [];
state.loading = true;
deleteRule({
UserName: globalData.value.username,
ID: item.ID
updateRule({
username: globalData.value.username,
Data: rules
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
@@ -92,32 +97,35 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
const handleDel = (item) => {
const rules = globalData.value.usernames[globalData.value.username].Rules || [];
const names = rules.map(c => c.Name);
rules.splice(names.indexOf(item.Name), 1);
globalData.value.usernames[globalData.value.username].Rules = rules;
_updateRule();
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
state.loading = true;
addRule({
UserName: globalData.value.username,
Rule: state.currentItem
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
globalData.value.updateRuleFlag = Date.now();
const rules = globalData.value.usernames[globalData.value.username].Rules || [];
const names = rules.map(c => c.Name);
let index = names.indexOf(state.currentItem.Name1);
if (index == -1) {
if (names.indexOf(state.currentItem.Name) >= 0) {
ElMessage.error('已存在同名');
return;
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
})
rules.push({ Name: state.currentItem.Name })
} else {
rules[index].Name = state.currentItem.Name;
}
globalData.value.usernames[globalData.value.username].Rules = rules;
_updateRule();
}
return { state, handleAdd, handleDel, handleEditCancel, handleEditSubmit }
}
}

View File

@@ -3,7 +3,7 @@
<div class="head t-c flex">
<div>
<el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem">
<el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" />
<el-option v-for="item in state.groups" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
</div>
<div class="flex-1"></div>
@@ -13,11 +13,11 @@
</div>
<div class="body flex flex-1">
<div class="private">
<CheckBoxWrap ref="privateProcess" :data="state.privateProcess" :items="state.privateProcessItems" label="ID" text="Name" title="私有程序组"></CheckBoxWrap>
<CheckBoxWrap ref="privateProcess" :data="state.privateProcess" :items="state.privateProcessItems" label="Name" text="Name" title="私有程序组"></CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="public">
<CheckBoxWrap ref="publicProcess" :data="state.publicProcess" :items="state.publicProcessItems" label="ID" text="Name" title="公共程序组"></CheckBoxWrap>
<CheckBoxWrap ref="publicProcess" :data="state.publicProcess" :items="state.publicProcessItems" label="Name" text="Name" title="公共程序组"></CheckBoxWrap>
</div>
</div>
</div>
@@ -27,7 +27,7 @@
import { computed, reactive, ref, watch } from 'vue';
import CheckBoxWrap from '../../../boxs/CheckBoxWrap.vue'
import { ElMessage } from 'element-plus';
import { addRule } from '../../../../../apis/hijack'
import { updateRule } from '../../../../../apis/hijack'
import { injectGlobalData } from '@/views/provide';
export default {
components: { CheckBoxWrap },
@@ -41,11 +41,11 @@ export default {
const state = reactive({
loading: false,
group: 0,
group: '',
groups: computed(() => {
if (user.value && user.value.Rules) {
if (state.group == 0 && user.value.Rules.length > 0) {
state.group = user.value.Rules[0].ID;
if (state.group == '' && user.value.Rules.length > 0) {
state.group = user.value.Rules[0].Name;
}
return user.value.Rules;
}
@@ -53,22 +53,23 @@ export default {
}),
rule: computed(() => {
if (user && user.value.Rules) {
let rule = user.value.Rules.filter(c => c.ID == state.group)[0];
let rule = user.value.Rules.filter(c => c.Name == state.group)[0];
if (rule) {
console.log(rule);
console.log(user.value.Processs.filter(c => rule.PrivateProcesss.indexOf(c.Name) >= 0));
return rule;
}
}
return {
ID: 0,
Name: '',
PrivateProcesss: [],
PublicProcesss: [],
}
}),
privateProcess: computed(() => user.value ? user.value.Processs : []),
privateProcessItems: computed(() => user.value ? user.value.Processs.filter(c => state.rule.PrivateProcesss.indexOf(c.ID) >= 0) : []),
privateProcessItems: computed(() => user.value ? user.value.Processs.filter(c => state.rule.PrivateProcesss.indexOf(c.Name) >= 0) : []),
publicProcess: computed(() => usePublic ? publicUser.value.Processs : []),
publicProcessItems: computed(() => usePublic ? publicUser.value.Processs.filter(c => state.rule.PublicProcesss.indexOf(c.ID) >= 0) : []),
publicProcessItems: computed(() => usePublic ? publicUser.value.Processs.filter(c => state.rule.PublicProcesss.indexOf(c.Name) >= 0) : []),
});
watch(() => state.show, (val) => {
if (!val) {
@@ -78,36 +79,43 @@ export default {
}
});
const privateProcess = ref(null);
const publicProcess = ref(null);
const handleSave = () => {
let rule = user.value.Rules.filter(c => c.ID == state.group)[0];
if (!rule) {
ElMessage.error('未选择任何限制分组');
return;
}
rule.PrivateProcesss = privateProcess.value.getData().map(c => c.ID);
rule.PublicProcesss = publicProcess.value.getData().map(c => c.ID);
const _updateRule = () => {
const rules = globalData.value.usernames[globalData.value.username].Rules || [];
rules.forEach(element => {
element.PrivateProcesss = element.PrivateProcesss.filter(c => typeof (c) != 'number');
element.PublicProcesss = element.PublicProcesss.filter(c => typeof (c) != 'number');
});
state.loading = true;
addRule({
UserName: globalData.value.username,
Rule: rule
updateRule({
username: globalData.value.username,
Data: rules
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功');
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
}).catch(() => {
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败');
ElMessage.error('操作失败!');
})
}
const handleSave = () => {
let rule = user.value.Rules.filter(c => c.Name == state.group)[0];
if (!rule) {
ElMessage.error('未选择任何限制分组');
return;
}
rule.PrivateProcesss = privateProcess.value.getData().map(c => c.Name);
rule.PublicProcesss = publicProcess.value.getData().map(c => c.Name);
_updateRule();
}
return {
state, handleSave, privateProcess, publicProcess

View File

@@ -0,0 +1,120 @@
<template>
<el-dialog class="options options-center" title="模式" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%">
<div class="modes-wrap flex">
<div class="items">
<CheckBoxWrap ref="devices" :data="globalData.devices" :items="state.items" label="MachineName" title="选择设备"></CheckBoxWrap>
</div>
<div class="flex-1"></div>
<div class="modes">
<div class="inner absolute scrollbar">
<template v-for="(item,index) in state.modes" :key="index">
<div class="item">
<div class="subitem flex">
<span class="label flex-1">{{item.Name}}</span>
<el-button @click="handleUseMode(item)">应用-{{item.Name}}</el-button>
</div>
</div>
</template>
</div>
</div>
</div>
<template #footer>
<el-button @click="handleCancel"> </el-button>
</template>
</el-dialog>
</template>
<script>
import { reactive, ref } from '@vue/reactivity';
import { computed, onMounted, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { ElMessage } from 'element-plus';
import { injectGlobalData } from '@/views/provide';
import { injectPluginState } from '../../provide';
import { useModes } from '../../../../apis/modes';
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
components: { CheckBoxWrap },
setup(props, { emit }) {
const globalData = injectGlobalData();
const pluginState = injectPluginState();
const devices = ref(null);
const state = reactive({
show: props.modelValue,
items: computed(() => pluginState.value.modes.devices),
modes: computed(() => (globalData.value.usernames[globalData.value.username] || {}).Modes || []),
loading: false
});
watch(() => state.show, (val) => {
if (!val) {
setTimeout(() => {
emit('update:modelValue', val);
}, 300);
}
});
const handleCancel = () => {
state.show = false;
}
const handleUseMode = (item) => {
const devicesNames = devices.value.getData().map(c => c.MachineName);
if (devicesNames.length == 0) {
ElMessage.error('请选择设备');
return;
}
const funcs = [];
const json = JSON.parse(item.Data);
for (let j in json) {
if (json[j].use) {
funcs.push(useModes(devicesNames, json[j].list, json[j].ids1, json[j].ids2, json[j].path));
}
}
Promise.all(funcs).then(res => {
ElMessage.success('设置成功');
}).catch(() => {
ElMessage.error('设置失败');
});
}
return {
state, globalData, devices, handleCancel, handleUseMode
}
}
}
</script>
<style lang="stylus" scoped>
.modes-wrap {
height: 70vh;
position: relative;
.items {
height: 100%;
width: 36%;
position: relative;
}
.modes {
height: 100%;
width: 62%;
position: relative;
border: 1px solid #ddd;
box-sizing: border-box;
.label {
line-height: 3.2rem;
}
.inner {
padding: 0.6rem;
&>div {
padding: 0.6rem 0;
}
}
}
}
</style>

View File

@@ -3,7 +3,7 @@
<el-icon>
<Help />
</el-icon>
<span>设置</span>
<span>模式</span>
</a>
</template>
@@ -15,7 +15,7 @@ export default {
const pluginState = injectPluginState();
const handleSetting = () => {
pluginState.value.setting.showSetting = true;
pluginState.value.modes.showModesSetting = true;
}
return {

View File

@@ -0,0 +1,27 @@
<template>
<el-button size="small" plain dark @click="handleMode">模式<el-icon>
<Help />
</el-icon></el-button>
</template>
<script>
import { injectGlobalData } from '@/views/provide';
import { injectPluginState } from '../../provide';
export default {
setup() {
const pluginState = injectPluginState();
const globalData = injectGlobalData();
const handleMode = () => {
pluginState.value.modes.devices = globalData.value.devices;
pluginState.value.modes.showModes = true;
}
return {
handleMode
}
}
}
</script>
<style lang="stylus" scoped></style>

View File

@@ -1,14 +1,16 @@
<template>
<div>
<ChooseDig v-if="pluginState.setting.showSetting" v-model="pluginState.setting.showSetting"></ChooseDig>
<ChooseDig v-if="pluginState.modes.showModes" v-model="pluginState.modes.showModes"></ChooseDig>
<SettingDig v-if="pluginState.modes.showModesSetting" v-model="pluginState.modes.showModesSetting"></SettingDig>
</div>
</template>
<script>
import { injectPluginState } from '../../provide';
import ChooseDig from './ChooseDig.vue'
import SettingDig from './SettingDig.vue'
export default {
components: { ChooseDig },
components: { ChooseDig, SettingDig },
setup() {
const pluginState = injectPluginState();
return { pluginState }

View File

@@ -0,0 +1,196 @@
<template>
<div class="modes-setting-wrap">
<el-dialog class="options options-center" title="模式设置" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%">
<div class="modes-wrap flex flex-column flex-nowrap">
<div class="head t-c">
<el-select size="small" v-model="state.mode" placeholder="Select" style="width: 80px;margin-right:.6rem">
<el-option v-for="item in state.items" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
<el-button size="small" @click="handleAdd">增加</el-button>
<el-button size="small" @click="handleEdit">编辑</el-button>
<el-popconfirm title="删除不可逆,确认吗?" @confirm="handleDelete">
<template #reference>
<el-button size="small" type="danger">删除</el-button>
</template>
</el-popconfirm>
<el-button size="small" type="primary" @click="handleSave">保存</el-button>
</div>
<div class="plugins flex-1">
<el-tabs type="border-card" class="absolute flex flex-column flxex-nowrap">
<template v-for="(item,index) in commandModules" :key="index">
<el-tab-pane :label="item.label" class="absolute">
<component :ref="`mode-${item.label}`" :is="item"></component>
</el-tab-pane>
</template>
</el-tabs>
</div>
</div>
<template #footer>
<el-button @click="handleCancel"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { reactive, ref } from '@vue/reactivity';
import { computed, getCurrentInstance, provide, watch } from '@vue/runtime-core';
import { ElMessage, ElMessageBox } from 'element-plus';
import { injectGlobalData } from '@/views/provide';
import { updateModes } from '../../../../apis/modes';
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
components: {},
setup(props, { emit }) {
const commandFiles = require.context('../../plugins/', true, /Modes\.vue/);
const commandModules = commandFiles.keys().map(c => commandFiles(c).default);
const current = getCurrentInstance();
const globalData = injectGlobalData();
const modeState = ref({});
provide('mode-state', modeState);
const state = reactive({
show: props.modelValue,
loading: false,
mode: '',
mode1: '',
items: computed(() => {
const arr = globalData.value.usernames[globalData.value.username].Modes || [];
if (arr.length > 0 && state.mode == '') {
state.mode = arr[0].Name;
}
const value = (globalData.value.usernames[globalData.value.username].Modes || []).filter(c => c.Name == state.mode)[0] || { Data: '{}' };
modeState.value = value.Data;
return arr;
})
});
watch(() => state.show, (val) => {
if (!val) {
setTimeout(() => {
emit('update:modelValue', val);
}, 300);
}
});
const handleCancel = () => {
state.show = false;
}
const handleSubmit = () => {
state.show = false;
}
const edit = () => {
const isEdit = state.mode1 != '';
const title = isEdit ? `编辑【${state.mode1}` : `增加新项`;
ElMessageBox.prompt('输入名字', title, {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputValue: state.mode1
}).then(({ value }) => {
value = value.replace(/^\s|\s$/g, '');
if (value) {
const modes = globalData.value.usernames[globalData.value.username].Modes;
if (isEdit) {
const mode = modes.filter(c => c.Name == state.mode1)[0];
mode.Name = value;
} else {
modes.push({ Name: value, Data: '{}' });
}
state.mode = value;
saveModes();
}
}).catch(() => { })
}
const handleAdd = () => {
state.mode1 = '';
edit();
}
const handleEdit = () => {
state.mode1 = state.mode;
edit();
}
const handleDelete = () => {
const modes = globalData.value.usernames[globalData.value.username].Modes;
const names = modes.map(c => c.Name);
modes.splice(names.indexOf(state.mode), 1);
state.mode = modes[0] || '';
saveModes();
}
const saveModes = () => {
updateModes({
username: globalData.value.username,
Data: globalData.value.usernames[globalData.value.username].Modes
}).then(() => {
state.loading = false;
globalData.value.updateRuleFlag = Date.now();
ElMessage.success('已操作')
}).catch(() => {
state.loading = false;
ElMessage.error('操作失败')
})
}
const handleSave = () => {
if (!state.mode) {
ElMessage.error('请选择一个模式');
return;
}
const mode = globalData.value.usernames[globalData.value.username].Modes.filter(c => c.Name == state.mode)[0];
if (!mode) {
ElMessage.error('请选择一个模式');
return;
}
const json = {};
for (let i = 0; i < commandModules.length; i++) {
json[commandModules[i].label] = current.refs[`mode-${commandModules[i].label}`][0].getData();
}
mode.Data = JSON.stringify(json);
saveModes();
}
return {
state, globalData, commandModules, handleCancel, handleSubmit, handleAdd, handleEdit, handleDelete, handleSave
}
}
}
</script>
<style lang="stylus">
.modes-setting-wrap {
.el-tabs__content {
flex: 1;
overflow: auto;
}
}
</style>
<style lang="stylus" scoped>
.modes-wrap {
height: 70vh;
position: relative;
.head {
padding-bottom: 1rem;
}
.plugins {
// border: 1px solid #ddd;
overflow: hidden;
position: relative;
.el-tab-pane {
top: 10px;
right: 10px;
bottom: 10px;
left: 10px;
}
}
}
</style>

View File

@@ -0,0 +1,14 @@
export default {
field() {
return {
}
},
state: {
modes: {
showModes: false,
showModesSetting: false,
devices: []
}
}
}

View File

@@ -1,112 +0,0 @@
<template>
<el-dialog class="options-center" title="设置" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%">
<div class="setting-wrap">
<el-form ref="ruleFormRef" :model="state.form" :rules="state.rules" label-width="100px">
<el-form-item label="报告延迟(ms)" prop="ReportDelay">
<el-input-number size="large" v-model="state.form.ReportDelay" :min="17" :max="1000" controls-position="right" />
</el-form-item>
<el-form-item label="截屏延迟(ms)" prop="ScreenDelay">
<el-input-number size="large" v-model="state.form.ScreenDelay" :min="17" :max="1000" controls-position="right" />
</el-form-item>
<el-form-item label="截屏缩放" prop="ScreenScale">
<el-input-number size="large" v-model="state.form.ScreenScale" :min="0.1" :max="1" :step="0.1" controls-position="right" />
</el-form-item>
<!-- <el-form-item label="保存配置" prop="SaveSetting">
<el-checkbox v-model="state.form.SaveSetting">保存限制配置</el-checkbox>
</el-form-item>
<el-form-item label="黑屏唤醒" prop="WakeUp">
<el-checkbox v-model="state.form.WakeUp">黑屏时唤醒</el-checkbox>
</el-form-item>
<el-form-item label="声音峰值" prop="VolumeMasterPeak">
<el-checkbox v-model="state.form.VolumeMasterPeak">报告声音峰值</el-checkbox>
</el-form-item> -->
</el-form>
</div>
<template #footer>
<el-button @click="handleCancel"> </el-button>
<el-button type="success" plain :loading="state.loading" @click="handleSubmit"> </el-button>
</template>
</el-dialog>
</template>
<script>
import { reactive, ref } from '@vue/reactivity';
import { onMounted, watch } from '@vue/runtime-core';
import CheckBoxWrap from '../../boxs/CheckBoxWrap.vue'
import { getSetting, saveSetting } from '../../../../apis/setting'
import { ElMessage } from 'element-plus';
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
components: { CheckBoxWrap },
setup(props, { emit }) {
const state = reactive({
show: props.modelValue,
loading: false,
rules: [],
form: {
ReportDelay: 0,
ScreenDelay: 0,
ScreenScale: 0,
SaveSetting: true,
WakeUp: true,
VolumeMasterPeak: true,
}
});
watch(() => state.show, (val) => {
if (!val) {
setTimeout(() => {
emit('update:modelValue', val);
}, 300);
}
});
const loadData = () => {
getSetting().then((res) => {
state.form.ReportDelay = res.ReportDelay;
state.form.ScreenDelay = res.ScreenDelay;
state.form.ScreenScale = res.ScreenScale;
state.form.SaveSetting = res.SaveSetting;
state.form.WakeUp = res.WakeUp;
state.form.VolumeMasterPeak = res.VolumeMasterPeak;
}).catch(() => {
});
}
const handleCancel = () => {
state.show = false;
}
const devices = ref(null);
const handleSubmit = () => {
state.loading = true;
saveSetting(state.form).then((error) => {
state.loading = false;
if (error) {
ElMessage.success('操作成功!');
state.show = false;
} else {
ElMessage.error('操作失败!');
}
}).catch(() => {
state.loading = false;
ElMessage.error('操作失败!');
});
}
onMounted(() => {
loadData();
});
return {
state, devices, handleCancel, handleSubmit
}
}
}
</script>
<style lang="stylus" scoped>
.setting-wrap {
position: relative;
padding: 2rem 5rem;
}
</style>

View File

@@ -1,12 +0,0 @@
export default {
field() {
return {
}
},
state: {
setting: {
showSetting: false
}
}
}

View File

@@ -1,12 +1,10 @@
<template>
<div>
<!-- <ChooseDig v-if="pluginState.setting.showSetting" v-model="pluginState.setting.showSetting"></ChooseDig> -->
</div>
</template>
<script>
import { injectPluginState } from '../../provide';
// import ChooseDig from './ChooseDig.vue'
export default {
components: {},
setup() {

View File

@@ -9,28 +9,26 @@
<el-table-column prop="Name" label="名称" />
<el-table-column label="操作" width="110">
<template #default="scope">
<template v-if="scope.row.ID > 1">
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
<el-button size="small" @click="handleAdd(scope.row)">
<el-icon>
<EditPen />
</el-icon>
</el-button>
<el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)">
<template #reference>
<el-button size="small" type="danger">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<el-dialog :title="`${state.currentItem.Name1==0?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%">
<div>
<el-input v-model="state.currentItem.Name" size="large" placeholder="分组名称" />
</div>
@@ -46,7 +44,7 @@
import { reactive } from '@vue/reactivity';
import { computed } from '@vue/runtime-core';
import { ElMessage } from 'element-plus';
import { addGroup, delGroup } from '@/apis/snatch'
import { updateSnatch } from '@/apis/snatch'
import { injectGlobalData } from '@/views/provide';
export default {
setup() {
@@ -54,13 +52,13 @@ export default {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
currentItem: { ID: 0, Name: '' },
currentItem: { Name: '', Name1: '' },
showEdit: false,
list: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Snatchs) {
if (state.group == 0 && user.Snatchs.length > 0) {
state.group = user.Snatchs[0].ID;
if (state.group == '' && user.Snatchs.length > 0) {
state.group = user.Snatchs[0].Name;
}
return user.Snatchs;
}
@@ -69,18 +67,27 @@ export default {
});
const handleAdd = (item) => {
item = item || { Name: '', ID: 0 };
item = item || { Name: '', Name1: '' };
state.currentItem.Name = item.Name;
state.currentItem.ID = item.ID;
state.currentItem.Name1 = item.Name;
state.showEdit = true;
}
const handleDel = (item) => {
const handleEditCancel = () => {
state.showEdit = false;
}
const updateSnatchGroup = () => {
const snatchs = globalData.value.usernames[globalData.value.username].Snatchs || [];
state.loading = true;
delGroup(globalData.value.username, item.ID).then((error) => {
updateSnatch({
username: globalData.value.username,
Data: snatchs
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
@@ -89,32 +96,36 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
const handleDel = (item) => {
const snatchs = globalData.value.usernames[globalData.value.username].Snatchs || [];
const names = snatchs.map(c => c.Name);
snatchs.splice(names.indexOf(item.Name), 1);
globalData.value.usernames[globalData.value.username].Snatchs = snatchs;
updateSnatchGroup();
}
const handleEditSubmit = () => {
state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, '');
if (!state.currentItem.Name) {
return;
}
state.loading = true;
addGroup({
UserName: globalData.value.username,
Group: state.currentItem
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
globalData.value.updateRuleFlag = Date.now();
const snatchs = globalData.value.usernames[globalData.value.username].Snatchs || [];
const names = snatchs.map(c => c.Name);
let index = names.indexOf(state.currentItem.Name1);
if (index == -1) {
if (names.indexOf(state.currentItem.Name) >= 0) {
ElMessage.error('已存在同名');
return;
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
})
snatchs.push({ Name: state.currentItem.Name })
} else {
snatchs[index].Name = state.currentItem.Name;
}
globalData.value.usernames[globalData.value.username].Snatchs = snatchs;
updateSnatchGroup();
}
return { state, handleAdd, handleDel, handleEditCancel, handleEditSubmit }
}
}

View File

@@ -2,7 +2,7 @@
<div class="snatchs-items-wrap flex flex-nowrap flex-column">
<div class="head t-c flex">
<el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem">
<el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" />
<el-option v-for="item in state.groups" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
<span class="flex-1"></span>
<el-button @click="handleAdd()">添加项</el-button>
@@ -32,7 +32,7 @@
</el-table>
</div>
</div>
<el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="94%">
<el-dialog :title="`${state.currentItem.Title1?'修改项':'添加项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="94%">
<div>
<el-form ref="formDom" :rules="state.rules" :model="state.currentItem" label-width="0">
<el-form-item prop="Title">
@@ -112,8 +112,8 @@ export default {
const globalData = injectGlobalData();;
const state = reactive({
loading: false,
group: 0,
currentItem: { ID: 0, Title: '', Cate: 1, Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 },
group: '',
currentItem: { Title: '', Title1: '', Cate: 1, Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 },
rules: {
Title: [
{ required: true, message: '名称必填', trigger: 'blur' }
@@ -139,15 +139,15 @@ export default {
groups: computed(() => {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Snatchs) {
if (state.group == 0 && user.Snatchs.length > 0) {
state.group = user.Snatchs[0].ID;
if (state.group == '' && user.Snatchs.length > 0) {
state.group = user.Snatchs[0].Name;
}
return user.Snatchs;
}
return [];
}),
list: computed(() => {
let group = state.groups.filter(c => c.ID == state.group)[0];
let group = state.groups.filter(c => c.Name == state.group)[0];
if (group) return group.List;
return [];
})
@@ -159,23 +159,33 @@ export default {
}
}
const handleAdd = (item) => {
item = item || { ID: 0, Title: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 };
item = item || { Title: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 };
state.currentItem.Title = item.Title;
state.currentItem.Title1 = item.Title;
state.currentItem.Type = item.Type;
state.currentItem.ID = item.ID;
state.currentItem.Question = item.Question;
state.currentItem.Options = item.Options;
state.currentItem.Correct = item.Correct;
state.currentItem.Chance = item.Chance;
state.showEdit = true;
}
const handleDel = (item) => {
const handleEditCancel = () => {
state.showEdit = false;
}
const updateSnatchGroup = () => {
const processs = globalData.value.usernames[globalData.value.username].Processs || [];
state.loading = true;
del(globalData.value.username, state.group, item.ID).then((error) => {
updateProcess({
username: globalData.value.username,
Data: processs
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
state.showEdit = false;
ElMessage.success('操作成功!');
globalData.value.updateRuleFlag = Date.now();
}
@@ -184,38 +194,46 @@ export default {
ElMessage.error('操作失败!');
})
}
const handleEditCancel = () => {
state.showEdit = false;
}
const handleDel = (item) => {
const snatchs = globalData.value.usernames[globalData.value.username].Snatchs || [];
const group = snatchs.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Title);
items.splice(names.indexOf(item.Title), 1);
globalData.value.usernames[globalData.value.username].Snatchs = snatchs;
updateSnatchGroup();
}
const formDom = ref(null);
const handleEditSubmit = () => {
formDom.value.validate((valid) => {
if (!valid) return;
state.loading = true;
const snatchs = globalData.value.usernames[globalData.value.username].Snatchs || [];
const group = snatchs.filter(c => c.Name == state.group)[0];
const items = group.List;
const names = items.map(c => c.Title);
let index = names.indexOf(state.currentItem.Title1);
const json = JSON.parse(JSON.stringify(state.currentItem));
json.Chance = +json.Chance;
json.Type = +json.Type;
json.Title = json.Title.replace(/^\s|\s$/g, '');
json.Correct = json.Correct.replace(/^\s|\s$/g, '');
add({
UserName: globalData.value.username,
GroupID: state.group,
Item: json
}).then((error) => {
state.loading = false;
if (error) {
ElMessage.error(error);
} else {
ElMessage.success('操作成功!');
state.showEdit = false;
globalData.value.updateRuleFlag = Date.now();
if (index == -1) {
if (names.indexOf(state.currentItem.Title) >= 0) {
ElMessage.error('已存在同名');
return;
}
}).catch((e) => {
state.loading = false;
ElMessage.error('操作失败!');
});
items.push({ Chance: +json.Chance, Type: +json.Type, Title: json.Title.replace(/^\s|\s$/g, ''), Correct: json.Correct.replace(/^\s|\s$/g, '') })
} else {
items[index].Chance = +json.Chance;
items[index].Type = +json.Type;
items[index].Title = json.Title.replace(/^\s|\s$/g, '');
items[index].Correct = json.Correct.replace(/^\s|\s$/g, '');
}
globalData.value.usernames[globalData.value.username].Snatchs = snatchs;
updateSnatchGroup();
});
}

View File

@@ -8,14 +8,14 @@
<el-col :span="12">
<el-form-item>
<el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem">
<el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" />
<el-option v-for="item in state.groups" :key="item.Name" :label="item.Name" :value="item.Name" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<el-select @change="handleItemChange" v-model="state.item" placeholder="选择一个模板" style="width:13rem">
<el-option v-for="item in state.list" :key="item.ID" :label="item.Title" :value="item.ID" />
<el-option v-for="item in state.list" :key="item.Title" :label="item.Title" :value="item.Title" />
</el-select>
</el-form-item>
</el-col>
@@ -98,9 +98,9 @@ export default {
const pluginState = injectPluginState();
const state = reactive({
loading: false,
group: 0,
item: 0,
currentItem: { ID: 0, Cate: 1, Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 },
group: '',
item: '',
currentItem: { Cate: 1, Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 },
rules: {
Question: [
{ required: true, message: '内容必填', trigger: 'blur' }
@@ -123,17 +123,17 @@ export default {
let user = globalData.value.usernames[globalData.value.username];
if (user && user.Snatchs) {
if (state.group == 0 && user.Snatchs.length > 0) {
state.group = user.Snatchs[0].ID;
state.group = user.Snatchs[0].Name;
}
return user.Snatchs;
}
return [];
}),
list: computed(() => {
let group = state.groups.filter(c => c.ID == state.group)[0];
let group = state.groups.filter(c => c.Name == state.group)[0];
if (group) {
if (state.item == 0 && group.List.length > 0) {
state.item = group.List[0].ID;
state.item = group.List[0].Title;
}
return group.List;
}
@@ -147,10 +147,10 @@ export default {
}
}
const handleItemChange = () => {
const item = state.list.filter(c => c.ID == state.item)[0] || { ID: 0, Cate: 1, Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 };
const item = state.list.filter(c => c.Title == state.item)[0] || { Cate: 1, Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Chance: 65535 };
state.currentItem.Cate = item.Cate;
state.currentItem.Type = item.Type;
state.currentItem.ID = item.ID;
state.currentItem.Title = item.Title;
state.currentItem.Question = item.Question;
state.currentItem.Options = item.Options;
state.currentItem.Correct = item.Correct;
@@ -244,6 +244,16 @@ export default {
handleRandom();
}).catch(() => { });
}
const randomQuestion = (length) => {
return new Promise((resolve, reject) => {
const snatchs = globalData.value.usernames[globalData.value.username].Snatchs || [];
const questions = snatchs.reduce((arr, current) => {
arr = arr.concat(current.List);
return arr;
}, []).sort((a, b) => Math.random() - 0.5);
resolve(questions.filter((value, index) => index < length));
});
}
const handleRandom = () => {
const names = pluginState.value.command.devices.map(c => c.MachineName);
state.loading = true;

View File

@@ -0,0 +1,95 @@
<template>
<div class="absolute flex flex-column flex-nowrap">
<div class="head">
<el-checkbox v-model="state.use">使用规则</el-checkbox>
</div>
<div class="body flex-1 scrollbar">
<ul>
<template v-for="(item,index) in state.options" :key="index">
<li class="flex">
<span class="label">{{item.label}}</span>
<span class="flex-1"></span>
<div class="options">
<el-switch v-model="item.value" inline-prompt active-text="禁用" inactive-text="启用" size="large" />
</div>
</li>
</template>
</ul>
</div>
</div>
</template>
<script>
import { reactive } from '@vue/reactivity';
import { getCurrentInstance, inject, onMounted, watch } from '@vue/runtime-core';
import { injectGlobalData } from '@/views/provide';
export default {
label: '系统选项',
setup(props, { emit }) {
const globalData = injectGlobalData();
const current = getCurrentInstance();
const modeState = inject('mode-state');
const state = reactive({
use: false,
options: []
});
watch(() => modeState.value, () => {
parseMode();
});
const parseMode = () => {
const json = JSON.parse(modeState.value)[current.type.label] || {};
state.use = json.use || false;
const list = (json.list || []).reduce((json, current) => {
json[current.key] = current.value;
return json;
}, {});
parseOptions(list);
}
const parseOptions = (list) => {
const optionJson = globalData.value.allDevices.reduce((json, value, index) => {
json = Object.assign(json, value.System.OptionKeys);
return json;
}, {});
const keys = Object.keys(optionJson);
const arr = keys.map(c => {
const item = optionJson[c];
return { key: c, label: item.Desc, index: item.Index, value: list[c] || false }
}).filter(c => c.label).sort((a, b) => a.index - b.index);
state.options = arr
}
onMounted(() => { parseMode(); });
const getData = () => {
return {
path: 'system/registryoptions',
use: state.use,
ids1: state.options.filter(c => c.value).map(c => c.key),
ids2: [],
list: state.options.map(c => {
return {
key: c.key,
value: c.value
}
}),
}
}
return {
state, getData
}
}
}
</script>
<style lang="stylus" scoped>
.el-switch {
--el-switch-on-color: rgba(255, 0, 0, 0.8) !important;
}
.body {
border: 1px solid #ddd;
padding: 1rem;
}
</style>

View File

@@ -47,7 +47,7 @@ export default {
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
updateRegistryOptions([props.data.MachineName], [key], value).then((res) => {
updateRegistryOptions([props.data.MachineName], [{ key: key, value: value }]).then((res) => {
if (res) {
ElMessage.success('操作成功');
resolve();
@@ -77,8 +77,11 @@ export default {
const newValue = !shutdown.value;
handleChange('NoClose', shutdown.value ? '确定启用关机按钮吗?' : '确定禁用关机按钮吗?', newValue).then(() => {
updateRegistryOptions([props.data.MachineName], [
'NoLogOff', 'DisableLockWorkstation', 'HideFastUserSwitching', 'DisableChangePassword'
], newValue);
{ key: 'NoLogOff', value: newValue },
{ key: 'DisableLockWorkstation', value: newValue },
{ key: 'HideFastUserSwitching', value: newValue },
{ key: 'DisableChangePassword', value: newValue },
]);
}).catch(() => { });
}

View File

@@ -107,7 +107,7 @@ export default {
}
const handleOptionChange = (item) => {
updateRegistryOptions(pluginState.value.system.devices.map(c => c.MachineName), [item.key], item.value).then(() => {
updateRegistryOptions(pluginState.value.system.devices.map(c => c.MachineName), [{ key: item.key, value: item.value }]).then(() => {
ElMessage.success('已执行');
}).catch(() => {
ElMessage.error('执行失败');
@@ -119,7 +119,7 @@ export default {
ElMessage.error('请选择一个设备');
return;
}
updateRegistryOptions(pluginState.value.system.devices.map(c => c.MachineName), [item.key], value).then(() => {
updateRegistryOptions(pluginState.value.system.devices.map(c => c.MachineName), [{ key: item.key, value: value }]).then(() => {
ElMessage.success('已执行');
}).catch(() => {
ElMessage.error('执行失败');

View File

@@ -51,9 +51,9 @@ export default {
Server: pluginState.value.viewer.device,
Clients: clients,
}).then(() => {
pluginState.viewer.showShare = false;
pluginState.value.viewer.showShare = false;
ElMessage.success('操作成功');
}).catch(() => {
}).catch((e) => {
ElMessage.error('操作失败');
});
}

View File

@@ -23,6 +23,8 @@ export default {
update(item, report) {
if (!report.Viewer) return;
item.Viewer.share = report.Viewer.Value;
item.Viewer.mode = ['client', 'server'][report.Viewer.Mode];
}

View File

@@ -1,6 +1,6 @@
<template>
<div class="foot-options-wrap flex">
<el-button size="default" plain dark @click="handleRefresh">
<el-button size="small" plain dark @click="handleRefresh">
<el-icon>
<Refresh />
</el-icon>
@@ -19,7 +19,7 @@
</p>
</div>
<span class="flex-1"></span>
<el-button size="default" plain dark @click="handleUpdate">{{username}}</el-button>
<el-button size="small" plain dark @click="handleUpdate">{{username}}</el-button>
</div>
</template>
@@ -76,11 +76,11 @@ export default {
.options-btn {
.el-button+.el-button {
margin-left: 0.6rem;
margin-left: 0.4rem;
}
p {
padding-top: 0.6rem;
padding-top: 0.4rem;
&:nth-child(1) {
padding: 0;

View File

@@ -26,6 +26,7 @@ namespace cmonitor.client
SignInTask();
tcpServer.OnDisconnected += (hashcode) =>
{
Logger.Instance.Info($"client disconnected");
clientSignInState.PushNetworkDisabled();
};
}

View File

@@ -1,12 +1,12 @@
using cmonitor.client.runningConfig;
using cmonitor.client.report;
using cmonitor.client.ruleConfig;
using cmonitor.config;
using cmonitor.libs;
using cmonitor.startup;
using common.libs;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using cmonitor.server.ruleConfig;
namespace cmonitor.client
{
@@ -14,8 +14,6 @@ namespace cmonitor.client
{
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<RuleConfig>();
serviceCollection.AddSingleton<ClientReportTransfer>();
serviceCollection.AddSingleton<ClientSignInState>();
@@ -33,13 +31,13 @@ namespace cmonitor.client
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<RuleConfig>();
}
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
{
Logger.Instance.Info($"start client");
Logger.Instance.Info($"server ip {config.Server}");
Logger.Instance.Info($"server ip {config.Client.ServerEP}");
Logger.Instance.Info($"start client report transfer");
ClientReportTransfer report = serviceProvider.GetService<ClientReportTransfer>();

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cmonitor.client.ruleConfig
{
public interface IRuleConfig
{
public T Get<T>(T defaultValue);
public T Get<T>(string name, T defaultValue);
public void Set<T>(T data);
}
}

View File

@@ -1,675 +0,0 @@
using cmonitor.plugins.snatch.report;
using common.libs.database;
using System.ComponentModel.DataAnnotations.Schema;
namespace cmonitor.client.ruleConfig
{
[Table("rule")]
public sealed class RuleConfig
{
private readonly IConfigDataProvider<RuleConfig> configDataProvider;
public RuleConfig() { }
public RuleConfig(IConfigDataProvider<RuleConfig> configDataProvider)
{
this.configDataProvider = configDataProvider;
RuleConfig config = configDataProvider.Load().Result ?? new RuleConfig
{
UserNames = new Dictionary<string, UserNameInfo> { { "snltty", DefaultUser() } }
};
UserNames = config.UserNames;
MaxID = config.MaxID;
Save();
}
public Dictionary<string, UserNameInfo> UserNames { get; set; } = new Dictionary<string, UserNameInfo>();
private uint maxid = 100;
public uint MaxID
{
get => maxid; set
{
maxid = value;
}
}
private readonly object lockObj = new object();
private UserNameInfo DefaultUser()
{
return new UserNameInfo
{
Rules = new List<RulesInfo> { new RulesInfo { ID = 1, Name = "默认" } },
Processs = new List<GroupInfo> { new GroupInfo { ID = 2, Name = "默认" } },
Windows = new List<WindowGroupInfo> { new WindowGroupInfo { ID = 3, Name = "默认" } },
Snatchs = new List<SnatchGroupInfo> { new SnatchGroupInfo { ID = 4, Name = "默认" } },
Modes = "{}",
};
}
public string AddName(string name)
{
lock (lockObj)
{
if (UserNames.ContainsKey(name) == false)
{
UserNames.Add(name, DefaultUser());
}
Save();
}
return string.Empty;
}
public string AddProcessGroup(UpdateGroupInfo updateGroupInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateGroupInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
if (userNameInfo.Processs.FirstOrDefault(c => c.Name == updateGroupInfo.Group.Name && c.ID != updateGroupInfo.Group.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateGroupInfo.Group.ID == 0)
{
updateGroupInfo.Group.ID = Interlocked.Increment(ref maxid);
userNameInfo.Processs.Add(updateGroupInfo.Group);
Save();
return string.Empty;
}
//修改
GroupInfo old = userNameInfo.Processs.FirstOrDefault(c => c.ID == updateGroupInfo.Group.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Name = updateGroupInfo.Group.Name;
Save();
}
return string.Empty;
}
public string AddProcess(UpdateItemInfo updateItem)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateItem.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
GroupInfo group = userNameInfo.Processs.FirstOrDefault(c => c.ID == updateItem.GroupID);
if (group == null)
{
return "不存在此分组";
}
if (group.List.FirstOrDefault(c => c.Name == updateItem.Item.Name && c.ID != updateItem.Item.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateItem.Item.ID == 0)
{
updateItem.Item.ID = Interlocked.Increment(ref maxid);
group.List.Add(updateItem.Item);
Save();
return string.Empty;
}
//修改
ItemInfo old = group.List.FirstOrDefault(c => c.ID == updateItem.Item.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Name = updateItem.Item.Name;
old.AllowType = updateItem.Item.AllowType;
old.DataType = updateItem.Item.DataType;
Save();
}
return string.Empty;
}
public string DeleteProcessGroup(DeleteGroupInfo deleteGroupInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deleteGroupInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
userNameInfo.Processs.Remove(userNameInfo.Processs.FirstOrDefault(c => c.ID == deleteGroupInfo.ID));
Save();
}
return string.Empty;
}
public string DeleteProcess(DeleteItemInfo deleteItemInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deleteItemInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
GroupInfo group = userNameInfo.Processs.FirstOrDefault(c => c.ID == deleteItemInfo.GroupID);
if (group == null)
{
return "不存在此分组";
}
group.List.Remove(group.List.FirstOrDefault(c => c.ID == deleteItemInfo.ID));
}
return string.Empty;
}
public string AddRule(UpdateRuleInfo updateRuleInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateRuleInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
if (userNameInfo.Rules.FirstOrDefault(c => c.Name == updateRuleInfo.Rule.Name && c.ID != updateRuleInfo.Rule.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateRuleInfo.Rule.ID == 0)
{
updateRuleInfo.Rule.ID = Interlocked.Increment(ref maxid);
userNameInfo.Rules.Add(updateRuleInfo.Rule);
Save();
return string.Empty;
}
//修改
RulesInfo old = userNameInfo.Rules.FirstOrDefault(c => c.ID == updateRuleInfo.Rule.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Name = updateRuleInfo.Rule.Name;
old.PrivateProcesss = updateRuleInfo.Rule.PrivateProcesss;
old.PublicProcesss = updateRuleInfo.Rule.PublicProcesss;
Save();
}
return string.Empty;
}
public string DeleteRule(DeleteRuleInfo deleteRuleInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deleteRuleInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
userNameInfo.Rules.Remove(userNameInfo.Rules.FirstOrDefault(c => c.ID == deleteRuleInfo.ID));
Save();
}
return string.Empty;
}
public string UpdateDevices(UpdateDevicesInfo updatDevicesInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updatDevicesInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
userNameInfo.Devices = updatDevicesInfo.Devices;
Save();
}
return string.Empty;
}
public string AddWindowGroup(UpdateWindowGroupInfo updateGroupInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateGroupInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
if (userNameInfo.Windows.FirstOrDefault(c => c.Name == updateGroupInfo.Group.Name && c.ID != updateGroupInfo.Group.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateGroupInfo.Group.ID == 0)
{
updateGroupInfo.Group.ID = Interlocked.Increment(ref maxid);
userNameInfo.Windows.Add(updateGroupInfo.Group);
Save();
return string.Empty;
}
//修改
WindowGroupInfo old = userNameInfo.Windows.FirstOrDefault(c => c.ID == updateGroupInfo.Group.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Name = updateGroupInfo.Group.Name;
Save();
}
return string.Empty;
}
public string DeleteWindowGroup(DeleteWindowGroupInfo deleteGroupInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deleteGroupInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
userNameInfo.Windows.Remove(userNameInfo.Windows.FirstOrDefault(c => c.ID == deleteGroupInfo.ID));
Save();
}
return string.Empty;
}
public string AddWindow(AddWindowItemInfo updateItem)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateItem.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
WindowGroupInfo group = userNameInfo.Windows.FirstOrDefault(c => c.ID == updateItem.GroupID);
if (group == null)
{
return "不存在此分组";
}
if (group.List.FirstOrDefault(c => c.Name == updateItem.Item.Name && c.ID != updateItem.Item.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateItem.Item.ID == 0)
{
updateItem.Item.ID = Interlocked.Increment(ref maxid);
group.List.Add(updateItem.Item);
Save();
return string.Empty;
}
//修改
WindowItemInfo old = group.List.FirstOrDefault(c => c.ID == updateItem.Item.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Name = updateItem.Item.Name;
old.Desc = updateItem.Item.Desc;
Save();
}
return string.Empty;
}
public string DelWindow(DeletedWindowItemInfo deletedFileNameInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deletedFileNameInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
WindowGroupInfo group = userNameInfo.Windows.FirstOrDefault(c => c.ID == deletedFileNameInfo.GroupID);
if (group == null)
{
return "不存在此分组";
}
group.List.Remove(group.List.FirstOrDefault(c => c.ID == deletedFileNameInfo.ID));
Save();
}
return string.Empty;
}
public string AddSnatchGroup(UpdateSnatchGroupInfo updateGroupInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateGroupInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
if (userNameInfo.Windows.FirstOrDefault(c => c.Name == updateGroupInfo.Group.Name && c.ID != updateGroupInfo.Group.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateGroupInfo.Group.ID == 0)
{
updateGroupInfo.Group.ID = Interlocked.Increment(ref maxid);
userNameInfo.Snatchs.Add(updateGroupInfo.Group);
Save();
return string.Empty;
}
//修改
SnatchGroupInfo old = userNameInfo.Snatchs.FirstOrDefault(c => c.ID == updateGroupInfo.Group.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Name = updateGroupInfo.Group.Name;
Save();
}
return string.Empty;
}
public string DeleteSnatchGroup(DeleteSnatchGroupInfo deleteGroupInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deleteGroupInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
userNameInfo.Snatchs.Remove(userNameInfo.Snatchs.FirstOrDefault(c => c.ID == deleteGroupInfo.ID));
Save();
}
return string.Empty;
}
public string AddSnatch(AddSnatchItemInfo updateItem)
{
lock (lockObj)
{
if (UserNames.TryGetValue(updateItem.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
SnatchGroupInfo group = userNameInfo.Snatchs.FirstOrDefault(c => c.ID == updateItem.GroupID);
if (group == null)
{
return "不存在此分组";
}
if (group.List.FirstOrDefault(c => c.Title == updateItem.Item.Title && c.ID != updateItem.Item.ID) != null)
{
return "已存在同名记录";
}
//添加
if (updateItem.Item.ID == 0)
{
updateItem.Item.ID = Interlocked.Increment(ref maxid);
group.List.Add(updateItem.Item);
Save();
return string.Empty;
}
//修改
SnatchItemInfo old = group.List.FirstOrDefault(c => c.ID == updateItem.Item.ID);
if (old == null)
{
return "不存在记录,无法修改";
}
old.Type = updateItem.Item.Type;
old.Title = updateItem.Item.Title;
old.Question = updateItem.Item.Question;
old.Options = updateItem.Item.Options;
old.Correct = updateItem.Item.Correct;
old.Chance = updateItem.Item.Chance;
Save();
}
return string.Empty;
}
public string DelSnatch(DeletedSnatchItemInfo deletedFileNameInfo)
{
lock (lockObj)
{
if (UserNames.TryGetValue(deletedFileNameInfo.UserName, out UserNameInfo userNameInfo) == false)
{
return "不存在此管理用户";
}
SnatchGroupInfo group = userNameInfo.Snatchs.FirstOrDefault(c => c.ID == deletedFileNameInfo.GroupID);
if (group == null)
{
return "不存在此分组";
}
group.List.Remove(group.List.FirstOrDefault(c => c.ID == deletedFileNameInfo.ID));
Save();
}
return string.Empty;
}
public SnatchItemInfo[] SnatchRandom(int length)
{
return UserNames.Values
.SelectMany(c => c.Snatchs)
.SelectMany(c => c.List).OrderBy(c => Guid.NewGuid())
.Where(c => c.Cate == SnatchCate.Question)
.Where(c => c.Type == SnatchType.Select && c.Options.Any(c => c.Value) || c.Type == SnatchType.Input && string.IsNullOrWhiteSpace(c.Correct) == false)
.Take(length).ToArray();
}
public string UpdateModes(UpdateModesInfo info)
{
if (UserNames.TryGetValue(info.UserName, out UserNameInfo userNameInfo))
{
userNameInfo.Modes = info.Modes;
}
return string.Empty;
}
public void Save()
{
configDataProvider.Save(this).Wait();
}
}
public sealed class UserNameInfo
{
public List<RulesInfo> Rules { get; set; } = new List<RulesInfo>();
public List<GroupInfo> Processs { get; set; } = new List<GroupInfo>();
public List<string> Devices { get; set; } = new List<string>();
public List<WindowGroupInfo> Windows { get; set; } = new List<WindowGroupInfo>();
public List<SnatchGroupInfo> Snatchs { get; set; } = new List<SnatchGroupInfo>();
public string Modes { get; set; } = "{}";
}
public sealed class UpdateDevicesInfo
{
public string UserName { get; set; }
public List<string> Devices { get; set; } = new List<string>();
}
public sealed class RulesInfo
{
public uint ID { get; set; }
public string Name { get; set; }
public List<uint> PrivateProcesss { get; set; } = new List<uint>();
public List<uint> PublicProcesss { get; set; } = new List<uint>();
}
public sealed class UpdateRuleInfo
{
public string UserName { get; set; }
public RulesInfo Rule { get; set; }
}
public sealed class DeleteRuleInfo
{
public string UserName { get; set; }
public uint ID { get; set; }
}
public sealed class GroupInfo
{
public uint ID { get; set; }
public string Name { get; set; }
public List<ItemInfo> List { get; set; } = new List<ItemInfo>();
}
public sealed class UpdateGroupInfo
{
public string UserName { get; set; }
public GroupInfo Group { get; set; }
}
public sealed class DeleteGroupInfo
{
public string UserName { get; set; }
public uint ID { get; set; }
}
public sealed class ItemInfo
{
public uint ID { get; set; }
public string Name { get; set; }
public DataType DataType { get; set; }
public AllowType AllowType { get; set; }
}
public enum DataType
{
Process = 0,
Domain = 1,
IP = 2,
}
public enum AllowType
{
Allow = 0,
Denied = 1
}
public sealed class UpdateItemInfo
{
public string UserName { get; set; }
public uint GroupID { get; set; }
public ItemInfo Item { get; set; }
}
public sealed class DeleteItemInfo
{
public string UserName { get; set; }
public uint GroupID { get; set; }
public uint ID { get; set; }
}
public sealed class WindowGroupInfo
{
public uint ID { get; set; }
public string Name { get; set; }
public List<WindowItemInfo> List { get; set; } = new List<WindowItemInfo>();
}
public sealed class UpdateWindowGroupInfo
{
public string UserName { get; set; }
public WindowGroupInfo Group { get; set; }
}
public sealed class DeleteWindowGroupInfo
{
public string UserName { get; set; }
public uint ID { get; set; }
}
public sealed class WindowItemInfo
{
public uint ID { get; set; }
public string Name { get; set; }
public string Desc { get; set; }
}
public sealed class AddWindowItemInfo
{
public string UserName { get; set; }
public uint GroupID { get; set; }
public WindowItemInfo Item { get; set; }
}
public sealed class DeletedWindowItemInfo
{
public string UserName { get; set; }
public uint GroupID { get; set; }
public uint ID { get; set; }
}
public sealed class SnatchGroupInfo
{
public uint ID { get; set; }
public string Name { get; set; }
public List<SnatchItemInfo> List { get; set; } = new List<SnatchItemInfo>();
}
public sealed class UpdateSnatchGroupInfo
{
public string UserName { get; set; }
public SnatchGroupInfo Group { get; set; }
}
public sealed class DeleteSnatchGroupInfo
{
public string UserName { get; set; }
public uint ID { get; set; }
}
public sealed class AddSnatchItemInfo
{
public string UserName { get; set; }
public uint GroupID { get; set; }
public SnatchItemInfo Item { get; set; }
}
public sealed class DeletedSnatchItemInfo
{
public string UserName { get; set; }
public uint GroupID { get; set; }
public uint ID { get; set; }
}
public sealed class SnatchItemInfo
{
public uint ID { get; set; }
public string Title { get; set; }
public SnatchCate Cate { get; set; } = SnatchCate.Question;
public SnatchType Type { get; set; } = SnatchType.Select;
/// <summary>
/// 问题
/// </summary>
public string Question { get; set; }
/// <summary>
/// 选项数
/// </summary>
public List<SnatchItemOptionInfo> Options { get; set; }
/// <summary>
/// 答案
/// </summary>
public string Correct { get; set; }
/// <summary>
/// 最多答题次数
/// </summary>
public int Chance { get; set; }
}
public sealed class SnatchItemOptionInfo
{
public string Text { get; set; }
public bool Value { get; set; }
}
public sealed class UpdateModesInfo
{
public string UserName { get; set; }
public string Modes { get; set; }
}
}

View File

@@ -1,75 +0,0 @@
namespace cmonitor.client.ruleConfig
{
/*
public sealed class RuleConfigJsonFile : IRuleConfig
{
private Dictionary<string, object> cache = new Dictionary<string, object>();
public RuleConfigJsonFile()
{
}
public T Get<T>(T defaultValue)
{
string name = nameof(T);
return Get(name, defaultValue);
}
public T Get<T>(string name, T defaultValue)
{
try
{
if (cache.TryGetValue(name, out object cacheValue))
{
return (T)cacheValue;
}
string value = (Registry.GetValue(savePath, name, string.Empty)).ToString();
if (string.IsNullOrWhiteSpace(value))
{
T data = value.DeJson<T>();
cache[name] = data;
return data;
}
}
catch (Exception)
{
}
return defaultValue;
}
public void Set<T>(T data)
{
try
{
string name = nameof(T);
string value = data.ToJson();
Registry.SetValue(savePath, name, value);
cache[name] = data;
}
catch (Exception)
{
}
}
}
[Table("rule-config")]
public sealed class RuleConfig
{
private readonly IConfigDataProvider<RuleConfig> configDataProvider;
public RuleConfig() { }
public RuleConfig(IConfigDataProvider<RuleConfig> configDataProvider)
{
this.configDataProvider = configDataProvider;
RuleConfig config = configDataProvider.Load().Result ?? new RuleConfig
{
UserNames = new Dictionary<string, string> { { "snltty", "{}" } }
};
UserNames = config.UserNames;
}
public Dictionary<string, string> UserNames { get; set; } = new Dictionary<string, string>();
}*/
}

View File

@@ -121,7 +121,7 @@ namespace cmonitor.config
public sealed class ConfigCommonInfo
{
public string[] Modes { get; set; } = new string[] { "client", /*"server"*/ };
public string[] Modes { get; set; } = new string[] { "client", "server" };
}
public sealed class ConfigClientInfo
{

View File

@@ -1,9 +1,9 @@
using cmonitor.api;
using cmonitor.client.ruleConfig;
using cmonitor.plugins.active.messenger;
using cmonitor.plugins.active.report;
using cmonitor.plugins.signIn.messenger;
using cmonitor.server;
using cmonitor.server.ruleConfig;
using common.libs;
using common.libs.extends;
using MemoryPack;
@@ -14,8 +14,8 @@ namespace cmonitor.plugins.active
{
private readonly MessengerSender messengerSender;
private readonly SignCaching signCaching;
private readonly RuleConfig ruleConfig;
public ActiveApiController(MessengerSender messengerSender, SignCaching signCaching, RuleConfig ruleConfig)
private readonly IRuleConfig ruleConfig;
public ActiveApiController(MessengerSender messengerSender, SignCaching signCaching, IRuleConfig ruleConfig)
{
this.messengerSender = messengerSender;
this.signCaching = signCaching;
@@ -72,8 +72,8 @@ namespace cmonitor.plugins.active
public async Task<bool> Disallow(ApiControllerParamsInfo param)
{
DisallowInfo disallowInfo = param.Content.DeJson<DisallowInfo>();
byte[] bytes = MemoryPackSerializer.Serialize(new ActiveDisallowInfo { FileNames = disallowInfo.FileNames, Ids = disallowInfo.Ids });
foreach (string name in disallowInfo.UserNames)
byte[] bytes = MemoryPackSerializer.Serialize(new ActiveDisallowInfo { FileNames = disallowInfo.Data, Ids1 = disallowInfo.Ids1, Ids2 = disallowInfo.Ids2 });
foreach (string name in disallowInfo.Devices)
{
if (signCaching.Get(name, out SignCacheInfo cache) && cache.Connected)
{
@@ -92,7 +92,7 @@ namespace cmonitor.plugins.active
public async Task<bool> Kill(ApiControllerParamsInfo param)
{
ActiveKillInfo activeKillInfo = param.Content.DeJson<ActiveKillInfo>();
byte[] bytes = activeKillInfo.pid.ToBytes();
byte[] bytes = activeKillInfo.Pid.ToBytes();
if (signCaching.Get(activeKillInfo.UserName, out SignCacheInfo cache) && cache.Connected)
{
await messengerSender.SendOnly(new MessageRequestWrap
@@ -107,34 +107,42 @@ namespace cmonitor.plugins.active
return false;
}
public string AddGroup(ApiControllerParamsInfo param)
public string Update(ApiControllerParamsInfo param)
{
return ruleConfig.AddWindowGroup(param.Content.DeJson<UpdateWindowGroupInfo>());
}
public string DeleteGroup(ApiControllerParamsInfo param)
{
return ruleConfig.DeleteWindowGroup(param.Content.DeJson<DeleteWindowGroupInfo>());
}
public string Add(ApiControllerParamsInfo param)
{
return ruleConfig.AddWindow(param.Content.DeJson<AddWindowItemInfo>());
}
public string Del(ApiControllerParamsInfo param)
{
return ruleConfig.DelWindow(param.Content.DeJson<DeletedWindowItemInfo>());
UpdateWindowGroupInfo model = param.Content.DeJson<UpdateWindowGroupInfo>();
ruleConfig.Set(model.UserName,"Windows", model.Data);
return string.Empty;
}
}
public sealed class UpdateWindowGroupInfo
{
public string UserName { get; set; }
public List<WindowGroupInfo> Data { get; set; } = new List<WindowGroupInfo>();
}
public sealed class WindowGroupInfo
{
public string Name { get; set; }
public List<WindowItemInfo> List { get; set; } = new List<WindowItemInfo>();
}
public sealed class WindowItemInfo
{
public string Name { get; set; }
public string Desc { get; set; }
}
public sealed class DisallowInfo
{
public string[] UserNames { get; set; }
public string[] FileNames { get; set; }
public uint[] Ids { get; set; }
public string[] Devices { get; set; }
public string[] Data { get; set; }
public string[] Ids1 { get; set; }
public string[] Ids2 { get; set; }
}
public sealed class ActiveKillInfo
{
public string UserName { get; set; }
public int pid { get; set; }
public int Pid { get; set; }
}
}

View File

@@ -37,7 +37,8 @@ namespace cmonitor.plugins.active.report
public object GetReports(ReportType reportType)
{
ticks = DateTime.UtcNow.Ticks;
report.Ids = activeConfig.Ids;
report.Ids1 = activeConfig.Ids1;
report.Ids2 = activeConfig.Ids2;
if (reportType == ReportType.Full || report.Updated())
{
return report;
@@ -141,7 +142,8 @@ namespace cmonitor.plugins.active.report
public sealed partial class ActiveDisallowInfo
{
public string[] FileNames { get; set; } = Array.Empty<string>();
public uint[] Ids { get; set; } = Array.Empty<uint>();
public string[] Ids1 { get; set; } = Array.Empty<string>();
public string[] Ids2 { get; set; } = Array.Empty<string>();
}
public sealed class ActiveReportInfo : ReportInfo
@@ -153,10 +155,11 @@ namespace cmonitor.plugins.active.report
public int DisallowCount { get; set; }
public int WindowCount { get; set; }
public uint[] Ids { get; set; }
public string[] Ids1 { get; set; }
public string[] Ids2 { get; set; }
public override int HashCode()
{
return Title.GetHashCode() ^ Pid.GetHashCode() ^ DisallowCount.GetHashCode() ^ Ids.GetHashCode();
return Title.GetHashCode() ^ Pid.GetHashCode() ^ DisallowCount.GetHashCode() ^ Ids1.GetHashCode() ^ Ids2.GetHashCode();
}
}

View File

@@ -0,0 +1,28 @@
using cmonitor.api;
using cmonitor.server.ruleConfig;
using common.libs.extends;
namespace cmonitor.plugins.devices
{
public sealed class DevicesApiController : IApiController
{
private readonly IRuleConfig ruleConfig;
public DevicesApiController(IRuleConfig ruleConfig)
{
this.ruleConfig = ruleConfig;
}
public string Update(ApiControllerParamsInfo param)
{
UpdateDevicesInfo model = param.Content.DeJson<UpdateDevicesInfo>();
ruleConfig.Set(model.UserName, "Devices", model.Data);
return string.Empty;
}
public sealed class UpdateDevicesInfo
{
public string UserName { get; set; }
public List<string> Data { get; set; } = new List<string>();
}
}
}

View File

@@ -1,26 +1,24 @@
using cmonitor.config;
using cmonitor.plugins.setting.messenger;
using cmonitor.startup;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
namespace cmonitor.plugins.setting
namespace cmonitor.plugins.devices
{
public sealed class SettingStartup : IStartup
public sealed class DevicesStartup : IStartup
{
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<SettingClientMessenger>();
}
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<SettingApiController>();
serviceCollection.AddSingleton<DevicesApiController>();
}
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
{
}
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)

View File

@@ -1,9 +1,9 @@
using cmonitor.api;
using cmonitor.client.ruleConfig;
using cmonitor.plugins.hijack.messenger;
using cmonitor.plugins.hijack.report;
using cmonitor.plugins.signIn.messenger;
using cmonitor.server;
using cmonitor.server.ruleConfig;
using common.libs.extends;
using MemoryPack;
@@ -11,57 +11,72 @@ namespace cmonitor.plugins.hijack
{
public sealed class HijackApiController : IApiController
{
private readonly RuleConfig ruleConfig;
private readonly IRuleConfig ruleConfig;
private readonly SignCaching signCaching;
private readonly MessengerSender messengerSender;
public HijackApiController(RuleConfig ruleConfig, SignCaching signCaching, MessengerSender messengerSender)
public HijackApiController(IRuleConfig ruleConfig, SignCaching signCaching, MessengerSender messengerSender)
{
this.ruleConfig = ruleConfig;
this.signCaching = signCaching;
this.messengerSender = messengerSender;
}
public Dictionary<string, UserNameInfo> Info(ApiControllerParamsInfo param)
{
return ruleConfig.UserNames;
}
public string AddName(ApiControllerParamsInfo param)
{
return ruleConfig.AddName(param.Content);
}
public string AddProcessGroup(ApiControllerParamsInfo param)
public string UpdateRule(ApiControllerParamsInfo param)
{
return ruleConfig.AddProcessGroup(param.Content.DeJson<UpdateGroupInfo>());
UpdateRuleInfo model = param.Content.DeJson<UpdateRuleInfo>();
ruleConfig.Set(model.UserName,"Rules", model.Data);
return string.Empty;
}
public string DeleteProcessGroup(ApiControllerParamsInfo param)
public sealed class RulesInfo
{
return ruleConfig.DeleteProcessGroup(param.Content.DeJson<DeleteGroupInfo>());
public string Name { get; set; }
public List<string> PrivateProcesss { get; set; } = new List<string>();
public List<string> PublicProcesss { get; set; } = new List<string>();
}
public string AddProcess(ApiControllerParamsInfo param)
public sealed class UpdateRuleInfo
{
return ruleConfig.AddProcess(param.Content.DeJson<UpdateItemInfo>());
}
public string DeleteProcess(ApiControllerParamsInfo param)
{
return ruleConfig.DeleteProcess(param.Content.DeJson<DeleteItemInfo>());
public string UserName { get; set; }
public List<RulesInfo> Data { get; set; }
}
public string AddRule(ApiControllerParamsInfo param)
public string UpdateProcess(ApiControllerParamsInfo param)
{
return ruleConfig.AddRule(param.Content.DeJson<UpdateRuleInfo>());
UpdateHijackInfo model = param.Content.DeJson<UpdateHijackInfo>();
ruleConfig.Set(model.UserName, "Processs", model.Data);
return string.Empty;
}
public string DeleteRule(ApiControllerParamsInfo param)
public sealed class HijackGroupInfo
{
return ruleConfig.DeleteRule(param.Content.DeJson<DeleteRuleInfo>());
public string Name { get; set; }
public List<HijackItemInfo> List { get; set; } = new List<HijackItemInfo>();
}
public sealed class HijackItemInfo
{
public string Name { get; set; }
public HijackDataType DataType { get; set; }
public HijackAllowType AllowType { get; set; }
}
public enum HijackDataType
{
Process = 0,
Domain = 1,
IP = 2,
}
public enum HijackAllowType
{
Allow = 0,
Denied = 1
}
public sealed class UpdateHijackInfo
{
public string UserName { get; set; }
public List<HijackGroupInfo> Data { get; set; }
}
public string UpdateDevices(ApiControllerParamsInfo param)
{
return ruleConfig.UpdateDevices(param.Content.DeJson<UpdateDevicesInfo>());
}
public async Task<List<string>> SetRules(ApiControllerParamsInfo param)
public async Task<List<string>> UseHijackRules(ApiControllerParamsInfo param)
{
List<string> errorDevices = new List<string>();
SetRuleParamInfo setRuleParamInfo = param.Content.DeJson<SetRuleParamInfo>();
@@ -69,9 +84,9 @@ namespace cmonitor.plugins.hijack
{
byte[] bytes = MemoryPackSerializer.Serialize(new HijackSetRuleInfo
{
Rules = setRuleParamInfo.Rules,
Ids = setRuleParamInfo.Ids,
Rules = setRuleParamInfo.Data,
Ids1 = setRuleParamInfo.Ids1,
Ids2 = setRuleParamInfo.Ids2,
});
for (int i = 0; i < setRuleParamInfo.Devices.Length; i++)
{
@@ -92,12 +107,12 @@ namespace cmonitor.plugins.hijack
}
return errorDevices;
}
public sealed class SetRuleParamInfo
{
public string[] Devices { get; set; }
public HijackRuleUpdateInfo Rules { get; set; }
public uint[] Ids { get; set; }
public HijackRuleUpdateInfo Data { get; set; }
public string[] Ids1 { get; set; }
public string[] Ids2 { get; set; }
}
}
}

View File

@@ -34,7 +34,8 @@
/// </summary>
public string[] DeniedIPs { get; set; } = Array.Empty<string>();
public uint[] HijackIds { get; set; } = Array.Empty<uint>();
public string[] HijackIds1 { get; set; } = Array.Empty<string>();
public string[] HijackIds2 { get; set; } = Array.Empty<string>();
public bool DomainKill { get; set; }

View File

@@ -43,7 +43,8 @@ namespace cmonitor.plugins.hijack.report
hijackConfig.DeniedIPs = config.DeniedIPs;
hijackConfig.AllowIPs = config.AllowIPs;
hijackConfig.DomainKill = config.DomainKill;
hijackConfig.HijackIds = config.HijackIds;
hijackConfig.HijackIds1 = config.HijackIds1;
hijackConfig.HijackIds2 = config.HijackIds2;
UpdateRules();
}
catch (Exception ex)
@@ -61,7 +62,8 @@ namespace cmonitor.plugins.hijack.report
hijackConfig.AllowIPs = info.Rules.AllowIPs;
hijackConfig.DeniedIPs = info.Rules.DeniedIPs;
hijackConfig.DomainKill = info.Rules.DomainKill;
hijackConfig.HijackIds = info.Ids;
hijackConfig.HijackIds1 = info.Ids1;
hijackConfig.HijackIds2 = info.Ids2;
clientConfig.Set(hijackConfig);
@@ -81,7 +83,8 @@ namespace cmonitor.plugins.hijack.report
hijackReportInfo.Upload = hijack.UdpSend + hijack.TcpSend;
hijackReportInfo.Download = hijack.TcpReceive + hijack.UdpReceive;
hijackReportInfo.Count = (ulong)(hijackConfig.AllowIPs.Length + hijackConfig.DeniedIPs.Length + hijackConfig.AllowDomains.Length + hijackConfig.DeniedDomains.Length + hijackConfig.AllowProcesss.Length + hijackConfig.DeniedProcesss.Length);
hijackReportInfo.Ids = hijackConfig.HijackIds;
hijackReportInfo.Ids1 = hijackConfig.HijackIds1;
hijackReportInfo.Ids2 = hijackConfig.HijackIds2;
hijackReportInfo.DomainKill = hijackConfig.DomainKill;
long _ticks = DateTime.UtcNow.Ticks;
@@ -100,12 +103,13 @@ namespace cmonitor.plugins.hijack.report
public ulong Download { get; set; }
public ulong Count { get; set; }
public uint[] Ids { get; set; }
public string[] Ids1 { get; set; }
public string[] Ids2 { get; set; }
public bool DomainKill { get; set; }
public override int HashCode()
{
return Upload.GetHashCode() ^ Download.GetHashCode() ^ Count.GetHashCode() ^ Ids.GetHashCode();
return Upload.GetHashCode() ^ Download.GetHashCode() ^ Count.GetHashCode() ^ Ids1.GetHashCode() ^ Ids2.GetHashCode();
}
}
@@ -114,7 +118,8 @@ namespace cmonitor.plugins.hijack.report
public sealed partial class HijackSetRuleInfo
{
public HijackRuleUpdateInfo Rules { get; set; }
public uint[] Ids { get; set; }
public string[] Ids1 { get; set; }
public string[] Ids2 { get; set; }
}

View File

@@ -161,6 +161,9 @@ namespace cmonitor.plugins.hijack.report.hijack
NFAPI.nf_udpPostSend(id, remoteAddress, buf, len, options);
}
private bool processWhiteAny = false;
private bool processBlackAny = false;
/// <summary>
/// 设置进程列表
/// </summary>
@@ -169,7 +172,10 @@ namespace cmonitor.plugins.hijack.report.hijack
public void SetProcess(string[] white, string[] black)
{
processWhite = white;
processWhiteAny = white.Any(c => c == "*");
processBlack = black;
processBlackAny = black.Any(c => c == "*");
}
/// <summary>
/// 设置域名列表
@@ -205,20 +211,44 @@ namespace cmonitor.plugins.hijack.report.hijack
domainIPs.Clear();
foreach (string domain in domainWhite)
{
IPHostEntry entry = Dns.GetHostEntry(domain);
foreach (var item in entry.AddressList)
if (domain == "*")
{
domainIPs[IPAddress.Any] = AllowType.Allow;
continue;
}
try
{
IPHostEntry entry = Dns.GetHostEntry(domain);
foreach (var item in entry.AddressList)
{
domainIPs[item] = AllowType.Allow;
}
}
catch (Exception)
{
domainIPs[item] = AllowType.Allow;
}
}
foreach (string domain in domainBlack)
{
IPHostEntry entry = Dns.GetHostEntry(domain);
foreach (IPAddress item in entry.AddressList)
if (domain == "*")
{
domainIPs[IPAddress.Any] = AllowType.Denied;
continue;
}
if (domainIPs.ContainsKey(item) == false)
domainIPs[item] = AllowType.Denied;
try
{
IPHostEntry entry = Dns.GetHostEntry(domain);
foreach (IPAddress item in entry.AddressList)
{
if (domainIPs.ContainsKey(item) == false)
domainIPs[item] = AllowType.Denied;
}
}
catch (Exception)
{
}
}
KillProcessWithDomainBlack();
@@ -292,14 +322,14 @@ namespace cmonitor.plugins.hijack.report.hijack
{
index += 2;
}
index += 2;//transID
index += 2;//跳过transID
ushort flag = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2;
ushort quesions = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2;
ushort answers = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2;
index += 4; // au2 + ad2
index += 4; //跳过 au 2字节 + ad 2字节
byte rcode = (byte)(flag & 0b1111);
byte tc = (byte)(flag >> 9 & 0x01);
@@ -332,22 +362,22 @@ namespace cmonitor.plugins.hijack.report.hijack
{
return null; //不是A查询
}
index += 2; //class
index += 2; //跳过class
string domain = Encoding.UTF8.GetString(domainCache.Span.Slice(0, domainPosition));
IPAddress[] ips = new IPAddress[answers];
//answers
for (int i = 0; i < answers; i++)
{
index += 2; //指针
index += 2; //跳过指针
type = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2;
index += 2;//class
index += 4;//timeLive
index += 2;//跳过class
index += 4;//跳过timeLive
int dataLength = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(index));
index += 2;
if (type == 1)
if (type == 1) //是A回应其它的不要
{
ips[i] = new IPAddress(span.Slice(index, dataLength));
}
@@ -394,7 +424,9 @@ namespace cmonitor.plugins.hijack.report.hijack
}
private unsafe bool DeniedIP(uint processId, IPAddress ip)
{
if (ip != null && domainIPs.TryGetValue(ip, out AllowType type))
bool res = domainIPs.TryGetValue(IPAddress.Any, out AllowType type) && type == AllowType.Denied;
if (ip != null && domainIPs.TryGetValue(ip, out type))
{
if (type == AllowType.Denied && domainKill)
{
@@ -414,7 +446,7 @@ namespace cmonitor.plugins.hijack.report.hijack
}
return type == AllowType.Denied;
}
return false;
return res;
}
private unsafe IPAddress ReadIPAddress(nint remoteAddress)
{
@@ -449,6 +481,9 @@ namespace cmonitor.plugins.hijack.report.hijack
{
return false;
}
bool res = processBlackAny;
processName = NFAPI.nf_getProcessName(processId);
//白名单
if (processWhite.Length > 0 && CheckName(processWhite, processName))
@@ -456,17 +491,19 @@ namespace cmonitor.plugins.hijack.report.hijack
return false;
}
//黑名单
if (processBlack.Length > 0)
if (processBlack.Length > 0 && CheckName(processBlack, processName))
{
return CheckName(processBlack, processName);
return true;
}
return false;
return res;
}
private bool CheckName(string[] names, string path)
{
bool res = false;
for (int i = 0; i < names.Length; i++)
{
if (names[i].Length > path.Length) continue;
@@ -484,7 +521,7 @@ namespace cmonitor.plugins.hijack.report.hijack
{
}
}
return false;
return res;
}

View File

@@ -1,26 +1,37 @@
using cmonitor.api;
using cmonitor.client.ruleConfig;
using cmonitor.plugins.signIn.messenger;
using cmonitor.server;
using cmonitor.server.ruleConfig;
using common.libs.extends;
namespace cmonitor.plugins.modes
{
public sealed class ModesApiController : IApiController
{
private readonly RuleConfig ruleConfig;
private readonly SignCaching signCaching;
private readonly MessengerSender messengerSender;
public ModesApiController(RuleConfig ruleConfig, SignCaching signCaching, MessengerSender messengerSender)
private readonly IRuleConfig ruleConfig;
public ModesApiController(IRuleConfig ruleConfig)
{
this.ruleConfig = ruleConfig;
this.signCaching = signCaching;
this.messengerSender = messengerSender;
}
public string Update(ApiControllerParamsInfo param)
{
return ruleConfig.UpdateModes(param.Content.DeJson<UpdateModesInfo>());
UpdateModesInfo info = param.Content.DeJson<UpdateModesInfo>();
ruleConfig.Set(info.UserName, "Modes", info.Data);
return string.Empty;
}
public sealed class ModesInfo
{
public string Name { get; set; }
public string Data { get; set; }
}
public sealed class UpdateModesInfo
{
public string UserName { get; set; }
public List<ModesInfo> Data { get; set; } = new List<ModesInfo>();
}
}
}

View File

@@ -0,0 +1,24 @@
using cmonitor.api;
using cmonitor.server.ruleConfig;
namespace cmonitor.plugins.rule
{
public sealed class RuleApiController : IApiController
{
private readonly IRuleConfig ruleConfig;
public RuleApiController(IRuleConfig ruleConfig)
{
this.ruleConfig = ruleConfig;
}
public RuleConfigInfo Info(ApiControllerParamsInfo param)
{
return ruleConfig.Data;
}
public string AddName(ApiControllerParamsInfo param)
{
ruleConfig.AddUser(param.Content);
return string.Empty;
}
}
}

View File

@@ -0,0 +1,28 @@
using cmonitor.config;
using cmonitor.startup;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
namespace cmonitor.plugins.rule
{
public sealed class RuleStartup : IStartup
{
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
}
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<RuleApiController>();
}
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
{
}
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
{
}
}
}

View File

@@ -1,51 +0,0 @@
using cmonitor.api;
using cmonitor.config;
using cmonitor.plugins.setting.messenger;
using cmonitor.plugins.signIn.messenger;
using cmonitor.server;
using common.libs.extends;
using MemoryPack;
namespace cmonitor.plugins.setting
{
public sealed class SettingApiController : IApiController
{
private readonly MessengerSender messengerSender;
private readonly SignCaching signCaching;
private readonly Config config;
public SettingApiController(MessengerSender messengerSender, SignCaching signCaching, Config config)
{
this.messengerSender = messengerSender;
this.signCaching = signCaching;
this.config = config;
}
public SettingInfo Get(ApiControllerParamsInfo param)
{
return new SettingInfo
{
};
}
public bool Set(ApiControllerParamsInfo param)
{
SettingInfo settingInfo = param.Content.DeJson<SettingInfo>();
byte[] bytes = MemoryPackSerializer.Serialize(settingInfo);
foreach (var item in signCaching.Get())
{
if (item.Connected)
{
_ = messengerSender.SendOnly(new MessageRequestWrap
{
Connection = item.Connection,
MessengerId = (ushort)SettingMessengerIds.Update,
Payload = bytes
});
}
}
return true;
}
}
}

View File

@@ -1,42 +0,0 @@
using cmonitor.config;
using cmonitor.server;
using MemoryPack;
namespace cmonitor.plugins.setting.messenger
{
public sealed class SettingClientMessenger : IMessenger
{
private Config config;
public SettingClientMessenger(Config config)
{
this.config = config;
}
[MessengerId((ushort)SettingMessengerIds.Update)]
public void Update(IConnection connection)
{
SettingInfo settingInfo = MemoryPackSerializer.Deserialize<SettingInfo>(connection.ReceiveRequestWrap.Payload.Span);
}
}
[MemoryPackable]
public sealed partial class SettingShareInfo
{
public float ScreenScale { get; set; } = 0.2f;
public int ScreenDelay { get; set; } = 30;
}
[MemoryPackable]
public sealed partial class SettingInfo
{
public int ReportDelay { get; set; } = 30;
public float ScreenScale { get; set; } = 0.2f;
public int ScreenDelay { get; set; } = 30;
public bool SaveSetting { get; set; } = true;
public bool WakeUp { get; set; } = true;
public bool VolumeMasterPeak { get; set; } = true;
}
}

View File

@@ -1,9 +0,0 @@
namespace cmonitor.plugins.setting.messenger
{
public enum SettingMessengerIds : ushort
{
Update = 1300,
None = 1399
}
}

View File

@@ -1,9 +1,9 @@
using cmonitor.api;
using cmonitor.client.ruleConfig;
using cmonitor.plugins.signIn.messenger;
using cmonitor.plugins.snatch.messenger;
using cmonitor.plugins.snatch.report;
using cmonitor.server;
using cmonitor.server.ruleConfig;
using common.libs.extends;
namespace cmonitor.plugins.snatch
@@ -11,11 +11,11 @@ namespace cmonitor.plugins.snatch
public sealed class SnatchApiController : IApiController
{
private readonly MessengerSender messengerSender;
private readonly RuleConfig ruleConfig;
private readonly IRuleConfig ruleConfig;
private readonly SignCaching signCaching;
private readonly ISnatachCaching snatachCaching;
public SnatchApiController(RuleConfig ruleConfig, MessengerSender messengerSender, SignCaching signCaching, ISnatachCaching snatachCaching)
public SnatchApiController(IRuleConfig ruleConfig, MessengerSender messengerSender, SignCaching signCaching, ISnatachCaching snatachCaching)
{
this.ruleConfig = ruleConfig;
this.messengerSender = messengerSender;
@@ -23,24 +23,13 @@ namespace cmonitor.plugins.snatch
this.snatachCaching = snatachCaching;
}
public string AddGroup(ApiControllerParamsInfo param)
public string Update(ApiControllerParamsInfo param)
{
return ruleConfig.AddSnatchGroup(param.Content.DeJson<UpdateSnatchGroupInfo>());
UpdateSnatchGroupInfo model = param.Content.DeJson<UpdateSnatchGroupInfo>();
ruleConfig.Set(model.UserName,"Snatchs", model.Data);
return string.Empty;
}
public string DeleteGroup(ApiControllerParamsInfo param)
{
return ruleConfig.DeleteSnatchGroup(param.Content.DeJson<DeleteSnatchGroupInfo>());
}
public string Add(ApiControllerParamsInfo param)
{
return ruleConfig.AddSnatch(param.Content.DeJson<AddSnatchItemInfo>());
}
public string Del(ApiControllerParamsInfo param)
{
return ruleConfig.DelSnatch(param.Content.DeJson<DeletedSnatchItemInfo>());
}
public AnswerGroupInfo[] GetQuestion(ApiControllerParamsInfo param)
{
if (snatachCaching.Get(param.Content, out SnatchQuestionCacheInfo info))
@@ -54,6 +43,7 @@ namespace cmonitor.plugins.snatch
return Array.Empty<AnswerGroupInfo>();
}
public async Task<bool> AddQuestion(ApiControllerParamsInfo param)
{
SnatchQuestionCacheParamInfo info = param.Content.DeJson<SnatchQuestionCacheParamInfo>();
@@ -78,10 +68,6 @@ namespace cmonitor.plugins.snatch
}
return true;
}
public SnatchItemInfo[] RandomQuestion(ApiControllerParamsInfo param)
{
return ruleConfig.SnatchRandom(int.Parse(param.Content));
}
public async Task<bool> UpdateQuestion(ApiControllerParamsInfo param)
{
UpdateQuestionCacheParamInfo info = param.Content.DeJson<UpdateQuestionCacheParamInfo>();
@@ -133,24 +119,62 @@ namespace cmonitor.plugins.snatch
public string UserName { get; set; }
public UpdateQuestionCacheParamItemInfo[] Items { get; set; }
}
public sealed class UpdateQuestionCacheParamItemInfo
{
public string MachineName { get; set; }
public SnatchQuestionInfo Question { get; set; }
}
public sealed class SnatchQuestionCacheParamInfo
{
public SnatchQuestionCacheInfo Cache { get; set; }
public SnatchQuestionInfo Question { get; set; }
}
public sealed class AnswerGroupInfo
{
public SnatchQuestionInfo Question { get; set; }
public SnatchAnswerInfo[] Answers { get; set; }
}
public sealed class SnatchGroupInfo
{
public string Name { get; set; }
public List<SnatchItemInfo> List { get; set; } = new List<SnatchItemInfo>();
}
public sealed class UpdateSnatchGroupInfo
{
public string UserName { get; set; }
public List<SnatchGroupInfo> Data { get; set; }
}
public sealed class SnatchItemInfo
{
public uint ID { get; set; }
public string Title { get; set; }
public SnatchCate Cate { get; set; } = SnatchCate.Question;
public SnatchType Type { get; set; } = SnatchType.Select;
/// <summary>
/// 问题
/// </summary>
public string Question { get; set; }
/// <summary>
/// 选项数
/// </summary>
public List<SnatchItemOptionInfo> Options { get; set; }
/// <summary>
/// 答案
/// </summary>
public string Correct { get; set; }
/// <summary>
/// 最多答题次数
/// </summary>
public int Chance { get; set; }
}
public sealed class SnatchItemOptionInfo
{
public string Text { get; set; }
public bool Value { get; set; }
}
}
}

View File

@@ -21,9 +21,9 @@ namespace cmonitor.plugins.system
{
PasswordInfo info = param.Content.DeJson<PasswordInfo>();
byte[] bytes = MemoryPackSerializer.Serialize(info.Input);
for (int i = 0; i < info.Names.Length; i++)
for (int i = 0; i < info.Devices.Length; i++)
{
if (signCaching.Get(info.Names[i], out SignCacheInfo cache) && cache.Connected)
if (signCaching.Get(info.Devices[i], out SignCacheInfo cache) && cache.Connected)
{
await messengerSender.SendOnly(new MessageRequestWrap
{
@@ -40,10 +40,10 @@ namespace cmonitor.plugins.system
public async Task<bool> RegistryOptions(ApiControllerParamsInfo param)
{
RegistryInfo info = param.Content.DeJson<RegistryInfo>();
byte[] bytes = MemoryPackSerializer.Serialize(info.Registry);
for (int i = 0; i < info.Names.Length; i++)
byte[] bytes = MemoryPackSerializer.Serialize(info.Data);
for (int i = 0; i < info.Devices.Length; i++)
{
if (signCaching.Get(info.Names[i], out SignCacheInfo cache) && cache.Connected)
if (signCaching.Get(info.Devices[i], out SignCacheInfo cache) && cache.Connected)
{
await messengerSender.SendOnly(new MessageRequestWrap
{
@@ -61,13 +61,13 @@ namespace cmonitor.plugins.system
public sealed class RegistryInfo
{
public string[] Names { get; set; }
public SystemOptionUpdateInfo Registry { get; set; }
public string[] Devices { get; set; }
public SystemOptionUpdateInfo[] Data { get; set; }
}
public sealed class PasswordInfo
{
public string[] Names { get; set; }
public string[] Devices { get; set; }
public PasswordInputInfo Input { get; set; }
}
}

View File

@@ -22,7 +22,7 @@ namespace cmonitor.plugins.system.messenger
[MessengerId((ushort)SystemMessengerIds.RegistryOptions)]
public void RegistryOptions(IConnection connection)
{
SystemOptionUpdateInfo registryUpdateInfo = MemoryPackSerializer.Deserialize<SystemOptionUpdateInfo>(connection.ReceiveRequestWrap.Payload.Span);
SystemOptionUpdateInfo[] registryUpdateInfo = MemoryPackSerializer.Deserialize<SystemOptionUpdateInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
report.OptionUpdate(registryUpdateInfo);
}

View File

@@ -8,7 +8,7 @@ namespace cmonitor.plugins.system.report
public Dictionary<string, SystemOptionKeyInfo> OptionKeys();
public string OptionValues();
public void OptionUpdate(SystemOptionUpdateInfo optionUpdateInfo);
public void OptionUpdate(SystemOptionUpdateInfo[] optionUpdateInfo);
public bool Password(PasswordInputInfo command);

View File

@@ -25,7 +25,7 @@
{
return string.Empty;
}
public void OptionUpdate(SystemOptionUpdateInfo registryUpdateInfo)
public void OptionUpdate(SystemOptionUpdateInfo[] registryUpdateInfo)
{
}

View File

@@ -25,7 +25,7 @@
{
return string.Empty;
}
public void OptionUpdate(SystemOptionUpdateInfo registryUpdateInfo)
public void OptionUpdate(SystemOptionUpdateInfo[] registryUpdateInfo)
{
}

View File

@@ -45,7 +45,7 @@ namespace cmonitor.plugins.system.report
return null;
}
public void OptionUpdate(SystemOptionUpdateInfo registryUpdateInfo)
public void OptionUpdate(SystemOptionUpdateInfo[] registryUpdateInfo)
{
system.OptionUpdate(registryUpdateInfo);
}
@@ -95,7 +95,7 @@ namespace cmonitor.plugins.system.report
[MemoryPackable]
public sealed partial class SystemOptionUpdateInfo
{
public string[] Keys { get; set; }
public string Keys { get; set; }
public bool Value { get; set; }
}

View File

@@ -5,6 +5,7 @@ using common.libs.winapis;
using Microsoft.Win32;
using monitor.plugins.system.report;
using System.Collections.Concurrent;
using System.Linq;
namespace cmonitor.plugins.system.report
{
@@ -74,7 +75,7 @@ namespace cmonitor.plugins.system.report
if (restored)
{
reused |= registryOptionHelper.Reuse();
OptionUpdate(new SystemOptionUpdateInfo { Keys = new string[] { "SoftwareSASGeneration" }, Value = false });
OptionUpdate(new SystemOptionUpdateInfo[] { new SystemOptionUpdateInfo { Keys = "SoftwareSASGeneration", Value = false } });
}
await Task.Delay(5000);
}
@@ -90,11 +91,11 @@ namespace cmonitor.plugins.system.report
{
return registryOptionHelper.GetValues();
}
public void OptionUpdate(SystemOptionUpdateInfo registryUpdateInfo)
public void OptionUpdate(SystemOptionUpdateInfo[] registryUpdateInfo)
{
actions.Enqueue(() =>
{
registryOptionHelper.UpdateValue(registryUpdateInfo.Keys, registryUpdateInfo.Value);
registryOptionHelper.UpdateValue(registryUpdateInfo);
});
}
private void LoopTask()
@@ -374,7 +375,7 @@ namespace cmonitor.plugins.system.report
}
return _allow;
}
public bool UpdateValue(string[] keys, bool value)
public bool UpdateValue(SystemOptionUpdateInfo[] keys)
{
bool result = false;
if (GetSid() == false)
@@ -384,21 +385,23 @@ namespace cmonitor.plugins.system.report
if (OperatingSystem.IsWindows())
{
IEnumerable<RegistryOptionInfo> info = Infos.Where(c => keys.Contains(c.Key));
if (info.Any() == false)
foreach (SystemOptionUpdateInfo item in keys)
{
return result;
}
foreach (RegistryOptionInfo item in info)
{
foreach (RegistryOptionPathInfo pathItem in item.Paths)
RegistryOptionInfo info = Infos.FirstOrDefault(c => c.Key == item.Keys);
if (info == null)
{
continue;
}
foreach (RegistryOptionPathInfo pathItem in info.Paths)
{
string path = ReplaceRegistryPath(pathItem.Path);
if (string.IsNullOrWhiteSpace(path))
{
continue;
}
string setValue = value ? pathItem.DisallowValue : pathItem.AllowValue;
string setValue = item.Value ? pathItem.DisallowValue : pathItem.AllowValue;
try
{
object oldValue = Registry.GetValue(path, pathItem.Key, null);

View File

@@ -9,8 +9,6 @@ namespace cmonitor.plugins.wlan.messenger
public WlanClientMessenger(WlanReport wlanReport)
{
this.wlanReport = wlanReport;
Console.WriteLine(wlanReport == null);
}

View File

@@ -1,5 +1,6 @@
using cmonitor.client.report;
using cmonitor.config;
using common.libs;
namespace cmonitor.plugins.wlan.report
{
@@ -28,9 +29,11 @@ namespace cmonitor.plugins.wlan.report
{
if (wlan.Connected() == false)
{
Logger.Instance.Warning($"network offline reconnect it~");
var wafis = wlan.WlanEnums();
foreach (var wifi in wafis)
{
Logger.Instance.Warning($"network offline reconnect {wifi}~");
bool res = await wlan.WlanConnect(wifi);
if (res)
{

View File

@@ -1,5 +1,5 @@
using common.libs.winapis;
using ManagedNativeWifi;
using ManagedNativeWifi;
using System.Net.NetworkInformation;
namespace cmonitor.plugins.wlan.report
{
@@ -22,7 +22,10 @@ namespace cmonitor.plugins.wlan.report
public bool Connected()
{
return Wininet.InternetGetConnectedState(out int desc, 0);
using Ping ping = new Ping();
var replay = ping.Send("www.baidu.com", 1000);
return replay.Status == IPStatus.Success;
//return Wininet.InternetGetConnectedState(out int desc, 0);
}
}
}

View File

@@ -1,4 +1,5 @@
using cmonitor.config;
using cmonitor.server.ruleConfig;
using cmonitor.startup;
using common.libs;
using Microsoft.Extensions.DependencyInjection;
@@ -17,6 +18,11 @@ namespace cmonitor.server
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
{
serviceCollection.AddSingleton<IRuleConfig, RuleConfigWindows>();
// if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IRuleConfig, RuleConfigWindows>();
// else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IRuleConfig, RuleConfigLinux>();
// else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IRuleConfig, RuleConfigMacOS>();
serviceCollection.AddSingleton<MessengerSender>();
serviceCollection.AddSingleton<MessengerResolver>();
serviceCollection.AddSingleton<TcpServer>();

View File

@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace cmonitor.server.ruleConfig
{
public interface IRuleConfig
{
public RuleConfigInfo Data { get; }
public void AddUser(string username);
public T Get<T>(string username,string key, T defaultValue);
public void Set<T>(string username, string key, T data);
}
[Table("rule")]
public sealed class RuleConfigInfo
{
public Dictionary<string, Dictionary<string, string>> Data { get; set; } = new Dictionary<string, Dictionary<string, string>>();
}
}

View File

@@ -0,0 +1,23 @@
namespace cmonitor.server.ruleConfig
{
public sealed class RuleConfigLinux : IRuleConfig
{
public RuleConfigInfo Data => null;
public void AddUser(string username)
{
}
public T Get<T>(string username, string key, T defaultValue)
{
return defaultValue;
}
public void Set<T>(string username, string key, T data)
{
}
}
}

View File

@@ -0,0 +1,22 @@
namespace cmonitor.server.ruleConfig
{
public sealed class RuleConfigMacOS : IRuleConfig
{
public RuleConfigInfo Data => null;
public void AddUser(string username)
{
}
public T Get<T>(string username, string key, T defaultValue)
{
return defaultValue;
}
public void Set<T>(string username, string key, T data)
{
}
}
}

View File

@@ -0,0 +1,89 @@
using common.libs;
using common.libs.database;
using common.libs.extends;
namespace cmonitor.server.ruleConfig
{
//[SupportedOSPlatform("windows")]
public sealed class RuleConfigWindows : IRuleConfig
{
private readonly IConfigDataProvider<RuleConfigInfo> configDataProvider;
private readonly RuleConfigInfo RuleConfigInfo;
private Dictionary<string, Dictionary<string, object>> cache = new Dictionary<string, Dictionary<string, object>>();
public RuleConfigInfo Data => RuleConfigInfo;
public RuleConfigWindows(IConfigDataProvider<RuleConfigInfo> configDataProvider)
{
this.configDataProvider = configDataProvider;
RuleConfigInfo = configDataProvider.Load().Result ?? new RuleConfigInfo();
}
public void AddUser(string username)
{
if (RuleConfigInfo.Data.ContainsKey(username))
{
return;
}
RuleConfigInfo.Data.Add(username,new Dictionary<string, string>());
}
public T Get<T>(string username, string key, T defaultValue)
{
try
{
if (cache.TryGetValue(username, out Dictionary<string, object> dic) && dic.TryGetValue(key, out object cacheValue))
{
return (T)cacheValue;
}
if (RuleConfigInfo.Data.TryGetValue(username, out Dictionary<string, string> dicStr) && dicStr.TryGetValue(key, out string value))
{
if (string.IsNullOrWhiteSpace(value) == false)
{
T data = value.DeJson<T>();
cache[username][key] = data;
return data;
}
}
}
catch (Exception ex)
{
Logger.Instance.Error(ex);
}
return defaultValue;
}
public void Set<T>(string username, string key, T data)
{
try
{
string value = data.ToJson();
if (RuleConfigInfo.Data.TryGetValue(username, out Dictionary<string, string> dicStr) == false)
{
RuleConfigInfo.Data[username] = new Dictionary<string, string>();
}
RuleConfigInfo.Data[username][key] = value;
if (cache.TryGetValue(username, out Dictionary<string, object> dic) == false)
{
cache[username] = new Dictionary<string, object>();
}
cache[username][key] = data;
configDataProvider.Save(RuleConfigInfo).Wait();
}
catch (Exception ex)
{
Logger.Instance.Error(ex);
}
}
}
}

View File

@@ -13,4 +13,5 @@ dotnet publish ./cmonitor.snatch.win -c release -f net8.0-windows -r win-x64 -o
dotnet publish ./cmonitor.llock.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
dotnet publish ./cmonitor.message.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
dotnet publish ./cmonitor.notify.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
dotnet publish ./cmonitor.wallpaper.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
dotnet publish ./cmonitor.wallpaper.win -c release -f net8.0-windows -r win-x64 -o public/extends/ -p:PublishSingleFile=true --self-contained false
MSBuild.exe cmonitor.viewer.server.win /t:Publish /p:Configuration=Release /p:TargetFramework=net8.0-windows /p:PublishSingleFile=true /p:RuntimeIdentifier=win-x64 /p:PublishDir=../public/extends/