Compare commits

..

14 Commits

20 changed files with 743 additions and 331 deletions

View File

@ -6,7 +6,9 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="xin-launcher" level="project" /> <orderEntry type="library" name="xin-launcher" level="project" />
<orderEntry type="library" name="xin-admin" level="project" />
<orderEntry type="library" name="xin-launcher" level="project" /> <orderEntry type="library" name="xin-launcher" level="project" />
<orderEntry type="library" name="xin-admin" level="project" /> <orderEntry type="library" name="xin-admin" level="project" />
<orderEntry type="library" name="xin-launcher" level="project" />
</component> </component>
</module> </module>

View File

@ -51,4 +51,33 @@
调整授权时对应注册表处理逻辑 调整授权时对应注册表处理逻辑
2025-03-03
根据Cooperop-Mix逻辑调整对应产品加载功能并优化重启处理逻辑
2025-07-11
1. 调整授权产品查看界面(补充二维码)
2. 调整授权校验(注册表存在必要信息后仅校验运行目录即可)
3. 追加 path_key 配置,配置为空时系统启动自动创建随机码并记录
2025-07-15
1. 优化全局过滤功能,区分已授权与未授权状态(前者自动跳转登录界面,后者自动跳转授权界面)
2. 修复全局过滤功能在项目重启后无法正确处理相应拦截的异常
2025-09-28
1. 大版本更新后续代码版本为3.0
2. 注册表存储随机字符串由机械码及下发授权文件决定
2025-11-17
1. 修复部分服务器硬件不存在导致每次启动授权码均变化的异常
2. 替换TOMCAT版本
3. 补充部分日志输出,方便后续比对
2026-03-02
1. xinadmin界面新增配置文件读取/设置保存弹窗
2. 新增相关工具函数,实现配置文件读取、加密及解密对象获取

View File

@ -0,0 +1,183 @@
# LauncherCommonFunc工具函数释义
本文档用于解释新增LauncherCommonFunc工具函数的使用释义开发使用。
本文档书写事件2025-09-28 对应 xinlauncher_20250928.zip 。
## 简介
该类统一了鉴权通用的静态资源(路径、命名规范等)及通用的调用功能函数。
## 调用函数
基于外部调用,针对每一个函数进行调用释义。
注意:该内容需要跟随版本进行修改,查看文档时请注意是否为对应版本包及文档。
1. 静态资源
定义内容以表格信息展示:
| 资源名称 | 调用 | 调用方式 | 释义 |
| --------------------------- | ---- | ------------------------------ | ---------------------- |
| BaseBoradSN | Y | LauncherCommonFunc.BaseBoradSN | 主板序列号 |
| CpuSN | Y | LauncherCommonFunc.CpuSN | CPU序列号 |
| DiskSN | Y | LauncherCommonFunc.DiskSN | 硬盘S/N |
| UD | Y | LauncherCommonFunc.UD | 授权唯一UUID |
| configFile | N | 不可外部调用 | 系统配置文件 |
| cipherFile | Y | LauncherCommonFunc.cipherFile | 机械码文件 |
| licenseFile | Y | LauncherCommonFunc.licenseFile | 系统授权文件 |
| cipherContent | N | 不可外部调用 | 机械码信息(加密字符串) |
| SYSTEM_CUSTOMER_AUTHOR_CODE | N | 不可外部调用 | 系统授权前缀信息 |
2. 静态函数
依次对函数进行释义
1. 机械码初始化函数
- 函数名init
- 调用:不可外部调用
- 调用方式LauncherCommonFunc.init();
- 基础逻辑初始化缓存项目所在机械对应主板序列号、CPU序列号及硬盘S/N编码。
- 入参:无
- 出参:无
2. 获取本机机械码秘钥
- 函数名generateKey
- 调用:不可外部调用
- 调用方式LauncherCommonFunc.generateKey();
- 基础逻辑:获取系统授权文件秘钥信息。
- 入参:无
- 出参:无
3. 字符串处理编码BOM异常
- 函数名deleteUTF8Bom
- 调用:不可外部调用
- 调用方式LauncherCommonFunc.deleteUTF8Bom(fileStr);
- 基础逻辑将传入字符串去除编码过程中出现的BOM异常。
- 入参:
| 字段 | 类型 | 释义 |
| ------- | ------ | ---------- |
| fileStr | String | 文件字符串 |
- 出参:去除异常后的字符串
4. 获取缓存授权码内容
- 函数名getCode
- 调用:可外部调用
- 调用方式LauncherCommonFunc.getCode();
- 基础逻辑:获取缓存授权码内容。
- 入参:无
- 出参:无
5. 设置机械码缓存授权码信息
- 函数名setCode
- 调用:不可外部调用
- 调用方式LauncherCommonFunc.setCode(content);
- 基础逻辑:设置机械码缓存授权码信息。
- 入参:
| 字段 | 类型 | 释义 |
| ------- | ------ | ------------------------ |
| content | String | 系统机械码加密字符串信息 |
- 出参:无
6. 获取授权随机加密地址
- 函数名getPathKey
- 调用:不可外部调用
- 调用方式LauncherCommonFunc.getPathKey(text);
- 基础逻辑:根据传入随机码(生成机械码时会自动创建),获取注册表定义地址信息。
- 入参:
| 字段 | 类型 | 释义 |
| ---- | ------ | ---------------- |
| text | String | 系统机械码随机码 |
- 出参:返回加密结果字符串
7. 生成系统机械码文件
- 函数名generateCipher
- 调用:可外部调用
- 调用方式LauncherCommonFunc.generateCipher();
- 基础逻辑:初始化生成机械码文件(存储对应服务器的硬件加密信息)。
- 入参:无
- 出参:无
8. 获取本机硬件加密信息
- 函数名generateCipherContent
- 调用:私有函数,不可外部调用
- 调用方式:无
- 基础逻辑:生成系统机械码必要信息对象,并转换为字符串信息。
- 入参:无
- 出参返回存储信息JSON字符串

View File

@ -0,0 +1,87 @@
# LocalLauncherValid工具函数释义
本文档用于解释新增LocalLauncherValid工具函数的使用释义开发使用。
本文档书写事件2025-09-28 对应 xinlauncher_20250928.zip 。
## 简介
该类统一了内部鉴权相关操作函数。
## 调用函数
基于外部调用,针对每一个函数进行调用释义。
注意:该内容需要跟随版本进行修改,查看文档时请注意是否为对应版本包及文档。
1. 静态资源
无。
2. 静态函数
依次对函数进行释义:
1. 读取授权码文件内容
- 函数名loadCipher
- 调用:可外部调用
- 调用方式LocalLauncherValid.loadCipher();
- 基础逻辑:读取授权文件对应字符串。
- 入参:无
- 出参:返回授权文件字符串信息。
2. 验证授权文件
- 函数名valid
- 调用:私有函数,不可外部调用
- 调用方式:无;
- 基础逻辑:校验系统授权文件,为空或鉴权失败时,清除已有文件并重新生成机械码信息。
- 入参:无
- 出参:无
3. 验证系统信息
- 函数名validCipher
- 调用:私有函数,不可外部调用
- 调用方式:无
- 基础逻辑:获取存储在机械码文件中的加密字符串信息,比对机械实际硬件信息,对照失败时,重新生成并删除已有授权文件。
- 入参:无
- 出参:无
4. 解码校验系统信息
- 函数名validCipher
- 调用:私有函数,不可外部调用
- 调用方式:无
- 基础逻辑:解密传入的机械码加密字符串,比对机械实际硬件信息,对照失败时,重新生成并删除已有授权文件。
- 入参:无
- 出参:无

View File

@ -0,0 +1,65 @@
# XinAdminLauncherValid工具函数释义
本文档用于解释新增XinAdminLauncherValid工具函数的使用释义开发使用。
本文档书写事件2025-09-28 对应 xinlauncher_20250928.zip 。
## 简介
该类统一了外部鉴权相关操作函数。
## 调用函数
基于外部调用,针对每一个函数进行调用释义。
注意:该内容需要跟随版本进行修改,查看文档时请注意是否为对应版本包及文档。
1. 静态资源
无。
2. 静态函数
依次对函数进行释义:
1. 读取授权码文件内容
- 函数名validCipher
- 调用:
- 调用方式XinAdminLauncherValid.validCipher(licenseContent,uploadFile);
- 基础逻辑:解码授权文件信息,校验系统硬件信息。
- 入参:
| 字段 | 类型 | 释义 |
| -------------- | ------- | -------------- |
| licenseContent | String | 授权文件字符串 |
| uploadFile | boolean | 是否为上传文件 |
- 出参:返回校验结果。
2. 验证授权文件
- 函数名validMachineInfo
- 调用:可外部调用
- 调用方式XinAdminLauncherValid.validMachineInfo(licenseContent);
- 基础逻辑:解码授权文件信息,比对机械码存储信息。
- 入参:
| 字段 | 类型 | 释义 |
| -------------- | ------ | -------------- |
| licenseContent | String | 授权文件字符串 |
- 出参:无

Binary file not shown.

View File

@ -34,7 +34,6 @@
<div class="company"> <div class="company">
<div class="company-det"> <div class="company-det">
<div class="company-lint"> <div class="company-lint">
<div class="company-name"> <div class="company-name">
<div class="company-logo"> <div class="company-logo">
@ -46,16 +45,27 @@
<div style="margin: 10px;"> <div style="margin: 10px;">
<div class="address">地址:{{companyAddress}}</div> <div class="address">地址:{{companyAddress}}</div>
<div class="des">简介:{{companyIntroduce}}</div> <div class="des">简介:{{companyIntroduce}}</div>
<div class="des">授权码:<span style="color: green">已生成</span> <span><el-link <div class="des">授权码:
type="primary" :underline="false" <span style="color: green">已生成</span>
style=" font-size: 12px;margin-left: 8px;"
@click="toSeeCode">查看</el-link></span></div>
<div class="des">授权文件:<span style="color: green">正常</span>
<span> <span>
<el-link type="primary" :underline="false" <el-link type="primary" :underline="false"
style=" font-size: 12px;margin-left: 8px;" style=" font-size: 12px;margin-left: 8px;"
@click="dialogTableVisible = true">更换授权文件</el-link> @click="toSeeCode">查看</el-link>
</span> </span>
</div>
<div class="des">授权文件:
<span style="color: green">正常</span>
<span>
<el-link type="primary" :underline="false" style="font-size: 12px;margin-left: 8px;"
@click="openUploadLicense">
更换授权文件
</el-link>
</span>
</div>
<div class="des">配置文件
<el-link type="primary" :underline="false"
style="font-size: 12px;margin-left: 8px;" @click="openConfigSet">设置
</el-link>
</div> </div>
</div> </div>
</div> </div>
@ -79,8 +89,8 @@
<div class="app-des">版本:{{item.version}}</div> <div class="app-des">版本:{{item.version}}</div>
<div class="app-license">{{item.grade == 'custom' ? '定制授权' : item.gradeName}}</div> <div class="app-license">{{item.grade == 'custom' ? '定制授权' : item.gradeName}}</div>
<div class="app-time" style="color: green" <div class="app-time" style="color: green"
v-if="new Date().getTime() < new Date(item.expiryTime).getTime()"> {{item.expiryTime | v-if="new Date().getTime() < new Date(item.expiryTime).getTime()">
dateFilter('YYYY-MM-DD')}}到期 {{item.expiryTime | dateFilter('YYYY-MM-DD')}}到期
</div> </div>
<div v-else style="color: red">已过期</div> <div v-else style="color: red">已过期</div>
</div> </div>
@ -117,19 +127,23 @@
<el-dialog title="授权码" :visible.sync="dialogCodeVisible" :close-on-click-modal="false"> <el-dialog title="授权码" :visible.sync="dialogCodeVisible" :close-on-click-modal="false">
<div class="demo-input-suffix"> <div class="demo-input-suffix">
<el-button style="float: right; margin-top: -25px" icon="el-icon-document-copy" @click="copy()" type="text"> <div style="display: flex;margin-top: 10px;">
复制授权码 <div style="display: flex;width: 200px;">
</el-button> <div id="qrcode" style="width:200px;height: 200px;"></div>
</div>
<div style="display: flex;width: 100%;">
<div id="qrcode" style="width:200px;height: 200px;margin: 10px"></div>
<el-input type="textarea" ref="copy" autosize="true" v-model="single.code" resize="none" <el-input type="textarea" ref="copy" autosize="true" v-model="single.code" resize="none"
readonly="true" :autosize="{ minRows: 9, maxRows: 10}" readonly="true" :autosize="{ minRows: 9, maxRows: 10}"
style="margin: 10px;flex: 1 1 0%;"> style="flex:1;margin-left: 10px"></el-input>
</el-input>
</div> </div>
</div> </div>
<div style="padding:10px;display: block">
<el-button style="float: right; " icon="el-icon-document-copy" @click="copy()"
type="text">
复制授权码
</el-button>
</div>
</el-dialog> </el-dialog>
<el-dialog title="授权文件修改" :visible.sync="dialogTableVisible" :close-on-click-modal="false"> <el-dialog title="授权文件修改" :visible.sync="dialogTableVisible" :close-on-click-modal="false">
@ -157,281 +171,346 @@
</el-table> </el-table>
</div> </div>
</el-dialog> </el-dialog>
<el-dialog title="系统配置文件设置" :visible.sync="configSetVis" :close-on-click-modal="false">
<el-row style="margin-top: -20px;margin-bottom: 10px;" :gutter="10">
<el-col :span="8">
<el-input v-model="configSetPath" placeholder="手动输入文件路径,例如C:\test.txt"></el-input>
</el-col>
<el-col :span="16">
<el-button @click="readFileInfo" :loading="readBtnLoad">读取配置</el-button>
<el-button @click="keepFileInfo" :disabled="!apiReadFile" :loading="keepBtnLoad">保存配置</el-button>
</el-col>
</el-row>
<el-input type="textarea" :disabled="!apiReadFile" :autosize="{ minRows: 20, maxRows: 20}"
v-model="configSetValue" v-loading="readBtnLoad"></el-input>
</el-dialog>
</div> </div>
<script> <script>
function generateQRCode(rendermethod, picwidth, picheight, url) { function generateQRCode(rendermethod, picwidth, picheight, url) {
$("#qrcode").qrcode({ $("#qrcode").qrcode({
render: rendermethod, // 渲染方式有table方式IE兼容和canvas方式 render: rendermethod, // 渲染方式有table方式IE兼容和canvas方式
width: picwidth, //宽度 width: picwidth, //宽度
height:picheight, //高度 height: picheight, //高度
text: utf16to8(url), //内容 text: utf16to8(url), //内容
typeNumber:-1,//计算模式 typeNumber: -1,//计算模式
correctLevel:2,//二维码纠错级别 correctLevel: 2,//二维码纠错级别
background:"#ffffff",//背景颜色 background: "#ffffff",//背景颜色
foreground:"#000000" //二维码颜色 foreground: "#000000" //二维码颜色
});
}
//中文编码格式转换
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
Vue.filter("dateFilter", function (date, formatPattern) {
return moment(date).format(formatPattern || "YYYY-MM-DD HH:mm:ss");
});
const home = new Vue({
el: '#app',
data() {
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.from.checkPass !== '') {
this.$refs.user.validateField('checkPass');
}
callback();
}
};
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.from.editPass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
single: [],
dialogCodeVisible: false,
dialogTableVisible: false,
rightDialogVisible: false,
rightDialogTitle: '',
tableData: [],
companyName: '',
companyAddress: '',
companyIntroduce: '',
showPassChange: false,
from: {
pass: '',
editPass: '',
checkPass: ''
},
rules: {
pass: [
{required: true, message: '请输入原密码', trigger: 'blur'},
],
editPass: [
{required: true, message: '请输入要修改的密码', trigger: 'blur'},
{
pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,16}$/g,
message: '密码必须包含大小写字母及数字允许特殊字符长度6-16'
},
{validator: validatePass, trigger: 'blur'}
],
checkPass: [
{required: true, message: '请再次输入修改的密码', trigger: 'blur'},
{validator: validatePass2, trigger: 'blur'}
]
},
generalQrCode: false
}
},
created: function () {
this.checkLogin();
this.singlecode();
},
//绑定方法
methods: {
singlecode() {
const that = this;
axios.get('/xinadmin/single', {}).then(function (res) {
if (res.data) {
if (res.data.license) {
that.single = res.data;
that.companyName = res.data.company.name;
that.companyAddress = res.data.company.address;
that.companyIntroduce = res.data.company.introduce;
} else {
location.href = "index.jsp"
}
}
}).catch(function (error) {
console.log(error)
})
},
checkLogin() {
const token = sessionStorage.getItem("token");
if (token == null) {
location.href = "login.jsp"
} else {
const str = new Date().getTime()
if ((+token + (2 * 60 * 60 * 1000) < str)) {
location.href = "login.jsp"
}
}
},
copy() {
this.$refs.copy.select()
document.execCommand('Copy')
this.$message.success('已复制到剪贴板')
},
uploadfile() {
this.$refs.upload.submit()
},
Success(response) {
if (response.state === "success") {
this.dialogTableVisible = false;
this.$notify({
title: '成功',
duration: 2000,
message: '校验通过',
type: 'success'
});
const that = this;
this.$confirm('授权文件已更新,是否立即重启相关应用?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.get('/xinadmin/adminstarter', {}).then(function () {
that.$notify({
title: '重启中',
duration: 2000,
message: '正在重启相关应用,请稍侯....',
type: 'info'
});
setTimeout(() => {
location.reload();
}, 2000);
}).catch(function (error) {
console.log(error)
})
}).catch(() => {
that.$notify({
title: '警告',
duration: 2000,
message: '应用尚未重启,授权尚未生效,请稍后手动重启',
type: 'warning'
});
});
} else {
this.$notify.error({
title: '上传失败',
message: response.error
});
}
},
showDetail(item) {
this.rightDialogVisible = true;
this.rightDialogTitle = item.name + "授权参数详情";
let ary = [];
let data = item.params;
if (data != null) {
for (let i in data) {
let desc = data[i].name;
let value = data[i].value;
let valueType = data[i].valueType;
if (valueType === "number") {
if (value === -1)
value = "未限制数量";
else
value = "当前允许最大数量为: " + value + " , 请勿超出限制";
} else if (valueType === "boolean") {
if (value === data[i].falseDefault)
value = "未拥有此功能(或权限)";
else if (value === data[i].trueDefault)
value = "已拥有此功能(或权限)";
}
let param = {
code: i,
description: desc,
value: value,
};
ary.push(param);
}
}
this.tableData = ary;
},
closeDetail() {
this.rightDialogVisible = false;
this.rightDialogTitle = '';
this.tableData = [];
},
openShow() {
this.showPassChange = true;
},
closeShow() {
this.form = {
pass: '',
editPass: '',
checkPass: ''
}
this.showPassChange = false
},
edit(user) {
this.$refs[user].validate((valid) => {
if (valid) {
if (this.from.editPass === this.from.checkPass) {
const that = this;
axios.post('/xinadmin/edit', this.from, {
headers: {
'token': sessionStorage.getItem("token")
}
}).then(function (res) {
if (res.data.state === "success") {
that.$message.success('修改成功');
setTimeout(() => { //设置延迟执行
location.href = "login.jsp";
}, 2000);
} else {
that.$message.error(res.data.mes??"密码错误");
}
}).catch(function (error) {
console.log(error)
})
} else {
this.$message.error("两次密码不一致")
}
}
}); });
},
toSeeCode() {
this.dialogCodeVisible = true
if ( !this.generalQrCode){
setTimeout(() => {
generateQRCode("table",200, 200, this.single.code);
this.generalQrCode = true;
} , 100)
}
}
} }
})
//中文编码格式转换
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
Vue.filter("dateFilter", function (date, formatPattern) {
return moment(date).format(formatPattern || "YYYY-MM-DD HH:mm:ss");
});
const home = new Vue({
el: '#app',
data() {
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.from.checkPass !== '') {
this.$refs.user.validateField('checkPass');
}
callback();
}
};
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.from.editPass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
single: [],
dialogCodeVisible: false,
dialogTableVisible: false,
rightDialogVisible: false,
rightDialogTitle: '',
tableData: [],
companyName: '',
companyAddress: '',
companyIntroduce: '',
showPassChange: false,
from: {
pass: '',
editPass: '',
checkPass: ''
},
rules: {
pass: [
{required: true, message: '请输入原密码', trigger: 'blur'},
],
editPass: [
{required: true, message: '请输入要修改的密码', trigger: 'blur'},
{
pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,16}$/g,
message: '密码必须包含大小写字母及数字允许特殊字符长度6-16'
},
{validator: validatePass, trigger: 'blur'}
],
checkPass: [
{required: true, message: '请再次输入修改的密码', trigger: 'blur'},
{validator: validatePass2, trigger: 'blur'}
]
},
generalQrCode: false,
configSetVis: false,
configSetPath: 'C:\\Users\\tiany\\Desktop\\tets\\datasource.xml',
apiReadFile: false,
configSetValue: '',
readBtnLoad: false,
keepBtnLoad: false,
}
},
created: function () {
this.checkLogin();
this.singlecode();
},
//绑定方法
methods: {
singlecode() {
const that = this;
axios.get('/xinadmin/single', {}).then(function (res) {
if (res.data) {
if (res.data.license) {
that.single = res.data;
that.companyName = res.data.company.name;
that.companyAddress = res.data.company.address;
that.companyIntroduce = res.data.company.introduce;
} else {
location.href = "index.jsp"
}
}
}).catch(function (error) {
console.log(error)
})
},
checkLogin() {
const token = sessionStorage.getItem("token");
if (token == null) {
location.href = "login.jsp"
} else {
const str = new Date().getTime()
if ((+token + (2 * 60 * 60 * 1000) < str)) {
location.href = "login.jsp"
}
}
},
copy() {
this.$refs.copy.select()
document.execCommand('Copy')
this.$message.success('已复制到剪贴板')
},
uploadfile() {
this.$refs.upload.submit()
},
Success(response) {
if (response.state === "success") {
this.dialogTableVisible = false;
this.$notify({
title: '成功',
duration: 2000,
message: '校验通过',
type: 'success'
});
const that = this;
this.$confirm('授权文件已更新,是否立即重启相关应用?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.get('/xinadmin/adminstarter', {}).then(function () {
that.$notify({
title: '重启中',
duration: 2000,
message: '正在重启相关应用,请稍侯....',
type: 'info'
});
setTimeout(() => {
location.reload();
}, 2000);
}).catch(function (error) {
console.log(error)
})
}).catch(() => {
that.$notify({
title: '警告',
duration: 2000,
message: '应用尚未重启,授权尚未生效,请稍后手动重启',
type: 'warning'
});
});
} else {
this.$notify.error({
title: '上传失败',
message: response.error
});
}
},
showDetail(item) {
this.rightDialogVisible = true;
this.rightDialogTitle = item.name + "授权参数详情";
let ary = [];
let data = item.params;
if (data != null) {
for (let i in data) {
let desc = data[i].name;
let value = data[i].value;
let valueType = data[i].valueType;
if (valueType === "number") {
if (value === -1)
value = "未限制数量";
else
value = "当前允许最大数量为: " + value + " , 请勿超出限制";
} else if (valueType === "boolean") {
if (value === data[i].falseDefault)
value = "未拥有此功能(或权限)";
else if (value === data[i].trueDefault)
value = "已拥有此功能(或权限)";
}
let param = {
code: i,
description: desc,
value: value,
};
ary.push(param);
}
}
this.tableData = ary;
},
closeDetail() {
this.rightDialogVisible = false;
this.rightDialogTitle = '';
this.tableData = [];
},
openShow() {
this.showPassChange = true;
},
closeShow() {
this.form = {
pass: '',
editPass: '',
checkPass: ''
}
this.showPassChange = false
},
edit(user) {
this.$refs[user].validate((valid) => {
if (valid) {
if (this.from.editPass === this.from.checkPass) {
const that = this;
axios.post('/xinadmin/edit', this.from, {
headers: {
'token': sessionStorage.getItem("token")
}
}).then(function (res) {
if (res.data.state === "success") {
that.$message.success('修改成功');
setTimeout(() => { //设置延迟执行
location.href = "login.jsp";
}, 2000);
} else {
that.$message.error(res.data.mes ?? "密码错误");
}
}).catch(function (error) {
console.log(error)
})
} else {
this.$message.error("两次密码不一致")
}
}
});
},
toSeeCode() {
this.dialogCodeVisible = true
if (!this.generalQrCode) {
setTimeout(() => {
generateQRCode("table", 200, 200, this.single.code);
this.generalQrCode = true;
}, 100)
}
},
openUploadLicense() {
this.dialogTableVisible = true;
},
openConfigSet() {
const that = this;
that.configSetVis = true;
},
closeConfigSet() {
const that = this;
that.configSetVis = false;
},
readFileInfo() {
const that = this;
that.configSetValue = '';
that.apiReadFile = false;
const params = {filePath: that.configSetPath}
that.readBtnLoad = true;
axios.post('/xinadmin/readConfigFile', params).then(function (res) {
if (res.status === 200) {
that.configSetValue = res.data.data;
that.apiReadFile = true;
} else {
that.$message.error(res.data.mes);
}
}).finally(() => {
that.readBtnLoad = false;
})
},
keepFileInfo() {
const that = this;
const params = {
filePath: that.configSetPath,
fileContent: that.configSetValue
}
that.keepBtnLoad = true;
axios.post('/xinadmin/keepConfigSetFile', params).then(function (res) {
if (res.status === 200) {
that.$message.success('保存成功!');
that.closeConfigSet();
} else {
that.$message.error(res.data.mes);
}
}).finally(() => {
that.keepBtnLoad = false;
})
},
}
})
</script> </script>
</body> </body>
</html> </html>

View File

@ -155,7 +155,7 @@ body {
} }
.app-name { .app-name {
font-family: "微软雅黑", serif; font-family: "微软雅黑";
font-size: 12pt; font-size: 12pt;
color: #666666; color: #666666;
text-decoration: none; text-decoration: none;
@ -164,14 +164,14 @@ body {
} }
.app-des { .app-des {
font-family: "微软雅黑", serif; font-family: "微软雅黑";
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
color: #999999; color: #999999;
} }
.app-license { .app-license {
font-family: "微软雅黑", serif; font-family: "微软雅黑";
font-size: 14px; font-size: 14px;
line-height: 28px; line-height: 28px;
color: #084aaf; color: #084aaf;
@ -216,7 +216,7 @@ body {
} }
.main { .main {
margin: 10px 0 auto; margin: 10px 0px auto;
padding: 10px; padding: 10px;
} }

View File

@ -1,16 +1,16 @@
#save success #save success
#Thu Dec 17 16:49:58 CST 2020 #Thu Dec 17 16:49:58 CST 2020
login.user=admin login.user=admin
path_key=
maxthreads=200 maxthreads=200
port=8080 port=8080
charset=UTF-8 charset=UTF-8
connectiontimeout=60000 connectiontimeout=60000
login.edit=0 login.edit=1
login.pass=aeb6a04dfe285d98298f5666f02d2503 login.pass=aeb6a04dfe285d98298f5666f02d2503
is_dev=1 is_dev=1
maxconnections=10000 maxconnections=10000
product_version=2.0 product_version=2026.2.6
# 产品分组标识 为空时不进行校验 存在值时将进行产品分组数据信息校验 不一致时鉴权不通过
product_group_code= product_group_code=
# 该配置为 1 时 标识不加载对应鉴权数据模块 为空或其他值时进行校验 # 该配置为 1 时 标识不加载对应鉴权数据模块 为空或其他值时进行校验
is_client= is_client=

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +0,0 @@
@echo off
setlocal EnableDelayedExpansion
@rem set "LinkName=C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\XinLauncher.lnk"
mshta VBScript:Execute("Set Shell=CreateObject(""WScript.Shell""):Set Link=Shell.CreateShortcut(Shell.SpecialFolders(""Startup"") & ""\XinLauncher.lnk""):Link.TargetPath=""%~dp0\run.bat"":Link.WorkingDirectory=""%~dp0\"":Link.Save:close")
pause
exit

View File

@ -1,27 +0,0 @@
@echo off
title Xin-launcher启动器请勿关闭
SETLOCAL
set "CURRENT_DIR=%cd%"
set "CATALINA_HOME=%CURRENT_DIR%"
set MAINPATH=%cd%\lib\xin-launcher.jar
set JAVA_HOME="C:\project\test_environment\jdk1.8.0_191"
echo CURRENT_DIR=%CURRENT_DIR%
echo JAVA_HOME=%JAVA_HOME%
echo MAINPATH=%MAINPATH%
@rem 设置Java虚拟机参数
set JAVA_VM=-hotspot
@rem 设置Java虚拟机所使用的内存
set MEM_ARGS=-Xms128m -Xmx128m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -XX:MaxDirectMemorySize=128m -Xss1024K
@rem start /b
taskkill /f /t /im javaw.exe
CHCP 65001
@rem 如果此行命令运行失败 使用下方命令
start /b %JAVA_HOME%\bin\javaw %MEM_ARGS% -Dfile.encoding=UTF-8 -jar %MAINPATH%
@rem start /b %JAVA_HOME%\bin\javaw %MEM_ARGS% %MAINPATH%
:end
ENDLOCAL