代码生成器问题修复和优化
商城增加海报、积分商城、电子面单、小票打印功能
This commit is contained in:
wangchen147 2024-11-30 12:05:34 +08:00
parent d529ebae2b
commit f8e031ab09
1132 changed files with 10301 additions and 2935 deletions

View File

@ -2,5 +2,6 @@
export {}
declare global {
const ElMessage: typeof import('element-plus/es')['ElMessage']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const ElNotification: typeof import('element-plus/es')['ElNotification']
}

View File

@ -13,7 +13,7 @@ export function getUpgradeContent(addon: string = '') {
*
*/
export function getUpgradeTask() {
return request.get('upgrade/task')
return request.get('upgrade/task', { showErrorMessage: false })
}
/**
@ -28,7 +28,7 @@ export function upgradeAddon(addon: string = '') {
*
*/
export function executeUpgrade() {
return request.post('upgrade/execute', {})
return request.post('upgrade/execute', {}, { showErrorMessage: false })
}
/**

View File

@ -22,7 +22,7 @@
</div>
</el-scrollbar>
</div>
<div class="flex justify-end" v-if="upgradeContent.version_list.length">
<div class="flex justify-end" v-if="upgradeContent && upgradeContent.version_list.length">
<el-button type="primary" @click="handleUpgrade" :loading="uploading">{{ t('upgrade.upgradeButton') }}</el-button>
</div>
</div>
@ -132,8 +132,10 @@ const uploading = ref(false)
const terminalRef = ref(null)
const emits = defineEmits(['complete', 'cloudbuild'])
const upgradeTipsShowDialog = ref<boolean>(false)
const isShowRestartTips = ref(false)
let upgradeLog = []
let errorLog = []
/**
* 查询升级任务
*/
@ -158,10 +160,12 @@ const getUpgradeTaskFn = () => {
})
//
if (data.error) {
upgradeTask.value = data
ElMessage({ message: '升级失败', type: 'error' })
terminalRef.value.pushMessage({ content: data.error, class: 'error' })
return
data.error.forEach(item => {
if (!errorLog.includes(item)) {
terminalRef.value.pushMessage({ content: item, class: 'error' })
errorLog.push(item)
}
})
}
//
if (data.step == 'upgradeComplete') {
@ -171,16 +175,40 @@ const getUpgradeTaskFn = () => {
clearUpgradeTask()
return
}
//
if (data.step == 'rollbackComplete') {
return
}
upgradeTask.value = data
if (data.status && data.status == 'restarting') {
if (!isShowRestartTips.value && data.env_type == 'dev') {
showRestartTips()
isShowRestartTips.value = true
}
setTimeout(() => {
getUpgradeTaskFn()
}, 5000)
return;
}
executeUpgradeFn()
}).catch()
}).catch(() => {
setTimeout(() => {
getUpgradeTaskFn()
}, 5000)
})
}
getUpgradeTaskFn()
const executeUpgradeFn = () => {
executeUpgrade().then(() => {
getUpgradeTaskFn()
}).catch()
}).catch(() => {
if (upgradeTask.value) {
setTimeout(() => {
getUpgradeTaskFn()
}, 5000)
}
})
}
let notificationEl : any = null
@ -200,6 +228,12 @@ const showElNotification = () => {
})
}
const showRestartTips = () => {
ElMessageBox.alert('更新内容已经覆盖请先手动重启服务,在这期间请不要进行其他操作,在服务重启后耐心等待后续操作执行完毕。', {
confirmButtonText: '我已知晓',
})
}
const elNotificationClick = () => {
showDialog.value = true
active.value = 'upgrade'
@ -316,7 +350,9 @@ const clearUpgradeTaskFn = () => {
uploading.value = false
upgradeTask.value = null
upgradeLog = []
errorLog = []
flashInterval && clearInterval(flashInterval)
isShowRestartTips.value = false
clearUpgradeTask().then(() => {}).catch()
}

View File

@ -19,5 +19,6 @@
"dataValuePlaceholder":"请输入数据值",
"sortPlaceholder":"数值越大越排前",
"momePlaceholder":"请输入备注",
"createTime":"创建时间"
}
"createTime":"创建时间",
"keyFormatTips": "关键字只允许输入字母和下划线"
}

View File

@ -1,35 +1,26 @@
{
"printerId": "",
"printerIdPlaceholder": "请输入",
"siteId": "站点id",
"siteIdPlaceholder": "请输入站点id",
"brand": "设备品牌易联云365飞鹅",
"brandPlaceholder": "请输入设备品牌易联云365飞鹅",
"printerSet": "打印机设置",
"printerName": "打印机名称",
"printerNamePlaceholder": "请输入打印机名称",
"brand": "设备品牌",
"brandPlaceholder": "请选择设备品牌",
"printerCode": "打印机编号",
"printerCodePlaceholder": "请输入打印机编号",
"printerCodeTips": "易联云打印机背面的终端号",
"printerKey": "打印机秘钥",
"printerKeyPlaceholder": "请输入打印机秘钥",
"printerKeyTips": "易联云打印机背面的密钥",
"openId": "开发者id",
"openIdPlaceholder": "请输入开发者id",
"openIdTips": "应用ID易联云-开发者中心后台应用中心里获取)",
"apikey": "开发者密钥",
"apikeyPlaceholder": "请输入开发者密钥",
"printNum": "打印张数",
"printNumPlaceholder": "请输入打印张数",
"value": "打印模板数据json格式",
"valuePlaceholder": "请输入打印模板数据json格式",
"apikeyTips": "应用密钥(易联云-开发者中心后台应用中心里获取)",
"printWidth": "纸张宽度",
"printWidthPlaceholder": "请输入纸张宽度",
"status": "状态0关闭1开启",
"statusPlaceholder": "请输入状态0关闭1开启",
"createTime": "创建时间",
"createTimePlaceholder": "请输入创建时间",
"updateTime": "修改时间",
"updateTimePlaceholder": "请输入修改时间",
"addPrinter": "添加小票打印机",
"updatePrinter": "编辑小票打印机",
"printerDeleteTips": "确定要删除该数据吗?",
"startDate": "请选择开始时间",
"endDate": "请选择结束时间"
"status": "状态",
"printTrigger": "打印时机",
"usePrintTemplate": "选择模板",
"printNum": "打印联数",
"printTypeEmpty": "缺少打印模板类型"
}

View File

@ -1,35 +1,19 @@
{
"printerId": "",
"printerIdPlaceholder": "请输入",
"siteId": "站点id",
"siteIdPlaceholder": "请输入站点id",
"brand": "设备品牌易联云365飞鹅",
"brandPlaceholder": "请输入设备品牌易联云365飞鹅",
"tabPrinterManager": "打印机管理",
"tabPrinterTemplate": "打印模板",
"printerName": "打印机名称",
"printerNamePlaceholder": "请输入打印机名称",
"printerCode": "打印机编号",
"printerCodePlaceholder": "请输入打印机编号",
"printerKey": "打印机秘钥",
"printerKeyPlaceholder": "请输入打印机秘钥",
"openId": "开发者id",
"openIdPlaceholder": "请输入开发者id",
"apikey": "开发者密钥",
"apikeyPlaceholder": "请输入开发者密钥",
"printNum": "打印张数",
"printNumPlaceholder": "请输入打印张数",
"value": "打印模板数据json格式",
"valuePlaceholder": "请输入打印模板数据json格式",
"brand": "设备品牌",
"printWidth": "纸张宽度",
"printWidthPlaceholder": "请输入纸张宽度",
"status": "状态0关闭1开启",
"statusPlaceholder": "请输入状态0关闭1开启",
"status": "状态",
"statusOn": "启用",
"statusOff": "禁用",
"createTime": "创建时间",
"createTimePlaceholder": "请输入创建时间",
"updateTime": "修改时间",
"updateTimePlaceholder": "请输入修改时间",
"addPrinter": "添加小票打印机",
"updatePrinter": "编辑小票打印机",
"addPrinter": "添加打印机",
"updatePrinter": "编辑打印机",
"printerDeleteTips": "确定要删除该数据吗?",
"startDate": "请选择开始时间",
"endDate": "请选择结束时间"
"testPrint": "测试打印",
"testPrintTips": "确定测试打印吗",
"refreshToken": "授权",
"refreshTokenTips": "若易联云打印机在 [测试打印] 时提示 access_token过期或错误请重新授权是否重新授权"
}

View File

@ -1,21 +1,11 @@
{
"templateId":"",
"templateIdPlaceholder":"请输入",
"siteId":"站点id",
"siteIdPlaceholder":"请输入站点id",
"templateType":"模板类型",
"templateTypePlaceholder":"请输入模板类型",
"templateName":"模板名称",
"templateNamePlaceholder":"请输入模板名称",
"value":"模板数据json格式",
"valuePlaceholder":"请输入模板数据json格式",
"createTime":"创建时间",
"createTimePlaceholder":"请输入创建时间",
"updateTime":"修改时间",
"updateTimePlaceholder":"请输入修改时间",
"addPrinterTemplate":"添加小票打印模板",
"updatePrinterTemplate":"编辑小票打印模板",
"printerTemplateDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
"templateInfoLabel": "模板信息",
"templateName": "模板名称",
"templateNamePlaceholder": "请输入模板名称",
"templateType": "模板类型",
"printTypeEmpty": "缺少打印模板类型",
"templateTypePlaceholder": "请选择模板类型",
"templateEditLabel": "模板编辑",
"preview": "预览图",
"printTemplateEmpty": "打印模板不存在"
}

View File

@ -1,21 +1,11 @@
{
"templateId":"",
"templateIdPlaceholder":"请输入",
"siteId":"站点id",
"siteIdPlaceholder":"请输入站点id",
"templateType":"模板类型",
"templateTypePlaceholder":"请输入模板类型",
"templateName":"模板名称",
"templateNamePlaceholder":"请输入模板名称",
"value":"模板数据json格式",
"valuePlaceholder":"请输入模板数据json格式",
"createTime":"创建时间",
"createTimePlaceholder":"请输入创建时间",
"updateTime":"修改时间",
"updateTimePlaceholder":"请输入修改时间",
"addPrinterTemplate":"添加小票打印模板",
"updatePrinterTemplate":"编辑小票打印模板",
"printerTemplateDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
"tabPrinterManager": "打印机管理",
"tabPrinterTemplate": "打印模板",
"templateName": "模板名称",
"templateNamePlaceholder": "请输入模板名称",
"templateType": "模板类型",
"templateTypePlaceholder": "请选择模板类型",
"createTime": "创建时间",
"addPrinterTemplate": "添加小票打印模板",
"printerTemplateDeleteTips": "确定要删除该数据吗?"
}

View File

@ -6,9 +6,10 @@
</el-form-item>
<el-form-item :label="t('key')" prop="key">
<el-input v-model.trim="formData.key" clearable maxlength="40" show-word-limit :placeholder="t('keyPlaceholder')" class="input-width" />
<p class="form-tip">{{ t('keyFormatTips') }}</p>
</el-form-item>
<el-form-item :label="t('memo')">
<el-input v-model="formData.memo" type="textarea" clearable :placeholder="t('memoPlaceholder')" class="input-width" />
<el-input v-model.trim="formData.memo" type="textarea" clearable :placeholder="t('memoPlaceholder')" class="input-width" />
</el-form-item>
</el-form>
@ -50,7 +51,17 @@ const formRules = computed(() => {
{ required: true, message: t('namePlaceholder'), trigger: 'blur' }
],
key: [
{ required: true, message: t('keyPlaceholder'), trigger: 'blur' }
{ required: true, message: t('keyPlaceholder'), trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (/^[a-zA-Z_]+$/.test(value)) {
callback()
} else {
callback(new Error(t('keyFormatTips')))
}
},
trigger: 'blur'
}
],
data: [
{ required: true, message: t('dataPlaceholder'), trigger: 'blur' }

View File

@ -1,240 +0,0 @@
<template>
<el-dialog v-model="showDialog" :title="formData.printer_id ? t('updatePrinter') : t('addPrinter')" width="50%" class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('siteId')" prop="site_id">
<el-input v-model="formData.site_id" clearable :placeholder="t('siteIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('brand')" prop="brand">
<el-input v-model="formData.brand" clearable :placeholder="t('brandPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('printerName')" prop="printer_name">
<el-input v-model="formData.printer_name" clearable :placeholder="t('printerNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('printerCode')" prop="printer_code">
<el-input v-model="formData.printer_code" clearable :placeholder="t('printerCodePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('printerKey')" prop="printer_key">
<el-input v-model="formData.printer_key" clearable :placeholder="t('printerKeyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('openId')" prop="open_id">
<el-input v-model="formData.open_id" clearable :placeholder="t('openIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('apikey')" prop="apikey">
<el-input v-model="formData.apikey" clearable :placeholder="t('apikeyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('printNum')" prop="print_num">
<el-input v-model="formData.print_num" clearable :placeholder="t('printNumPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('value')" >
<el-input v-model="formData.value" clearable :placeholder="t('valuePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('printWidth')" prop="print_width">
<el-input v-model="formData.print_width" clearable :placeholder="t('printWidthPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('status')" prop="status">
<el-input v-model="formData.status" clearable :placeholder="t('statusPlaceholder')" class="input-width" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addPrinter, editPrinter, getPrinterInfo } from '@/app/api/printer'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
printer_id: '',
brand: '',
printer_name: '',
printer_code: '',
printer_key: '',
open_id: '',
apikey: '',
print_num: '',
value: '',
print_width: '',
status: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
brand: [
{ required: true, message: t('brandPlaceholder'), trigger: 'blur' },
]
,
printer_name: [
{ required: true, message: t('printerNamePlaceholder'), trigger: 'blur' },
]
,
printer_code: [
{ required: true, message: t('printerCodePlaceholder'), trigger: 'blur' },
]
,
printer_key: [
{ required: true, message: t('printerKeyPlaceholder'), trigger: 'blur' },
]
,
open_id: [
{ required: true, message: t('openIdPlaceholder'), trigger: 'blur' },
]
,
apikey: [
{ required: true, message: t('apikeyPlaceholder'), trigger: 'blur' },
]
,
print_num: [
{ required: true, message: t('printNumPlaceholder'), trigger: 'blur' },
]
,
value: [
{ required: true, message: t('valuePlaceholder'), trigger: 'blur' },
]
,
print_width: [
{ required: true, message: t('printWidthPlaceholder'), trigger: 'blur' },
]
,
status: [
{ required: true, message: t('statusPlaceholder'), trigger: 'blur' },
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.printer_id ? editPrinter : addPrinter
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if(row){
const data = await (await getPrinterInfo(row.printer_id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label{
height: auto !important;
}
</style>

View File

@ -1,170 +0,0 @@
<template>
<el-dialog v-model="showDialog" :title="formData.template_id ? t('updatePrinterTemplate') : t('addPrinterTemplate')" width="50%" class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('siteId')" prop="site_id">
<el-input v-model="formData.site_id" clearable :placeholder="t('siteIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('templateType')" prop="template_type">
<el-input v-model="formData.template_type" clearable :placeholder="t('templateTypePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('value')" >
<el-input v-model="formData.value" clearable :placeholder="t('valuePlaceholder')" class="input-width" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addPrinterTemplate, editPrinterTemplate, getPrinterTemplateInfo } from '@/app/api/printer'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
template_id: '',
template_type: '',
template_name: '',
value: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
template_type: [
{ required: true, message: t('templateTypePlaceholder'), trigger: 'blur' },
]
,
template_name: [
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' },
]
,
value: [
{ required: true, message: t('valuePlaceholder'), trigger: 'blur' },
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.template_id ? editPrinterTemplate : addPrinterTemplate
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if(row){
const data = await (await getPrinterTemplateInfo(row.template_id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label{
height: auto !important;
}
</style>

View File

@ -0,0 +1,363 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card>
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('printerSet') }}</h3>
<el-form-item :label="t('printerName')" prop="printer_name">
<el-input v-model.trim="formData.printer_name" clearable :placeholder="t('printerNamePlaceholder')" class="input-width" maxlength="20" />
</el-form-item>
<el-form-item :label="t('brand')" prop="brand">
<el-select v-model="formData.brand" :placeholder="t('brandPlaceholder')" clearable>
<el-option v-for="(item,key) in brandList" :key="key" :label="item" :value="key" />
</el-select>
</el-form-item>
<el-form-item :label="t('printerCode')" prop="printer_code">
<div>
<el-input v-model.trim="formData.printer_code" clearable :placeholder="t('printerCodePlaceholder')" class="input-width" maxlength="30" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerCodeTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('printerKey')" prop="printer_key">
<div>
<el-input v-model.trim="formData.printer_key" clearable :placeholder="t('printerKeyPlaceholder')" class="input-width" maxlength="30" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerKeyTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('openId')" prop="open_id">
<div>
<el-input v-model.trim="formData.open_id" clearable :placeholder="t('openIdPlaceholder')" class="input-width" maxlength="30" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('openIdTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('apikey')" prop="apikey">
<div>
<el-input v-model.trim="formData.apikey" clearable :placeholder="t('apikeyPlaceholder')" class="input-width" maxlength="60" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('apikeyTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('printWidth')" prop="print_width">
<el-radio-group v-model="formData.print_width">
<el-radio value="58mm">58mm</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('status')">
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-card>
<el-card v-for="(item,index) in printerType" :key="item.key" class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ item.title }}</h3>
<div class="flex mb-[10px] py-[8px] bg-[#F5F7F9] text-[14px]">
<div class="px-[12px] w-[200px]">{{ t('printTrigger') }}</div>
<div class="px-[12px] w-[100px]">{{ t('status') }}</div>
<div class="px-[12px] w-[250px]">{{ t('usePrintTemplate') }}</div>
<div class="px-[12px] w-[300px] flex-1" v-for="childItem in item.condition" :key="childItem.key">{{ childItem.title }}</div>
<div class="px-[12px] w-[200px]">{{ t('printNum') }}</div>
</div>
<template v-if="item.trigger">
<div class="flex bg-[#f8f8f9] mb-[10px] py-[20px]" v-for="(triggerItem,triggerKey) in item.trigger" :key="triggerKey">
<template v-if="formData.value[item.key]['trigger_' + triggerKey]">
<div class="font-bold w-[200px] px-[12px]">{{ triggerItem }}</div>
<div class="w-[100px] px-[12px]">
<el-switch v-model="formData.value[item.key]['trigger_' + triggerKey].status" :active-value="1" :inactive-value="0" />
</div>
<div class="w-[250px] px-[12px]">
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].template_id" :placeholder="t('请选择小票打印模板')" clearable>
<el-option v-for="templateItem in templateList[item.key]" :key="templateItem.template_id" :label="templateItem.template_name" :value="templateItem.template_id" />
</el-select>
</div>
<template v-for="childItem in item.condition">
<div class="w-[300px] px-[12px] flex-1" v-if="childItem.type == 'checkbox'">
<el-checkbox-group v-model="formData.value[item.key]['trigger_' + triggerKey][childItem.key]">
<el-checkbox v-for="(checkboxItem, index) in childItem.list" :label="checkboxItem.value" :key="index">{{ checkboxItem.name }}</el-checkbox>
</el-checkbox-group>
</div>
</template>
<div class="w-[200px] px-[12px]">
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].print_num">
<el-option label="1联" :value="1" />
<el-option label="2联" :value="2" />
<el-option label="3联" :value="3" />
<el-option label="4联" :value="4" />
</el-select>
</div>
</template>
</div>
</template>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { FormInstance, ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { deepClone } from '@/utils/common';
import { addPrinter, editPrinter,getPrinterInfo,getPrinterType,getPrinterBrand,getPrinterTemplateList } from '@/app/api/printer'
const route = useRoute()
const router = useRouter()
const repeat = ref(false)
const loading = ref(true)
const pageName = route.meta.title
/**
* 表单数据
*/
const initialFormData:any = {
printer_id: route.query.printer_id || 0,
brand: '',
printer_name: '',
printer_code: '',
printer_key: '',
open_id: '',
apikey: '',
template_type: [],
trigger: [],
value: {},
print_width: '58mm',
status: 1,
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
printer_name: [
{ required: true, message: t('printerNamePlaceholder'), trigger: 'blur' },
],
brand: [
{ required: true, message: t('brandPlaceholder'), trigger: 'blur' },
],
printer_code: [
{ required: true, message: t('printerCodePlaceholder'), trigger: 'blur' },
],
printer_key: [
{ required: true, message: t('printerKeyPlaceholder'), trigger: 'blur' },
],
open_id: [
{ required: true, message: t('openIdPlaceholder'), trigger: 'blur' },
],
apikey: [
{ required: true, message: t('apikeyPlaceholder'), trigger: 'blur' },
]
}
})
const printerType = ref([])
const init = async ()=> {
await getPrinterType({}).then((res: any) => {
if (res.data) {
printerType.value = res.data;
for (let i = 0; i < printerType.value.length; i++) {
let item: any = printerType.value[i];
formData.value[item.key] = {};
let extendData: any = {};
for (let ci = 0; ci < item.condition.length; ci++) {
let condition = item.condition[ci];
extendData[condition.key] = [];
if (condition.type == 'checkbox') {
extendData[condition.key] = []; //
for (let k = 0; k < condition.list.length; k++) {
extendData[condition.key].push(condition.list[k].value);
}
}
}
for (let key in item.trigger) {
formData.value[item.key]['trigger_' + key] = {
status: 1,
template_id: '',
print_num: 1,
};
Object.assign(formData.value[item.key]['trigger_' + key], deepClone(extendData));
}
}
}
if (!formData.printer_id) {
loading.value = false
}
})
if (formData.printer_id) {
getPrinterInfo(formData.printer_id).then((res: any) => {
let data = res.data;
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) {
if (key == 'value') {
for (let ck in formData[key]){
Object.assign(formData[key][ck],data[key][ck])
}
} else {
formData[key] = data[key]
}
}
})
loading.value = false
})
}
}
init()
const brandList = ref([])
getPrinterBrand({}).then((res: any) => {
brandList.value = res.data;
})
const templateList:any = ref({}) //
getPrinterTemplateList({}).then((res:any)=> {
if (res.data) {
let data = res.data;
for (let i = 0; i < data.length; i++) {
let item = data[i];
if (templateList.value[item.template_type] == undefined) {
templateList.value[item.template_type] = []
}
templateList.value[item.template_type].push({
template_id: item.template_id,
template_name: item.template_name,
})
}
}
})
/**
* 确认
* @param formEl
*/
const confirm = async(formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
if (printerType.value.length == 0) {
ElMessage({
type: 'warning',
message: t('printTypeEmpty')
})
return;
}
let save = formData.printer_id ? editPrinter : addPrinter
await formEl.validate(async(valid) => {
if (valid) {
let validateFlag = false;
let validateMessage = '';
for (let i = 0; i < printerType.value.length; i++) {
let item: any = printerType.value[i];
for (let k = 0; k < Object.keys(item.trigger).length; k++) {
let triggerItem = Object.keys(item.trigger)[k];
if (formData.value[item.key]['trigger_' + triggerItem].status == 0) {
continue;
}
if (!formData.value[item.key]['trigger_' + triggerItem].template_id) {
validateFlag = true;
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的小票打印模板`
break;
}
let isFail = false;
for (let ck = 0; ck < item.condition.length; ck++) {
let condition = item.condition[ck];
if (condition.type == 'checkbox') {
if (formData.value[item.key]['trigger_' + triggerItem][condition.key].length == 0) {
validateFlag = true;
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的${ condition.title }`
isFail = true;
break;
}
}
}
//
if (isFail) {
break;
}
}
//
if (validateFlag) {
break;
}
}
if (validateFlag) {
ElMessage({
type: 'warning',
message: validateMessage
})
return;
}
formData.template_type = [];
formData.trigger = [];
for (let key in formData.value) {
for (let childKey in formData.value[key]) {
formData.trigger.push(key + '_' + childKey);
}
formData.template_type.push(key)
}
if (repeat.value) return
repeat.value = true
let data = formData
save(data).then(res => {
repeat.value = false
if (!formData.printer_id) {
router.push('/printer/list')
}
}).catch(err => {
repeat.value = false
})
}
})
}
const back = () => {
router.push('/printer/list')
}
</script>
<style lang="scss" scoped></style>

View File

@ -10,50 +10,14 @@
</div>
<el-tabs class="demo-tabs" model-value="/printer/list" @tab-change="handleClick">
<el-tab-pane :label="t('打印机管理')" name="/printer/list" />
<el-tab-pane :label="t('打印模板')" name="/printer/template/list" />
<el-tab-pane :label="t('tabPrinterManager')" name="/printer/list" />
<el-tab-pane :label="t('tabPrinterTemplate')" name="/printer/template/list" />
</el-tabs>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="printerTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('siteId')" prop="site_id">
<el-input v-model="printerTable.searchParam.site_id" :placeholder="t('siteIdPlaceholder')" />
</el-form-item>
<el-form-item :label="t('brand')" prop="brand">
<el-input v-model="printerTable.searchParam.brand" :placeholder="t('brandPlaceholder')" />
</el-form-item>
<el-form-item :label="t('printerName')" prop="printer_name">
<el-input v-model="printerTable.searchParam.printer_name" :placeholder="t('printerNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('printerCode')" prop="printer_code">
<el-input v-model="printerTable.searchParam.printer_code" :placeholder="t('printerCodePlaceholder')" />
</el-form-item>
<el-form-item :label="t('printerKey')" prop="printer_key">
<el-input v-model="printerTable.searchParam.printer_key" :placeholder="t('printerKeyPlaceholder')" />
</el-form-item>
<el-form-item :label="t('openId')" prop="open_id">
<el-input v-model="printerTable.searchParam.open_id" :placeholder="t('openIdPlaceholder')" />
</el-form-item>
<el-form-item :label="t('apikey')" prop="apikey">
<el-input v-model="printerTable.searchParam.apikey" :placeholder="t('apikeyPlaceholder')" />
</el-form-item>
<el-form-item :label="t('printNum')" prop="print_num">
<el-input v-model="printerTable.searchParam.print_num" :placeholder="t('printNumPlaceholder')" />
</el-form-item>
<el-form-item :label="t('value')" prop="value">
<el-input v-model="printerTable.searchParam.value" :placeholder="t('valuePlaceholder')" />
</el-form-item>
<el-form-item :label="t('printWidth')" prop="print_width">
<el-input v-model="printerTable.searchParam.print_width" :placeholder="t('printWidthPlaceholder')" />
</el-form-item>
<el-form-item :label="t('status')" prop="status">
<el-input v-model="printerTable.searchParam.status" :placeholder="t('statusPlaceholder')" />
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-input v-model="printerTable.searchParam.create_time" :placeholder="t('createTimePlaceholder')" />
</el-form-item>
<el-form-item :label="t('updateTime')" prop="update_time">
<el-input v-model="printerTable.searchParam.update_time" :placeholder="t('updateTimePlaceholder')" />
<el-input v-model.trim="printerTable.searchParam.printer_name" :placeholder="t('printerNamePlaceholder')" maxlength="20" />
</el-form-item>
<el-form-item>
@ -68,31 +32,24 @@
<template #empty>
<span>{{ !printerTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="printer_id" :label="t('printerId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="brand" :label="t('brand')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="printer_name" :label="t('printerName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="printer_code" :label="t('printerCode')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="printer_key" :label="t('printerKey')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="open_id" :label="t('openId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="apikey" :label="t('apikey')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="print_num" :label="t('printNum')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="value" :label="t('value')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="printer_name" :label="t('printerName')" min-width="220" :show-overflow-tooltip="true"/>
<el-table-column prop="brand_name" :label="t('brand')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="print_width" :label="t('printWidth')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="status" :label="t('status')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="status" :label="t('status')" min-width="80" :show-overflow-tooltip="true" >
<template #default="{ row }">
<el-tag type="success" v-if="row.status == 1" @click="modifyPrinterStatusEvent(row.printer_id, 0)" class="cursor-pointer">{{ t('statusOn') }}</el-tag>
<el-tag type="info" v-else @click="modifyPrinterStatusEvent(row.printer_id, 1)" class="cursor-pointer">{{ t('statusOff') }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="testPrintEvent(row.printer_id)">{{ t('testPrint') }}</el-button>
<el-button type="primary" link @click="refreshTokenEvent(row.printer_id)">{{ t('refreshToken') }}</el-button>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.printer_id)">{{ t('delete') }}</el-button>
</template>
@ -106,60 +63,39 @@
</div>
</div>
<edit ref="editPrinterDialog" @complete="loadPrinterList" />
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import { getPrinterList, deletePrinter } from '@/app/api/printer'
import { img } from '@/utils/common'
import { getPrinterPageList, modifyPrinterStatus, deletePrinter,refreshPrinterToken,testPrint } from '@/app/api/printer'
import { ElMessageBox,FormInstance } from 'element-plus'
import Edit from '@/app/views/printer/components/printer-edit.vue'
import { useRoute,useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title;
const repeat = ref(false)
const handleClick = (path: string) => {
router.push({ path })
}
let printerTable = reactive({
const printerTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
"site_id":"",
"brand":"",
"printer_name":"",
"printer_code":"",
"printer_key":"",
"open_id":"",
"apikey":"",
"print_num":"",
"value":"",
"print_width":"",
"status":"",
"create_time":"",
"update_time":""
printer_name:''
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取小票打印机列表
*/
@ -167,7 +103,7 @@ const loadPrinterList = (page: number = 1) => {
printerTable.loading = true
printerTable.page = page
getPrinterList({
getPrinterPageList({
page: printerTable.page,
limit: printerTable.limit,
...printerTable.searchParam
@ -179,16 +115,30 @@ const loadPrinterList = (page: number = 1) => {
printerTable.loading = false
})
}
loadPrinterList()
const editPrinterDialog: Record<string, any> | null = ref(null)
const isRepeat = ref(false)
//
const modifyPrinterStatusEvent = (printer_id: any, status: any) => {
if (isRepeat.value) return
isRepeat.value = true
modifyPrinterStatus({
printer_id,
status
}).then((res) => {
loadPrinterList()
isRepeat.value = false
})
}
/**
* 添加小票打印机
*/
const addEvent = () => {
editPrinterDialog.value.setFormData()
editPrinterDialog.value.showDialog = true
router.push('/printer/add')
}
/**
@ -196,8 +146,7 @@ const addEvent = () => {
* @param data
*/
const editEvent = (data: any) => {
editPrinterDialog.value.setFormData(data)
editPrinterDialog.value.showDialog = true
router.push('/printer/edit?printer_id=' + data.printer_id)
}
/**
@ -205,36 +154,74 @@ const editEvent = (data: any) => {
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('printerDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
if (repeat.value) return
repeat.value = true
deletePrinter(id).then(() => {
loadPrinterList()
repeat.value = false
}).catch(() => {
repeat.value = false
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadPrinterList()
}
/**
* 测试打印
* @param printer_id
*/
const testPrintEvent = (printer_id: any) => {
ElMessageBox.confirm(t('testPrintTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
if (repeat.value) return
repeat.value = true
testPrint(printer_id).then((res: any) => {
repeat.value = false
}).catch(() => {
repeat.value = false
})
})
}
/**
* 授权重新获取token
* @param printer_id
*/
const refreshTokenEvent = (printer_id: any) => {
ElMessageBox.confirm(t('refreshTokenTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
if (repeat.value) return
repeat.value = true
refreshPrinterToken(printer_id).then((res: any) => {
loadPrinterList()
repeat.value = false
}).catch(() => {
repeat.value = false
})
})
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>
</style>

View File

@ -0,0 +1,350 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card>
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
<div class="flex">
<div class="flex-1 mr-[20px] bg-[#fff]">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('templateInfoLabel') }}</h3>
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model.trim="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" maxlength="20" />
</el-form-item>
<el-form-item :label="t('templateType')" prop="template_type" v-if="printerType.length">
<el-radio-group v-model="formData.template_type">
<el-radio v-for="item in printerType" :key="item.key" :label="item.key" @change="handlePrintType">{{ item.title }}</el-radio>
</el-radio-group>
</el-form-item>
</el-card>
<el-card class="box-card !border-none" shadow="never" v-if="printerType.length">
<h3 class="panel-title !text-sm">{{ t('templateEditLabel') }}</h3>
<div v-for="item in template" :key="item.key" class="bg-[#f8f8f9] mb-[20px] py-[20px] px-[40px] text-[14px]">
<h4 class="panel-title !text-sm">{{ item.title }}</h4>
<div v-for="(childItem,index) in item.list" :key="childItem.key" class="ml-[30px]" :style="{ 'margin-bottom' : item.list.length == (index + 1) ? '0' : '20px' }">
<div class="flex">
<el-checkbox v-model="formData.value[item.key][childItem.key].status" v-if="childItem.label" :label="childItem.label" :value="childItem.status" :true-value="1" :false-value="0" class="w-[180px] mr-[10px]" :disabled="childItem.disabled" />
<template v-if="childItem.type == 'input'">
<el-input v-model.trim="formData.value[item.key][childItem.key].value" clearable :placeholder="'请输入' + (childItem.placeholder ? childItem.placeholder : childItem.label)" class="input-width mr-[30px]" maxlength="32" />
</template>
<template v-if="childItem.type == 'checkbox'">
<el-checkbox-group v-model="formData.value[item.key][childItem.key].value" class="mr-[30px]">
<el-checkbox v-for="(checkboxItem, key) in childItem.list" :label="key" :key="key" :disabled="childItem.disabled">{{ checkboxItem }}</el-checkbox>
</el-checkbox-group>
</template>
<template v-if="childItem.type == 'select'">
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">{{ childItem.text }}</div>
<el-select v-model="formData.value[item.key][childItem.key].value" class="!w-[130px] mr-[30px]">
<el-option v-for="(item,key) in childItem.list" :key="key" :label="item" :value="key" />
</el-select>
</template>
<template v-if="childItem.fontSize">
<div class="flex mr-[30px]">
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">字号</div>
<el-select v-model="formData.value[item.key][childItem.key].fontSize" class="!w-[130px]">
<el-option label="小" value="normal" />
<!-- <el-option label="小" value="small" />-->
<el-option label="大" value="big" />
</el-select>
</div>
</template>
<template v-if="childItem.fontWeight">
<div class="flex mr-[30px]">
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">粗细</div>
<el-select v-model="formData.value[item.key][childItem.key].fontWeight" class="!w-[130px]">
<el-option label="正常" value="normal" />
<el-option label="加粗" value="bold" />
</el-select>
</div>
</template>
</div>
<div v-if="childItem.remark" class="text-[12px] text-[#b2b2b2] mt-[10px]">{{ childItem.remark }}</div>
</div>
</div>
</el-card>
</div>
<el-card class="box-card !border-none w-[450px]" shadow="never">
<h3 class="panel-title !text-sm">{{ t('preview') }}</h3>
<!-- 动态加载组件 -->
<component :is="modules[previewPath]" :value="formData.value"/>
</el-card>
</div>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { FormInstance, ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { getPrinterType, addPrinterTemplate, editPrinterTemplate, getPrinterTemplateInfo } from '@/app/api/printer'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const repeat = ref(false)
const loading = ref(true)
/**
* 表单数据
*/
const initialFormData:any = {
template_id: route.query.template_id || 0,
template_type: '',
template_name: '',
value: {},
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
template_name: [
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' },
],
template_type: [
{ required: true, message: t('templateTypePlaceholder'), trigger: 'blur' },
]
}
})
//
const modulesFiles = import.meta.glob('./components/*.vue', { eager: true })
const addonModulesFiles = import.meta.glob('@/addon/**/views/printer/components/*.vue', { eager: true })
addonModulesFiles && Object.assign(modulesFiles, addonModulesFiles)
const modules:any = {}
for (const [key, value] of Object.entries(modulesFiles)) {
const moduleName:any = key.split('/').pop()
const name = moduleName.split('.')[0]
modules[name] = value.default
}
const previewPath = ref('')
const printerType:any = ref([])
const template:any = ref([])
const init = async ()=> {
await getPrinterType({}).then((res: any) => {
if (res.data && res.data.length) {
printerType.value = res.data;
handlePrintType(printerType.value[0].key, Boolean(parseInt(formData.template_id)));
}
if (!formData.template_id) {
loading.value = false
}
})
if(formData.template_id) {
getPrinterTemplateInfo(formData.template_id).then((res:any)=>{
let data = res.data;
if (data && Object.keys(data).length) {
Object.keys(formData).forEach((key: string) => {
if (key == 'value') {
for (let ck in formData[key]){
Object.assign(formData[key][ck],data[key][ck])
}
} else {
formData[key] = data[key]
}
})
loading.value = false
}else {
ElMessage({
type: 'warning',
duration: 1500,
message: t('printTemplateEmpty')
})
setTimeout(()=>{
back();
loading.value = false
}, 2000);
}
})
}
};
init();
//
const handlePrintType = (value: any, load: boolean = false) => {
for (let i = 0; i < printerType.value.length; i++) {
if (printerType.value[i].key == value) {
formData.template_type = printerType.value[i].key;
previewPath.value = printerType.value[i].path;
template.value = printerType.value[i].template;
break;
}
}
//
for (let key in formData.value) {
delete formData.value[key];
}
refreshTemplateData();
}
//
const refreshTemplateData = ()=> {
for (let i = 0; i < template.value.length; i++) {
let item: any = template.value[i];
formData.value[item.key] = {};
for (let k = 0; k < item.list.length; k++) {
let childItem = item.list[k];
formData.value[item.key][childItem.key] = {
type: childItem.type,
value: childItem.value,
status: childItem.status,
fontSize: childItem.fontSize,
fontWeight: childItem.fontWeight,
};
}
}
}
/**
* 确认
* @param formEl
*/
const confirm = async(formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
if (printerType.value.length == 0) {
ElMessage({
type: 'warning',
message: t('printTypeEmpty')
})
return;
}
let save = formData.template_id ? editPrinterTemplate : addPrinterTemplate
await formEl.validate(async(valid) => {
if (valid) {
let validateFlag = false;
let validateMessage = '';
for (let i = 0; i < template.value.length; i++) {
let item: any = template.value[i];
let isFail = false;
for (let k = 0; k < item.list.length; k++) {
let childItem = item.list[k];
if (formData.value[item.key][childItem.key].status == 0) {
continue;
}
if (childItem.type == 'input') {
if (formData.value[item.key][childItem.key].value == '') {
validateFlag = true;
validateMessage = `请输入${ childItem.label }`;
isFail = true;
break;
}
} else if (childItem.type == 'select') {
if (formData.value[item.key][childItem.key].value == '') {
validateFlag = true;
validateMessage = `${ childItem.label }未设置[${ childItem.text }]`;
isFail = true;
break;
}
}
}
//
if (isFail) {
break;
}
}
if (validateFlag) {
ElMessage({
type: 'warning',
message: validateMessage
})
return;
}
for (let i = 0; i < template.value.length; i++) {
let item: any = template.value[i];
for (let k = 0; k < item.list.length; k++) {
let childItem = item.list[k];
if (childItem.type == 'checkbox') {
if (formData.value[item.key][childItem.key].value.length) {
formData.value[item.key][childItem.key].status = 1;
} else {
formData.value[item.key][childItem.key].status = 0;
}
}
}
}
if (repeat.value) return
repeat.value = true
let data = formData
save(data).then(res => {
repeat.value = false
if (!formData.template_id) {
back()
}
}).catch(err => {
repeat.value = false
})
}
})
}
const back = () => {
router.push('/printer/template/list')
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -10,31 +10,20 @@
</div>
<el-tabs class="demo-tabs" model-value="/printer/template/list" @tab-change="handleClick">
<el-tab-pane :label="t('打印机管理')" name="/printer/list" />
<el-tab-pane :label="t('打印模板')" name="/printer/template/list" />
<el-tab-pane :label="t('tabPrinterManager')" name="/printer/list" />
<el-tab-pane :label="t('tabPrinterTemplate')" name="/printer/template/list" />
</el-tabs>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="printerTemplateTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('siteId')" prop="site_id">
<el-input v-model="printerTemplateTable.searchParam.site_id" :placeholder="t('siteIdPlaceholder')" />
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model.trim="printerTemplateTable.searchParam.template_name" :placeholder="t('templateNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('templateType')" prop="template_type">
<el-input v-model="printerTemplateTable.searchParam.template_type" :placeholder="t('templateTypePlaceholder')" />
<el-select v-model="printerTemplateTable.searchParam.template_type" :placeholder="t('templateTypePlaceholder')" clearable>
<el-option v-for="(item,key) in printerType" :key="itemkey" :label="item.title" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model="printerTemplateTable.searchParam.template_name" :placeholder="t('templateNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('value')" prop="value">
<el-input v-model="printerTemplateTable.searchParam.value" :placeholder="t('valuePlaceholder')" />
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-input v-model="printerTemplateTable.searchParam.create_time" :placeholder="t('createTimePlaceholder')" />
</el-form-item>
<el-form-item :label="t('updateTime')" prop="update_time">
<el-input v-model="printerTemplateTable.searchParam.update_time" :placeholder="t('updateTimePlaceholder')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadPrinterTemplateList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
@ -47,14 +36,12 @@
<template #empty>
<span>{{ !printerTemplateTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="template_id" :label="t('templateId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="template_name" :label="t('templateName')" min-width="220" :show-overflow-tooltip="true"/>
<el-table-column prop="template_type" :label="t('templateType')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="template_name" :label="t('templateName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="value" :label="t('value')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="template_type_name" :label="t('templateType')" min-width="180" :show-overflow-tooltip="true"/>
<el-table-column prop="create_time" :label="t('createTime')" min-width="120" />
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
@ -71,19 +58,15 @@
</div>
</div>
<edit ref="editPrinterTemplateDialog" @complete="loadPrinterTemplateList" />
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import { getPrinterTemplateList, deletePrinterTemplate } from '@/app/api/printer'
import { img } from '@/utils/common'
import { getPrinterTemplatePageList, deletePrinterTemplate,getPrinterType } from '@/app/api/printer'
import { ElMessageBox,FormInstance } from 'element-plus'
import Edit from '@/app/views/printer/components/printer-template-edit.vue'
import { useRoute,useRouter } from 'vue-router'
const route = useRoute()
@ -94,29 +77,26 @@ const handleClick = (path: string) => {
router.push({ path })
}
let printerTemplateTable = reactive({
const printerTemplateTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
"site_id":"",
"template_type":"",
"template_name":"",
"value":"",
"create_time":"",
"update_time":""
searchParam: {
template_name: '',
template_type: '',
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const printerType = ref([])
getPrinterType({}).then((res: any) => {
if (res.data) {
printerType.value = res.data;
}
})
/**
* 获取小票打印模板列表
@ -125,7 +105,7 @@ const loadPrinterTemplateList = (page: number = 1) => {
printerTemplateTable.loading = true
printerTemplateTable.page = page
getPrinterTemplateList({
getPrinterTemplatePageList({
page: printerTemplateTable.page,
limit: printerTemplateTable.limit,
...printerTemplateTable.searchParam
@ -139,14 +119,11 @@ const loadPrinterTemplateList = (page: number = 1) => {
}
loadPrinterTemplateList()
const editPrinterTemplateDialog: Record<string, any> | null = ref(null)
/**
* 添加小票打印模板
*/
const addEvent = () => {
editPrinterTemplateDialog.value.setFormData()
editPrinterTemplateDialog.value.showDialog = true
router.push('/printer/template/add')
}
/**
@ -154,8 +131,7 @@ const addEvent = () => {
* @param data
*/
const editEvent = (data: any) => {
editPrinterTemplateDialog.value.setFormData(data)
editPrinterTemplateDialog.value.showDialog = true
router.push('/printer/template/edit?template_id=' + data.template_id)
}
/**
@ -171,13 +147,10 @@ const deleteEvent = (id: number) => {
).then(() => {
deletePrinterTemplate(id).then(() => {
loadPrinterTemplateList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
@ -186,13 +159,4 @@ const resetForm = (formEl: FormInstance | undefined) => {
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

View File

@ -4,7 +4,7 @@
<el-form-item :label="t('selectType')" prop="type">
<el-radio-group v-model="formData.select_type">
<el-radio :label="1">{{ t('dictType' )}}</el-radio>
<el-radio :label="2">{{ t('remotePullDown') }}</el-radio>
</el-radio-group>
</el-form-item>
@ -25,6 +25,18 @@
<el-option v-for="item in modelList" :label="item" :value="item" :key="item" />
</el-select>
</el-form-item>
<el-form-item prop="value_key" :label="t('remotePullDownValue')" v-if="formData.select_type == 2">
<el-select class="input-width" :placeholder="t('remotePullDownValuePlaceholder')" v-model="formData.value_key">
<el-option :label="`${item.name}:${item.comment}`" :value="item.name" v-for="(item, index) in keyList" :key="index" />
</el-select>
</el-form-item>
<el-form-item prop="label_key" :label="t('remotePullDownLabel')" v-if="formData.select_type == 2">
<el-select class="input-width" :placeholder="t('remotePullDownLabelPlaceholder')" v-model="formData.label_key">
<el-option :label="`${item.name}:${item.comment}`" :value="item.name" v-for="(item, index) in keyList" :key="index" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
@ -41,6 +53,8 @@ import { t } from '@/lang'
import { getDictAll } from '@/app/api/dict'
import type { FormInstance } from 'element-plus'
import { cloneDeep } from 'lodash-es'
import { getGeneratorAllModel, getAddonDevelop,getGeneratorModelTableColumn } from '@/app/api/tools'
const showDialog = ref(false)
const title = ref('')
/**
@ -59,8 +73,44 @@ const formData: Record<string, any> = ref({ ...initialFormData })
const formRef = ref<FormInstance>()
const dicList = ref<Array<any>>([])
/**
* 获取关联模型
*/
const modelList = ref([])
const getGeneratorAllModelFn = (params:any) => {
getGeneratorAllModel(params).then(res => {
modelList.value = res.data
})
}
//
const addonList = ref<Array<any>>([])
const getAddonDevelopFn = async () => {
let { data } = await getAddonDevelop({})
addonList.value = [{ title: "系统", key: "system" }]
addonList.value.push(...data)
getGeneratorAllModelFn({addon:'system'})
}
getAddonDevelopFn()
//
const addonChange =(val:any)=>{
formData.value.model = ''
getGeneratorAllModelFn({addon:val})
}
const keyList = ref([])
const getGeneratorModelTableColumnFn = (params:any) => {
getGeneratorModelTableColumn(params).then(res => {
keyList.value = res.data
})
}
//
const modelChange = (val:any) => {
// formData.value.model = ''
getGeneratorModelTableColumnFn({model:val})
}
//
const formRules = computed(() => {
@ -76,6 +126,54 @@ const formRules = computed(() => {
},
trigger: 'blur'
}
],
addon: [
{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.select_type == 2 && formData.value.addon == '') {
callback(new Error(t('addonsPlaceholder')))
}else{
callback()
}
},
trigger: 'blur'
}
],
model: [
{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.select_type == 2 && formData.value.model == '') {
callback(new Error(t('associatedModelPlaceholder')))
}else{
callback()
}
},
trigger: 'blur'
}
],
value_key: [
{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.select_type == 2 && formData.value.value_key == '') {
callback(new Error(t('remotePullDownValuePlaceholder')))
}else{
callback()
}
},
trigger: 'blur'
}
],
label_key: [
{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.select_type == 2 && formData.value.label_key == '') {
callback(new Error(t('remotePullDownLabelPlaceholder')))
}else{
callback()
}
},
trigger: 'blur'
}
]
}
@ -105,6 +203,11 @@ const confirm = async (formEl: FormInstance | undefined) => {
const setFormData = async (row: any = null) => {
formData.value = cloneDeep(Object.assign(initialFormData, row))
getDictAllFn()
if(formData.value.model != '')
{
getGeneratorAllModelFn({addon:formData.value.addon})
getGeneratorModelTableColumnFn({model:formData.value.model})
}
showDialog.value = true
}
const beforeClose = (next: any) => {

View File

@ -468,10 +468,6 @@ const onSave = async (code: number) => {
generateCreateFn(code)
} else {
loading.value = false
ElMessage({
type: 'success',
message: '操作成功'
})
setTimeout(() => {
window.codeActiveName = 'codeList'
back()

View File

@ -161,10 +161,15 @@
</el-tree>
</div>
</el-scrollbar>
<div class="ml-[20px]" style="width: calc(100% - 285px);">
<div class="ml-[20px] relative" style="width: calc(100% - 285px);">
<el-scrollbar class="h-[100%] w-[100%]">
<highlightjs autodetect class="h-[100%]" :code="code" />
</el-scrollbar>
<div class="absolute top-0 right-[15px] z-5 cursor-pointer hover:text-primary" @click="copyCode">
<el-tooltip content="点击复制" placement="top" >
<icon name="iconfont icondingdanzhongxinPC-3"/>
</el-tooltip>
</div>
</div>
</div>
</el-dialog>
@ -173,7 +178,7 @@
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'
import { reactive, ref, onMounted, watch } from 'vue'
import { t } from '@/lang'
import { getGenerateTableList, deleteGenerateTable, generateCreate, generatePreview, generatorCheckFile, getAddonDevelop } from '@/app/api/tools'
import { img } from '@/utils/common'
@ -182,6 +187,7 @@ import AddTable from '@/app/views/tools/code/components/add-table.vue'
import type { FormInstance } from 'element-plus'
import { downloadFile } from '@/utils/file'
import { useRouter, useRoute } from 'vue-router'
import { useClipboard } from '@vueuse/core'
const route = useRoute()
const pageName = route.meta.title
@ -381,6 +387,27 @@ const listToTree = (arr:any) => {
}
return ret
}
const { copy, isSupported, copied } = useClipboard()
const copyCode = () => {
if (!isSupported.value) {
ElMessage({
message: t('notSupportCopy'),
type: 'warning'
})
return
}
copy(code.value)
}
watch(copied, () => {
if (copied.value) {
ElMessage({
message: t('copySuccess'),
type: 'success'
})
}
})
</script>
<style lang="scss" scoped></style>

View File

@ -126,7 +126,14 @@ export function isUrl(str: string): boolean {
* @returns
*/
export function img(path: string): string {
return isUrl(path) ? path : `${import.meta.env.VITE_IMG_DOMAIN || location.origin}/${path}`
if (isUrl(path)) {
return path
} else {
let baseURL = import.meta.env.VITE_IMG_DOMAIN || location.origin
baseURL = baseURL.substr(-1) == '/' ? baseURL : `${baseURL}/`
if (path.substr(0, 1) == '/') path = path.substr(1)
return baseURL + path
}
}
/**

308
mvnw vendored Normal file
View File

@ -0,0 +1,308 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

205
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,205 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

View File

@ -9,10 +9,10 @@
<version>1.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<java.version>8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>1.8</java.version>
</properties>
<dependencies>
@ -21,6 +21,11 @@
<artifactId>hutool-all</artifactId>
<version>5.8.28</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>

View File

@ -153,6 +153,7 @@ public class BootConfig {
BootLogUtils.log("manager.app-name -> " + applicationName());
BootLogUtils.log("manager.jar-path -> " + this.getJarDir());
BootLogUtils.log("manager.jar-name -> " + jarName());
BootLogUtils.log("manager.root-path -> " + this.getRootPath());
// BootLogUtils.log("monitor.time-to-idle-seconds -> " + timeToIdleSeconds());
// BootLogUtils.log("manager.failed-restart-count -> " + failedRestartCount());
// BootLogUtils.log("manager.service-starting-hook-flag -> " + serviceStartingHookFlag());
@ -248,6 +249,21 @@ public class BootConfig {
}
}
public String getRootPath() {
String runPath = getRunPath(BootConfig.class);
if (runPath.startsWith("file:\\")) {
runPath = runPath.substring(6, runPath.length());
}
if (runPath.startsWith("file:")) {
runPath = runPath.substring(5, runPath.length());
}
String webroot = runPath;
if (webroot.contains("webroot")) {
webroot = webroot.substring(0, webroot.indexOf("webroot"));
}
return webroot;
}
/**
* @return
*/

View File

@ -1,13 +1,17 @@
package com.niu.boot.process;
import cn.hutool.core.io.FileUtil;
import com.niu.boot.config.BootConfig;
import com.niu.boot.utils.BIOUtils;
import com.niu.boot.utils.BootLogUtils;
import com.niu.boot.utils.PipeNameUtils;
import com.niu.boot.utils.ThreadUtils;
import org.apache.commons.io.FileUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class ProcessManager {
@ -89,12 +93,12 @@ public class ProcessManager {
AddonRollback.execute(uninstalledCommand, this.bootConfig.getJarDir());
this.start();
ThreadUtils.sleepSeconds(5);
} else if (pipeContent.startsWith("upgrade,")) {
} else if (pipeContent.startsWith("install,")) {
// ============================================================================//
// 正常升级情况进程也在运行中
// 正常安装情况进程也在运行中
// ============================================================================//
if (getAtomicStatus().get() == 3) {
String upgradingCommand = pipeContent.replaceAll("upgrade,", "upgrading,");
String upgradingCommand = pipeContent.replaceAll("install,", "installing,");
this.writePipe(upgradingCommand);
this.upgradeCount = 1;
this.upgradeTime = System.currentTimeMillis();
@ -108,10 +112,10 @@ public class ProcessManager {
ThreadUtils.sleepSeconds(10);
}
// ============================================================================//
// 正常升级情况进程已经处于停止状态这时候也需要启动起来继续升级任务
// 正常安装情况进程已经处于停止状态这时候也需要启动起来继续安装任务
// ============================================================================//
if (getAtomicStatus().get() == 5 || getAtomicStatus().get() == 6) {
String upgradingCommand = pipeContent.replaceAll("upgrade,", "upgrading,");
String upgradingCommand = pipeContent.replaceAll("install,", "installing,");
this.writePipe(upgradingCommand);
this.upgradeCount = 1;
this.upgradeTime = System.currentTimeMillis();
@ -124,20 +128,20 @@ public class ProcessManager {
this.start();
ThreadUtils.sleepSeconds(10);
}
} else if (pipeContent.startsWith("upgrading,")) {
} else if (pipeContent.startsWith("installing,")) {
// ============================================================================//
// 执行升级情况可以正常启动进入升级完成同时做出通知
// 执行安装情况可以正常启动进入安装完成同时做出通知
// ============================================================================//
if (getAtomicStatus().get() == 3) {
long currentTime = System.currentTimeMillis();
BootLogUtils.log("插件升级成功, 耗时:" + ((currentTime - upgradeTime) / 60) + " s.");
String upgradedCommand = pipeContent.replaceAll("upgrading,", "upgraded,");
BootLogUtils.log("插件安装成功, 耗时:" + ((currentTime - upgradeTime) / 60) + " s.");
String upgradedCommand = pipeContent.replaceAll("installing,", "installed,");
this.writePipe(upgradedCommand);
this.upgradeCommand = "";
this.upgradeTime = 0;
}
// ============================================================================//
// 执行升级情况不能正常启动进入重启或者回滚后重启同时做出通知
// 执行安装情况不能正常启动进入重启或者回滚后重启同时做出通知
// ============================================================================//
if (getAtomicStatus().get() == 5) {
if (this.upgradeCount < this.bootConfig.failedRestartCount()) {
@ -147,24 +151,121 @@ public class ProcessManager {
long currentTime = System.currentTimeMillis();
BootLogUtils.log("" + this.upgradeCount + "次启动, 耗时:" + ((currentTime - upgradeTime) / 60) + " s.");
} else {
String rollbackCommand = this.upgradeCommand.replaceAll("upgrading,", "rollback,");
String rollbackCommand = this.upgradeCommand.replaceAll("installing,", "rollback,");
this.writePipe(rollbackCommand);
AddonRollback.execute(rollbackCommand, this.bootConfig.getJarDir());
long currentTime = System.currentTimeMillis();
BootLogUtils.log("插件升级失败, 耗时:" + ((currentTime - upgradeTime) / 60) + " s, 进入回滚操作.");
BootLogUtils.log("插件安装失败, 耗时:" + ((currentTime - upgradeTime) / 60) + " s, 进入回滚操作.");
this.upgradeCommand = "";
this.restartWait();
}
}
} else if (pipeContent.startsWith("upgraded,")) {
BootLogUtils.log("升级成功后, 已正常启动服务.");
} else if (pipeContent.startsWith("installed,")) {
BootLogUtils.log("安装成功后, 已正常启动服务.");
} else if (pipeContent.startsWith("rollback,")) {
if (getAtomicStatus().get() == 3) {
BootLogUtils.log("升级回滚后, 已正常启动服务.");
BootLogUtils.log("安装回滚后, 已正常启动服务.");
}
if (getAtomicStatus().get() == 5) {
BootLogUtils.log(".......................................................");
BootLogUtils.log("升级回滚后, 启动失败,急需要人工干预处理.");
BootLogUtils.log("安装回滚后, 启动失败,急需要人工干预处理.");
}
} else if (pipeContent.startsWith("upgrade,")) {
this.resetPipe();
this.stop();
String[] data = pipeContent.split(",");
String addon = data[1];
String dir = data[2];
String version = data[3];
// 判断升級文件是否存在
File upgradeDir = new File(bootConfig.getRootPath(), "webroot/runtime/upgrade/" + addon + "/" + dir);
BootLogUtils.log("升级覆盖文件路径:" + upgradeDir.getPath());
String command = "upgradesuccess,";
if (upgradeDir.exists()) {
try {
this.coverUpgradeFile(upgradeDir, addon, version);
} catch (Exception e) {
command = "upgradefail,升级覆盖文件失败错误原因:" + e.getMessage();
BootLogUtils.log("升级覆盖文件失败,错误原因:" + e.getMessage());
e.printStackTrace();
}
} else {
BootLogUtils.log("升级覆盖文件路径不存在" + upgradeDir.getPath());
}
this.writePipe(command);
this.start();
} else if (pipeContent.startsWith("upgraderollback,")) {
this.resetPipe();
this.stop();
String[] data = pipeContent.split(",");
String addon = data[1];
String dir = data[2];
// 判断升級文件是否存在
File upgradeDir = new File(bootConfig.getRootPath(), "webroot/runtime/upgrade/" + addon + "/" + dir);
BootLogUtils.log("升级文件路径:" + upgradeDir.getPath());
String command = "upgraderollbacksuccess,";
if (upgradeDir.exists()) {
try {
FileUtils.copyDirectory(new File(upgradeDir, "backup/code"), new File(bootConfig.getRootPath()));
} catch (Exception e) {
command = "upgraderollbackfail,升级变更文件回滚失败错误原因:" + e.getMessage();
BootLogUtils.log("升级变更文件回滚失败错误原因:" + e.getMessage());
e.printStackTrace();
}
} else {
BootLogUtils.log("升级文件路径不存在" + upgradeDir.getPath());
}
this.writePipe(command);
this.start();
}
}
private void coverUpgradeFile(File upgradeDir, String addon, String versionList) throws Exception {
for (String version: versionList.split("-")) {
File changeRecord = new File(upgradeDir, "download/" + version + ".txt");
File sourceFile = null;
if (addon.equals("niucloud-admin")) {
sourceFile = new File(bootConfig.getRootPath());
} else {
sourceFile = new File(bootConfig.getRootPath(), "webroot/addon/" + addon);
}
// 移除已删除文件
if (changeRecord.exists()) {
List<String> change = Arrays.asList(FileUtils.readFileToString(changeRecord, "UTF-8").split("\n"));
for (String line : change) {
String[] content = line.split(" ");
if (content[0].equals("-")) {
(new File(sourceFile, content[2])).deleteOnExit();
}
}
}
// 覆盖变更文件
File codeDir = new File(upgradeDir, "download/" + version);
if (addon.equals("niucloud-admin")) {
File[] childFile = codeDir.listFiles();
for (File file : childFile) {
if (file.isDirectory()) {
if (new File(sourceFile, file.getName()).exists()) FileUtils.copyDirectory(file, new File(sourceFile, file.getName()));
} else {
FileUtils.copyFile(file, new File(sourceFile, file.getName()));
}
}
} else {
// 覆盖jar包
FileUtils.copyDirectory(codeDir, sourceFile);
File jarFile = new File(codeDir, "jar/" + addon + ".jar");
if (jarFile.exists()) FileUtils.copyFile(jarFile, new File(bootConfig.getRootPath(), "webroot/jar/addon/" + addon + ".jar"));
}
}
}

View File

@ -354,6 +354,13 @@
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>com.yly.print_sdk_library</groupId>
<artifactId>yly</artifactId>
<scope>system</scope>
<version>2.2.2</version>
<systemPath>${pom.basedir}/src/main/resources/core/lib/yly_sdk_2.2.2.jar</systemPath>
</dependency>
</dependencies>

View File

@ -0,0 +1,59 @@
package com.niu.core.common.component.context;
import com.niu.core.common.config.dataization.AddonModuleContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import java.util.*;
@Slf4j
public final class MapperMap {
private static final Map<String, List<String>> mappersByModule = new LinkedHashMap<>();
public static synchronized void init(Class<? extends Mapper> annotationClass, List<Class> annotationImplClassList) {
if (annotationClass == null || annotationImplClassList == null || annotationImplClassList.size() <= 0) {
return;
}
Map<String, String> addonModuleMap = getAddonModuleMap();
for (Class annotationImplClass : annotationImplClassList) {
Mapper mapper = (Mapper) annotationImplClass.getAnnotation(annotationClass);
if (mapper != null) {
String moduleName = getModuleName(addonModuleMap, annotationImplClass.getName());
List<String> mappers = mappersByModule.getOrDefault(moduleName, new LinkedList<>());
mappers.add(annotationImplClass.getName());
mappersByModule.put(moduleName, mappers);
}
}
log.info("mappersByModule = " + mappersByModule);
}
private static String getModuleName(Map<String, String> addonModuleMap, String className) {
String module = "core";
for (String key : addonModuleMap.keySet()) {
if (className.startsWith(key + ".")) {
module = addonModuleMap.get(key);
break;
}
}
return module;
}
private static Map<String, String> getAddonModuleMap() {
Map<String, String> map = new HashMap<>();
Map<String, Class<?>> addonModule = AddonModuleContext.getAddonModuleMap();
for (String key: addonModule.keySet()) {
Class clazz = addonModule.get(key);
map.put(clazz.getPackage().getName(), key);
}
return map;
}
public static List<String> getMappersByModule(String module) {
return mappersByModule.getOrDefault(module, new LinkedList<>());
}
}

View File

@ -5,10 +5,8 @@ import com.niu.core.common.component.context.listener.CallbackListener;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
* 媒介类事件服务者
@ -48,31 +46,32 @@ public final class CallbackMediator {
/**
* @param callbackClass
*/
private void initCallback(Class callbackClass) {
private void initCallback(Class<?> callbackClass) {
try {
Object subscriberObject = callbackClass.newInstance();
if (subscriberObject instanceof CallbackListener) {
Method method = getCallbackMethod(callbackClass);
Class businessThemeClass = getCallbackType(method);
if (businessThemeClass == null) {
return;
}
Object themeObject = themeObjectMap.get(businessThemeClass);
if (themeObject == null) {
themeObject = businessThemeClass.newInstance();
if (themeObject instanceof Event) {
themeObjectMap.put(businessThemeClass, (Event) themeObject);
for (Method method : getCallbackMethod(callbackClass)) {
Class<?> businessThemeClass = getCallbackType(method);
if (businessThemeClass == null) {
return;
}
Object themeObject = themeObjectMap.get(businessThemeClass);
if (themeObject == null) {
themeObject = businessThemeClass.newInstance();
if (themeObject instanceof Event) {
themeObjectMap.put(businessThemeClass, (Event) themeObject);
}
}
List<CallbackListener> callbackListenerList = callbackListenerMap.get(businessThemeClass);
if (callbackListenerList == null) {
callbackListenerList = new ArrayList<>();
}
callbackListenerList.add((CallbackListener<?>) subscriberObject);
callbackListenerMap.put(businessThemeClass, callbackListenerList);
}
List<CallbackListener> callbackListenerList = callbackListenerMap.get(businessThemeClass);
if (callbackListenerList == null) {
callbackListenerList = new ArrayList<>();
}
callbackListenerList.add((CallbackListener) subscriberObject);
callbackListenerMap.put(businessThemeClass, callbackListenerList);
}
} catch (Exception e) {
// ignore
throw new RuntimeException(e);
}
}
@ -80,9 +79,9 @@ public final class CallbackMediator {
* @param method
* @return
*/
public Class getCallbackType(Method method) {
public Class<?> getCallbackType(Method method) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes != null && parameterTypes.length > 0) {
if (parameterTypes.length > 0) {
return parameterTypes[0];
}
return null;
@ -92,16 +91,11 @@ public final class CallbackMediator {
* @param clazz
* @return
*/
public Method getCallbackMethod(Class clazz) {
Method[] methods = clazz.getMethods();
Method targetMethod = null;
for (Method method : methods) {
if (method.getName().equals("handleCallback")) {
targetMethod = method;
break;
}
}
return targetMethod;
public List<Method> getCallbackMethod(Class<?> clazz) {
return Arrays.stream(clazz.getMethods())
.filter(method -> method.getName().equals("handleCallback"))
.filter(method -> method.getParameters().length == 1)
.collect(Collectors.toList());
}
/**

View File

@ -21,7 +21,7 @@ public class Event extends ApplicationEvent {
private Set<String> appSignSet = new HashSet();
// 是否授权发送
private boolean authority = true;
private boolean authority = false;
// 事件名称
private String name;

View File

@ -0,0 +1,14 @@
package com.niu.core.common.component.upgrade;
import cn.hutool.json.JSONObject;
import com.niu.core.common.component.upload.model.*;
public interface IUpgradeProvider {
/**
* 处理
* @param
*/
public void handle();
}

View File

@ -0,0 +1,15 @@
package com.niu.core.common.component.upgrade.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UpgradeProvider {
String addon();
String version();
}

View File

@ -0,0 +1,60 @@
package com.niu.core.common.component.upgrade.factory;
import cn.hutool.core.util.StrUtil;
import com.niu.core.common.component.upgrade.IUpgradeProvider;
import com.niu.core.common.component.upgrade.annotation.UpgradeProvider;
import com.niu.core.common.component.upload.IUploadProvider;
import com.niu.core.common.component.upload.annotation.UploadProvider;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
@Slf4j
public final class UpgradeProviderFactory {
private static Map<String, Class<? extends IUpgradeProvider>> upgradeProviderMap = new HashMap<>();
/**
* 初始化执行
*
* @param annotationClass
* @param annotationImplClassList
*/
public static synchronized void init(Class<? extends UpgradeProvider> annotationClass, List<Class> annotationImplClassList) {
if (annotationClass == null || annotationImplClassList == null || annotationImplClassList.size() <= 0) {
return;
}
for (Class annotationImplClass : annotationImplClassList) {
UpgradeProvider upgradeProvider = (UpgradeProvider) annotationImplClass.getAnnotation(annotationClass);
if (upgradeProvider != null) {
String addon = upgradeProvider.addon();
String version = upgradeProvider.version();
if (StrUtil.isNotEmpty(addon) && StrUtil.isNotEmpty(version)) {
try {
upgradeProviderMap.put(addon + version, annotationImplClass);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
log.info("upgradeProviderMap = " + upgradeProviderMap);
}
/**
* 执行升级方法
* @param addon
* @param version
*/
public static void handle(String addon, String version) {
Class<? extends IUpgradeProvider> upgradeProviderClass = upgradeProviderMap.get(addon + version);
IUpgradeProvider uploadProvider = null;
if (upgradeProviderClass != null) {
try {
uploadProvider = upgradeProviderClass.newInstance();
uploadProvider.handle();
} catch (InstantiationException | IllegalAccessException e) {
}
}
}
}

View File

@ -458,4 +458,9 @@ public final class AddonModuleContext {
return addonModuleMap.keySet();
}
/**
*
* @return
*/
public static Map<String, Class<?>> getAddonModuleMap() { return addonModuleMap; }
}

View File

@ -1,7 +1,12 @@
package com.niu.core.common.config.dataization;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.github.yulichang.injector.MPJSqlInjector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -9,6 +14,7 @@ import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
@Configuration
public class MybatisPlusConfig {
@ -48,4 +54,20 @@ public class MybatisPlusConfig {
return paginationInnerInterceptor;
}
@Bean
public InsertBatchSqlInjector insertBatchSqlInjector() {
return new InsertBatchSqlInjector();
}
public static class InsertBatchSqlInjector extends MPJSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
return methodList;
}
}
}

View File

@ -54,21 +54,26 @@ public class CoreApplicationRunner implements CommandLineRunner, ApplicationRunn
} else {
executorService.schedule(() -> {
log.info("生产环境下装载模块开始.");
// 初始化已安装的插件
Map<String, String> addonEnvsMap = AddonResourceHelper.loadDynamicAddon();
log.info("addonEnvsMap = " + addonEnvsMap);
AddonModuleContext.init(addonEnvsMap);
// 统一扫描注解
Map<Class<? extends Annotation>, List<Class>> annotationClassListMap = ResourceBeanInitializer.scanning(basePackage);
// 初始化国际化
AddonModuleBundleMessageSource.init();
// 业务资源初始化
ResourceBeanInitializer.initialize(annotationClassListMap);
// 从管道中获取命令
PipeCommandHelper.doPipeCommand();
log.info("生产环境下装载模块完成.");
// 钩子输出
System.out.println("Service started successfully.");
try {
// 初始化已安装的插件
Map<String, String> addonEnvsMap = AddonResourceHelper.loadDynamicAddon();
log.info("addonEnvsMap = " + addonEnvsMap);
AddonModuleContext.init(addonEnvsMap);
// 统一扫描注解
Map<Class<? extends Annotation>, List<Class>> annotationClassListMap = ResourceBeanInitializer.scanning(basePackage);
// 初始化国际化
AddonModuleBundleMessageSource.init();
// 业务资源初始化
ResourceBeanInitializer.initialize(annotationClassListMap);
// 从管道中获取命令
PipeCommandHelper.doPipeCommand();
log.info("生产环境下装载模块完成.");
// 钩子输出
System.out.println("Service started successfully.");
}catch (Exception e) {
log.info("生产环境下装载模块异常");
e.printStackTrace();
}
}, delaySeconds, TimeUnit.SECONDS);
}
executorService.shutdown();

View File

@ -78,7 +78,7 @@ public final class PipeCommandHelper {
ICoreAddonInstallService iCoreAddonInstallService = (ICoreAddonInstallService) SpringContext.getBean(ICoreAddonInstallService.class);
iCoreAddonInstallService.installResult(false, addonResult.getAddon(), addonResult.getMessage());
}
} else if (addonResult.getOperate().endsWith("upgraded,")) {
} else if (addonResult.getOperate().endsWith("installed,")) {
// 升级成功需要回调
if (addonResult.getResult() == 1) {
ICoreAddonInstallService iCoreAddonInstallService = (ICoreAddonInstallService) SpringContext.getBean(ICoreAddonInstallService.class);

View File

@ -2,6 +2,9 @@ package com.niu.core.common.config.executable.initialize;
import com.niu.core.common.annotation.EventCallback;
import com.niu.core.common.annotation.SpringModuleApplication;
import com.niu.core.common.component.context.MapperMap;
import com.niu.core.common.component.upgrade.annotation.UpgradeProvider;
import com.niu.core.common.component.upgrade.factory.UpgradeProviderFactory;
import com.niu.core.common.utils.system.ClassPathScanAnnotationManager;
import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.component.context.event.EventMediatorContext;
@ -19,6 +22,7 @@ import com.niu.core.common.component.sms.factory.SmsProviderFactory;
import com.niu.core.common.component.upload.annotation.UploadProvider;
import com.niu.core.common.component.upload.factory.UploadProviderFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
@ -52,6 +56,10 @@ public final class ResourceBeanInitializer {
scanAnnotationClassList.add(JobProvider.class);
// 事件回调
scanAnnotationClassList.add(EventCallback.class);
// 升级事件
scanAnnotationClassList.add(UpgradeProvider.class);
// mapper
scanAnnotationClassList.add(Mapper.class);
// 统一获取系统中的注解返回注解以及扫描到实现类列表
Map<Class<? extends Annotation>, List<Class>> annotationClassListMap = ClassPathScanAnnotationManager.scanClassAnnotation(basePackage, scanAnnotationClassList);
return annotationClassListMap;
@ -79,6 +87,10 @@ public final class ResourceBeanInitializer {
// EventMediatorContext.test();
// 任务调度统一实现
JobProviderFactory.init(JobProvider.class, annotationClassListMap.get(JobProvider.class));
// 升级事件初始化
UpgradeProviderFactory.init(UpgradeProvider.class, annotationClassListMap.get(UpgradeProvider.class));
MapperMap.init(Mapper.class, annotationClassListMap.get(Mapper.class));
}
}

View File

@ -0,0 +1,23 @@
package com.niu.core.common.utils;
import java.net.MalformedURLException;
import java.net.URL;
public class CommonUtils {
/**
* 判断字符串是否是链接
* @param str
* @return
*/
public static boolean isUrl(String str) {
if (str == null || str.isEmpty()) {
return false;
}
try {
new URL(str);
return true;
} catch (MalformedURLException e) {
return false;
}
}
}

View File

@ -69,7 +69,7 @@ public class DatabaseBackup {
statement = connection.prepareStatement("SHOW TABLES");
resultSet = statement.executeQuery();
file = new File(this.backupFilePath + fileName + ".sql");
file = new File(this.backupFilePath + fileName + "-" + fileCounter + ".sql");
writer = new FileWriter(file);
while (resultSet.next()) {

View File

@ -180,7 +180,7 @@ public class NiucloudUtils {
* niucloud云服务器
*/
public static class Cloud {
private String baseUrl = "http://8.152.194.94:8000/";
private String baseUrl = "http://java.oss.niucloud.com/";
private String url;

View File

@ -32,9 +32,8 @@ public class QrcodeUtils {
throw new UploadException("创建二维码存放目录失败");
}
}
String filePath = dir + "/" + DigestUtil.md5Hex(url + String.valueOf(System.currentTimeMillis())) + ".png";
return createQrcode(url, page, data, siteId, channel, true, filePath);
return createQrcode(url, page, data, siteId, channel, true, dir);
}
/**

View File

@ -10,6 +10,7 @@ import java.util.Random;
import javax.imageio.ImageIO;
import cn.hutool.crypto.digest.DigestUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
@ -120,8 +121,8 @@ public class QRCodeUtils {
public static String encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtils.createImage(content, imgPath, needCompress);
mkdirs(destPath);
String file = new Random().nextInt(99999999) + ".jpg";
ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));
String file = DigestUtil.md5Hex(content) + ".png";
ImageIO.write(image, FORMAT_NAME, new File(destPath, file));
return file;
}
@ -169,8 +170,8 @@ public class QRCodeUtils {
* @param destPath 存储地址
* @throws Exception
*/
public static void encode(String content, String destPath) throws Exception {
QRCodeUtils.encode(content, null, destPath, false);
public static String encode(String content, String destPath) throws Exception {
return QRCodeUtils.encode(content, null, destPath, false);
}
/**

View File

@ -33,7 +33,7 @@ public class DateUtils {
*/
public static Long StringToTimestamp(String date) {
if (date.equals("")) {
if (date.equals("") || date.equals("0")) {
return 0L;
}
java.util.Date dateTime = DateUtil.parse(date);

View File

@ -1,7 +1,11 @@
package com.niu.core.common.utils.file;
import cn.hutool.core.util.ObjectUtil;
import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.utils.system.RuntimeTools;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.service.admin.upgrade.IUpgradeService;
import com.niu.core.service.admin.upgrade.vo.UpgradeTaskVo;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
@ -16,7 +20,7 @@ public class PipeNameUtils {
* @param addonName
*/
public static void noticeBootRestart(String applicationName, String addonName) {
noticeBoot(applicationName, "upgrade", addonName);
noticeBoot(applicationName, "install", addonName);
}
/**
@ -27,6 +31,20 @@ public class PipeNameUtils {
noticeBoot(applicationName, "uninstall", addonName);
}
/**
*
* @param applicationName
* @param addonName
*/
public static void noticeBootRestartByUpgrade(String applicationName, String addonName, String dir, String version) {
noticeBootCommand(applicationName, "upgrade," + addonName + "," + dir + "," + version);
}
public static void noticeBootRestartByUpgradeRollback(String applicationName, String addonName, String dir) {
noticeBootCommand(applicationName, "upgraderollback," + addonName + "," + dir);
}
/**
* @param applicationName
* @param command
@ -91,15 +109,15 @@ public class PipeNameUtils {
addonResult.setOperate(AddonResult.OPERATE_UNINSTALL);
addonResult.setAddon(addon);
// 卸载完成
} else if (command.startsWith("upgrading,")) {
} else if (command.startsWith("installing,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
String addon = command.replaceAll("upgrading,", "");
String addon = command.replaceAll("installing,", "");
addonResult.setResult(1);
addonResult.setOperate(AddonResult.OPERATE_ROLLBACK);
addonResult.setAddon(addon);
} else if (command.startsWith("upgraded,")) {
} else if (command.startsWith("installed,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
String addon = command.replaceAll("upgraded,", "");
String addon = command.replaceAll("installed,", "");
addonResult.setResult(1);
addonResult.setOperate(AddonResult.OPERATE_ROLLBACK);
addonResult.setAddon(addon);
@ -109,6 +127,45 @@ public class PipeNameUtils {
addonResult.setResult(-1);
addonResult.setOperate(AddonResult.OPERATE_ROLLBACK);
addonResult.setAddon(addon);
} else if (command.startsWith("upgrade,") || command.startsWith("upgraderollback,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
} else if (command.startsWith("upgradefail,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
IUpgradeService upgradeService = SpringContext.bean(IUpgradeService.class);
UpgradeTaskVo task = upgradeService.getUpgradeTask();
if (ObjectUtil.isNotEmpty(task) && ObjectUtil.isNotEmpty(task.getStatus()) && task.getStatus().equals("restarting")) {
String msg = command.replaceAll("upgradefail,", "");
task.setStatus("restarted");
task.getError().add(msg);
upgradeService.setUpgradeTaskCache(task);
upgradeService.upgradeErrorHandle(task);
}
} else if (command.startsWith("upgradesuccess,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
IUpgradeService upgradeService = SpringContext.bean(IUpgradeService.class);
UpgradeTaskVo task = upgradeService.getUpgradeTask();
if (ObjectUtil.isNotEmpty(task) && ObjectUtil.isNotEmpty(task.getStatus()) && task.getStatus().equals("restarting")) {
task.setStatus("restarted");
upgradeService.setUpgradeTaskCache(task);
}
} else if (command.startsWith("upgraderollbackfail,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
IUpgradeService upgradeService = SpringContext.bean(IUpgradeService.class);
UpgradeTaskVo task = upgradeService.getUpgradeTask();
if (ObjectUtil.isNotEmpty(task) && ObjectUtil.isNotEmpty(task.getStatus()) && task.getStatus().equals("restarting")) {
String msg = command.replaceAll("upgraderollbackfail,", "");
task.setStatus("restarted");
task.getError().add(msg);
upgradeService.setUpgradeTaskCache(task);
}
} else if (command.startsWith("upgraderollbacksuccess,")) {
PipeNameUtils.noticeBootCommand(applicationName, "");
IUpgradeService upgradeService = SpringContext.bean(IUpgradeService.class);
UpgradeTaskVo task = upgradeService.getUpgradeTask();
if (ObjectUtil.isNotEmpty(task) && ObjectUtil.isNotEmpty(task.getStatus()) && task.getStatus().equals("restarting")) {
task.setStatus("restarted");
upgradeService.setUpgradeTaskCache(task);
}
} else {
addonResult.setResult(0);
}

View File

@ -1,9 +1,13 @@
package com.niu.core.common.utils.image;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.utils.CommonUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
@ -16,14 +20,18 @@ public class ImageUtils {
* 图片转base64
* @throws IOException
*/
public static String imageToBase64(String path) throws IOException {
File file = new File(path);
if (!file.exists()) return "";
public static String imageToBase64(String path) {
try {
File file = new File(path);
if (!file.exists()) return "";
byte[] imageBytes = Files.readAllBytes(Paths.get(path));
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
byte[] imageBytes = Files.readAllBytes(Paths.get(path));
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
return "data:image/"+ getImageExt(path) +";base64," + base64Image;
return "data:image/"+ getImageExt(path) +";base64," + base64Image;
} catch (Exception e) {
return "";
}
}
/**
@ -40,4 +48,38 @@ public class ImageUtils {
return "";
}
}
/**
* 读取图片
* @param imgPath
* @return
* @throws Exception
*/
public static BufferedImage readImage(String imgPath) throws Exception {
if (CommonUtils.isUrl(imgPath)) {
URL url = new URL(imgPath);
return ImageIO.read(url);
} else {
File defaultFile = new File(WebAppEnvs.get().webRootDownResource, imgPath);
return ImageIO.read(defaultFile);
}
}
/**
* 读取图片
* @param imgPath
* @param defaultImg
* @return
*/
public static BufferedImage readImage(String imgPath, String defaultImg) {
try {
return readImage(imgPath);
} catch (Exception e) {
try {
return readImage(defaultImg);
} catch (Exception d) {
return null;
}
}
}
}

View File

@ -1,6 +1,7 @@
package com.niu.core.controller.adminapi.addon;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.json.JSONObject;
import com.niu.core.common.domain.Result;
import com.niu.core.enums.addon.AddonTypeEnum;
import com.niu.core.service.admin.addon.IAddonService;
@ -39,6 +40,22 @@ public class UpgradeController {
return Result.success(upgradeService.getUpgradeContent(addon));
}
/**
* 升级检测
*/
@GetMapping("/check")
public Result<?> upgradeCheck() {
return Result.success(upgradeService.upgradeCheck(""));
}
/**
* 升级检测
*/
@GetMapping("/check/{addon}")
public Result<?> upgradeCheck(@PathVariable(value = "addon") String addon) {
return Result.success(upgradeService.upgradeCheck(addon));
}
/**
* 升级
*/

View File

@ -1,5 +1,6 @@
package com.niu.core.controller.adminapi.generator;
import com.niu.core.common.component.context.MapperMap;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
@ -101,7 +102,7 @@ public class GenerateController {
public Result<Map<String, String>> create(@Validated @RequestBody GenerateCodeParam generateCodeParam) {
generateService.generate(generateCodeParam);
Map<String, String> data = new HashMap<>();
data.put("file", "upload/generate/package.zip");
if (generateCodeParam.getGenerateType().equals("2")) data.put("file", "upload/generate/package.zip");
return Result.success(data);
}
@ -149,12 +150,24 @@ public class GenerateController {
return Result.success(list);
}
/**
* 获取mapper
* @param addon
* @return
*/
@GetMapping("/all_model")
public Result<?> getAllMapper(@RequestParam String addon) {
if (addon.equals("system")) addon = "core";
return Result.success(MapperMap.getMappersByModule(addon));
}
/**
* 根据mapper获取表字段
* @param model
* @return
*/
@GetMapping("/model_table_column")
public Result<?> gettableColumn(@RequestParam String model) {
return Result.success(generateService.getTableColumnByMapper(model));
}
}

View File

@ -75,7 +75,7 @@ public class SysPosterController {
* @return Result<Object>
*/
@PutMapping("/{id}")
public Result<Object> edit(Integer id, @Validated @RequestBody SysPosterParam editParam) {
public Result<Object> edit(@PathVariable Integer id, @Validated @RequestBody SysPosterParam editParam) {
sysPosterService.edit(id, editParam);
return Result.success();
}
@ -86,7 +86,7 @@ public class SysPosterController {
* @return Result<Object>
*/
@DeleteMapping("/{id}")
public Result<Object> del(@Validated @RequestBody Integer id) {
public Result<Object> del(@PathVariable Integer id) {
sysPosterService.del(id);
return Result.success();
}

View File

@ -0,0 +1,128 @@
package com.niu.core.controller.adminapi.sys;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.Result;
import com.niu.core.service.admin.sys.ISysPrinterService;
import com.niu.core.service.admin.sys.param.SysPrinterModifyStatusParam;
import com.niu.core.service.admin.sys.param.SysPrinterParam;
import com.niu.core.service.admin.sys.param.SysPrinterSearchParam;
import com.niu.core.service.core.sys.param.SysPrinterPrintTicketParam;
import com.niu.core.service.core.sys.vo.SysPrinterPrintTicketVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 小票打印机控制器
*/
@RestController
@RequestMapping("adminapi/sys/printer")
public class SysPrinterController {
@Resource
ISysPrinterService sysPrinterService;
/**
* 小票打印机分页列表
*
* @param pageParam 分页
* @param searchParam 搜索条件
* @return Result<PageResult < SysPrinterListVo>>
*/
@GetMapping
public Result<?> page(@Validated PageParam pageParam, @Validated SysPrinterSearchParam searchParam) {
return Result.success(sysPrinterService.page(pageParam, searchParam));
}
@GetMapping("/list")
public Result<?> lists(@Validated SysPrinterSearchParam searchParam) {
return Result.success(sysPrinterService.getList(searchParam));
}
/**
* 小票打印机详情
*
* @param id 主键ID
* @return Result<SysPrinterInfoVo>
*/
@GetMapping("/{id}")
public Result<?> info(@PathVariable Integer id) {
return Result.success(sysPrinterService.info(id));
}
/**
* 小票打印机添加
*
* @param addParam 添加参数
* @return Result<?>
*/
@PostMapping
public Result<?> add(@Validated @RequestBody SysPrinterParam addParam) {
sysPrinterService.add(addParam);
return Result.success();
}
/**
* 小票打印机编辑
*
* @param editParam 编辑参数
* @return Result<?>
*/
@PutMapping("/{id}")
public Result<?> edit(@PathVariable Integer id, @Validated @RequestBody SysPrinterParam editParam) {
sysPrinterService.edit(id, editParam);
return Result.success();
}
@PutMapping("/status")
public Result<?> modifyStatus(@Validated @RequestBody SysPrinterModifyStatusParam editParam) {
sysPrinterService.modifyStatus(editParam);
return Result.success();
}
/**
* 小票打印机删除
*
* @param id 参数
* @return Result<?>
*/
@DeleteMapping("/{id}")
public Result<?> del(@PathVariable Integer id) {
sysPrinterService.del(id);
return Result.success();
}
@GetMapping("/type")
public Result<?> getType() {
return Result.success(sysPrinterService.getType());
}
@GetMapping("/brand")
public Result<?> getBrand() {
return Result.success(sysPrinterService.getBrand());
}
@PutMapping("/refreshtoken/{id}")
public Result<?> refreshToken(@PathVariable Integer id) {
return Result.success(sysPrinterService.refreshToken(id));
}
@PutMapping("/testprint/{id}")
public Result<?> testPrint(@PathVariable Integer id) {
sysPrinterService.testPrint(id);
return Result.success();
}
@PostMapping("/printticket")
public Result<?> printTicket(@RequestBody SysPrinterPrintTicketParam param) {
SysPrinterPrintTicketVo vo = sysPrinterService.printTicket(param);
if (vo.getCode() == 0) {
return Result.success();
}
return Result.fail(vo.getMessage());
}
}

View File

@ -0,0 +1,56 @@
package com.niu.core.controller.adminapi.sys;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.Result;
import com.niu.core.service.admin.sys.ISysPrinterTemplateService;
import com.niu.core.service.admin.sys.param.SysPrinterTemplateParam;
import com.niu.core.service.admin.sys.param.SysPrinterTemplateSearchParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 小票打印模板控制器
*/
@RestController
@RequestMapping("adminapi/sys/printer/template")
public class SysPrinterTemplateController {
@Resource
ISysPrinterTemplateService sysPrinterTemplateService;
@GetMapping
public Result<?> templatePageLists(@Validated PageParam pageParam, @Validated SysPrinterTemplateSearchParam searchParam) {
return Result.success(sysPrinterTemplateService.page(pageParam, searchParam));
}
@GetMapping("/list")
public Result<?> templateLists(@Validated SysPrinterTemplateSearchParam searchParam) {
return Result.success(sysPrinterTemplateService.getList(searchParam));
}
@GetMapping("/{id}")
public Result<?> info(@PathVariable Integer id) {
return Result.success(sysPrinterTemplateService.info(id));
}
@PostMapping
public Result<?> add(@Validated @RequestBody SysPrinterTemplateParam addParam) {
sysPrinterTemplateService.add(addParam);
return Result.success();
}
@PutMapping("/{id}")
public Result<?> edit(@PathVariable Integer id, @Validated @RequestBody SysPrinterTemplateParam editParam) {
sysPrinterTemplateService.edit(id, editParam);
return Result.success();
}
@DeleteMapping("/{id}")
public Result<?> del(@PathVariable Integer id) {
sysPrinterTemplateService.del(id);
return Result.success();
}
}

View File

@ -31,7 +31,10 @@ public class MemberAccountController {
* @return
*/
@GetMapping("/account/point")
public Result<?> point(@Validated PageParam pageParam, @Validated AccountPointFlowParam param) {
public Result<?> point(@Validated PageParam pageParam, @Validated AccountPointFlowParam param, @RequestParam(name = "create_time[0]", defaultValue = "") String startTime, @RequestParam(name = "create_time[1]", defaultValue = "") String endTime) {
if (!startTime.isEmpty() && !endTime.isEmpty()) {
param.setCreateTime(new String[]{ startTime, endTime });
}
return Result.success(memberAccountService.pointFlow(pageParam, param));
}
@ -42,7 +45,10 @@ public class MemberAccountController {
* @return
*/
@GetMapping("/account/balance")
public Result<?> balance(@Validated PageParam pageParam, @Validated AccountBalanceFlowParam param) {
public Result<?> balance(@Validated PageParam pageParam, @Validated AccountBalanceFlowParam param, @RequestParam(name = "create_time[0]", defaultValue = "") String startTime, @RequestParam(name = "create_time[1]", defaultValue = "") String endTime) {
if (!startTime.isEmpty() && !endTime.isEmpty()) {
param.setCreateTime(new String[]{ startTime, endTime });
}
return Result.success(memberAccountService.balanceFlow(pageParam, param));
}
@ -53,7 +59,10 @@ public class MemberAccountController {
* @return
*/
@GetMapping("/account/balance_list")
public Result<?> balanceList(@Validated PageParam pageParam, @Validated AccountBalanceListParam param) {
public Result<?> balanceList(@Validated PageParam pageParam, @Validated AccountBalanceListParam param, @RequestParam(name = "create_time[0]", defaultValue = "") String startTime, @RequestParam(name = "create_time[1]", defaultValue = "") String endTime) {
if (!startTime.isEmpty() && !endTime.isEmpty()) {
param.setCreateTime(new String[]{ startTime, endTime });
}
return Result.success(memberAccountService.balanceList(pageParam, param));
}

View File

@ -0,0 +1,32 @@
package com.niu.core.controller.api.sys;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.niu.core.common.domain.Result;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.service.core.poster.ICorePosterService;
import com.niu.core.service.core.poster.param.GetPosterParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 海报控制器
*/
@RestController
@RequestMapping("api/poster")
public class SysPosterController {
@Resource
private ICorePosterService corePosterService;
@GetMapping("")
public Result<?> poster(GetPosterParam param) {
param.setSiteId(RequestUtils.siteId());
param.setChannel(RequestUtils.channel());
return Result.success("", corePosterService.get(param));
}
}

View File

@ -26,9 +26,11 @@ public class SiteGroup implements Serializable {
private String groupDesc;
/** 应用 */
@JsonSerialize(using = BeanJsonSerializer.StringToJsonSerializer.class)
private String app;
/** 插件 */
@JsonSerialize(using = BeanJsonSerializer.StringToJsonSerializer.class)
private String addon;
/** 添加时间 */

View File

@ -0,0 +1,95 @@
package com.niu.core.entity.sys;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印机实体
*/
@Data
public class SysPrinter implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 开发者密钥
*/
private String apikey;
/**
* 设备品牌易联云365飞鹅
*/
private String brand;
/**
* 创建时间
*/
private Long createTime;
/**
* 开发者id
*/
private String openId;
/**
* 纸张宽度
*/
private String printWidth;
/**
* 打印机编号
*/
private String printerCode;
/**
*
*/
@TableId(value = "printer_id", type = IdType.AUTO)
private Integer printerId;
/**
* 打印机秘钥
*/
private String printerKey;
/**
* 打印机名称
*/
private String printerName;
/**
* 站点id
*/
private Integer siteId;
/**
* 状态0关闭1开启
*/
private Integer status;
/**
* 小票打印模板类型多个逗号隔开
*/
private String templateType;
/**
* 触发打印时机
*/
@TableField("`trigger`")
private String trigger;
/**
* 修改时间
*/
private Long updateTime;
/**
* 打印模板数据json格式
*/
private String value;
}

View File

@ -0,0 +1,53 @@
package com.niu.core.entity.sys;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印模板实体
*/
@Data
public class SysPrinterTemplate implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
private Long createTime;
/**
* 站点id
*/
private Integer siteId;
/**
*
*/
@TableId(value = "template_id", type = IdType.AUTO)
private Integer templateId;
/**
* 模板名称
*/
private String templateName;
/**
* 模板类型
*/
private String templateType;
/**
* 修改时间
*/
private Long updateTime;
/**
* 模板数据json格式
*/
private String value;
}

View File

@ -0,0 +1,35 @@
package com.niu.core.enums.sys;
import lombok.Getter;
@Getter
public enum SysPrinterBrandEnum {
NONE("", ""),
YI_LIAN_YUN("yilianyun", "易联云打印机");
private final String brand;
private final String name;
SysPrinterBrandEnum(String brand, String name) {
this.brand = brand;
this.name = name;
}
public static String getNameByBrand(String brand) {
for (SysPrinterBrandEnum value : SysPrinterBrandEnum.values()) {
if (value.getBrand().equals(brand)) {
return value.getName();
}
}
return "";
}
public static SysPrinterBrandEnum getEnumByBrand(String brand) {
for (SysPrinterBrandEnum value : SysPrinterBrandEnum.values()) {
if (value.getBrand().equals(brand)) {
return value;
}
}
return NONE;
}
}

View File

@ -0,0 +1,22 @@
package com.niu.core.enums.sys;
import cn.hutool.json.JSONArray;
import com.alibaba.fastjson2.JSON;
import com.niu.core.common.utils.json.JsonModuleLoader;
public class SysPrinterTypeEnum {
public static JSONArray getType() {
return JsonModuleLoader.build().mergeResultSet("printer/printer.json");
}
public static String getTypeName(String type) {
return getType()
.stream()
.filter(o -> JSON.parseObject(o.toString()).getString("key").equals(type))
.map(o -> JSON.parseObject(o.toString()).getString("title"))
.findFirst()
.orElse("");
}
}

View File

@ -1,7 +1,10 @@
package com.niu.core.event.pay;
import com.niu.core.common.component.context.event.Event;
import com.niu.core.entity.pay.PayTransfer;
import lombok.Data;
@Data
public class TransferSuccessEvent extends Event {
private PayTransfer transfer;
}

View File

@ -5,6 +5,8 @@ import com.niu.core.common.component.context.event.EventResult;
import com.niu.core.common.component.context.listener.CallbackListener;
import lombok.Data;
import java.util.Map;
/**
* 获取海报数据
*/
@ -13,10 +15,15 @@ public abstract class GetPosterDataEventDefiner extends CallbackListener<GetPost
@Data
public static class GetPosterDataEvent extends Event {
private String type;
private Map<String, Object> param;
private String channel;
}
@Data
public static class GetPosterDataResult extends EventResult {
private Map<String, Object> data;
}
public abstract GetPosterDataEventDefiner.GetPosterDataResult handleCallback(GetPosterDataEventDefiner.GetPosterDataEvent event);

View File

@ -0,0 +1,26 @@
package com.niu.core.event.sys;
import cn.hutool.json.JSONObject;
import com.freewayso.image.combiner.ImageCombiner;
import com.niu.core.common.component.context.event.Event;
import lombok.Data;
import java.util.Map;
@Data
public class PosterDrawEvent extends Event {
/**
* 海报绘制对象
*/
private ImageCombiner combiner;
/**
* 绘制项目
*/
private JSONObject poster;
/**
* 海报数据
*/
private Map<String, Object> posterData;
}

View File

@ -0,0 +1,24 @@
package com.niu.core.listener.pay;
import com.niu.core.common.annotation.EventListen;
import com.niu.core.common.component.context.listener.AbstractListener;
import com.niu.core.event.pay.PaySuccessEvent;
import com.niu.core.service.core.site.ICoreSiteAccountService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 支付成功
*/
@EventListen("core")
@Component
public class PaySuccessListener extends AbstractListener {
@Resource
ICoreSiteAccountService coreSiteAccountService;
public void handleEvent(PaySuccessEvent event) {
coreSiteAccountService.addPayLog(event.getPay());
}
}

View File

@ -0,0 +1,24 @@
package com.niu.core.listener.pay;
import com.niu.core.common.annotation.EventListen;
import com.niu.core.common.component.context.listener.AbstractListener;
import com.niu.core.event.refund.RefundSuccessEvent;
import com.niu.core.service.core.site.ICoreSiteAccountService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 退款成功
*/
@EventListen("core")
@Component
public class RefundSuccessListener extends AbstractListener {
@Resource
ICoreSiteAccountService coreSiteAccountService;
public void handleEvent(RefundSuccessEvent event) {
coreSiteAccountService.addRefundLog(event.getRefund());
}
}

View File

@ -0,0 +1,25 @@
package com.niu.core.listener.pay;
import com.niu.core.common.annotation.EventListen;
import com.niu.core.common.component.context.listener.AbstractListener;
import com.niu.core.event.pay.TransferSuccessEvent;
import com.niu.core.event.refund.RefundSuccessEvent;
import com.niu.core.service.core.site.ICoreSiteAccountService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 转账成功
*/
@EventListen("core")
@Component
public class TransferSuccessListener extends AbstractListener {
@Resource
ICoreSiteAccountService coreSiteAccountService;
public void handleEvent(TransferSuccessEvent event) {
coreSiteAccountService.addTransferLog(event.getTransfer());
}
}

View File

@ -11,7 +11,7 @@ import com.niu.core.service.admin.diy.IDiyService;
import com.niu.core.service.admin.diy.param.SetDiyDataParam;
import org.springframework.stereotype.Component;
@EventListen("code")
@EventListen("core")
@Component
public class SiteAddAfterListener extends AbstractListener {

View File

@ -0,0 +1,89 @@
package com.niu.core.listener.sys;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.freewayso.image.combiner.ImageCombiner;
import com.freewayso.image.combiner.element.ImageElement;
import com.freewayso.image.combiner.element.RectangleElement;
import com.freewayso.image.combiner.element.TextElement;
import com.freewayso.image.combiner.enums.BaseLine;
import com.freewayso.image.combiner.enums.LineAlign;
import com.freewayso.image.combiner.enums.ZoomMode;
import com.niu.core.common.annotation.EventListen;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.component.context.listener.AbstractListener;
import com.niu.core.common.utils.image.ImageUtils;
import com.niu.core.event.sys.PosterDrawEvent;
import org.springframework.stereotype.Component;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
@EventListen("core")
@Component
public class PosterDrawListener extends AbstractListener {
public void handleEvent(PosterDrawEvent event) {
JSONObject poster = event.getPoster();
ImageCombiner combiner = event.getCombiner();
Map<String, Object> posterData = event.getPosterData();
String type = poster.getStr("type", "").toLowerCase();
switch (type) {
case "image":
String imgPath = poster.getStr("value", "");
if (imgPath.isEmpty() && !poster.getStr("relate").isEmpty()) {
imgPath = (String) posterData.getOrDefault(poster.getStr("relate"), "");
}
BufferedImage img = ImageUtils.readImage(imgPath, "static/resource/images/diy/crack_figure.png");
ImageElement imgElement = new ImageElement(img, poster.getInt("x"), poster.getInt("y"), poster.getInt("width"), poster.getInt("height"), ZoomMode.Width);
if (poster.getStr("shape", "").equals("circle")) {
imgElement.setRoundCorner(poster.getInt("width"));
}
combiner.addElement(imgElement);
break;
case "text":
String testStr = poster.getStr("value");
if (testStr.isEmpty() && !poster.getStr("relate").isEmpty()) {
testStr = (String) posterData.getOrDefault(poster.getStr("relate"), "");
}
int fontStyle = poster.getBool("weight") ? Font.BOLD : Font.PLAIN;
Font customFont = null;
String defaultFont = "static/font/SourceHanSansCN-Regular.ttf";
File fontFile = new File(WebAppEnvs.get().webRootDownResource, ObjectUtil.defaultIfEmpty(poster.getStr("fontFamily", defaultFont), defaultFont));
try {
customFont = Font.createFont(Font.TRUETYPE_FONT, fontFile);
customFont = customFont.deriveFont(fontStyle, poster.getInt("fontSize"));
} catch (Exception e) {
e.printStackTrace();
}
TextElement text = new TextElement(testStr, fontStyle, poster.getInt("fontSize"), poster.getInt("x"), poster.getInt("y"));
// 设置字体颜色
text.setColor(Color.decode(poster.getStr("fontColor")));
// 设置换行
text.setAutoBreakLine(poster.getInt("width"), poster.getInt("height") / poster.getInt("fontSize"), LineAlign.Left);
if (customFont != null) text.setFont(customFont);
combiner.addElement(text);
break;
case "qrcode":
String qrcodePath = (String) posterData.getOrDefault(poster.getStr("relate"), "static/resource/images/diy/qrcode.png");
BufferedImage qrcode = ImageUtils.readImage(qrcodePath, "static/resource/images/diy/qrcode.png");
ImageElement qrcodeElement = new ImageElement(qrcode, poster.getInt("x"), poster.getInt("y"), poster.getInt("width"), poster.getInt("height"), ZoomMode.Width);
combiner.addElement(qrcodeElement);
break;
case "draw":
RectangleElement rectangle = new RectangleElement(poster.getInt("x"), poster.getInt("y"), poster.getInt("width"), poster.getInt("height"));
rectangle.setColor(Color.decode(poster.getStr("bgColor")));
combiner.addElement(rectangle);
break;
}
}
}

View File

@ -0,0 +1,25 @@
package com.niu.core.listener.sys;
import cn.hutool.core.util.ObjectUtil;
import com.niu.core.common.component.context.SpringContext;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.component.initialize.InitializeProvider;
import com.niu.core.common.component.initialize.annotation.Initializer;
import com.niu.core.service.admin.upgrade.IUpgradeService;
import com.niu.core.service.admin.upgrade.vo.UpgradeTaskVo;
import org.springframework.context.ApplicationContext;
@Initializer("system")
public class SystemRestartListener implements InitializeProvider {
public void init(ApplicationContext applicationContext) throws Exception {
if (WebAppEnvs.get().envType.equals("dev")) {
IUpgradeService upgradeService = SpringContext.bean(IUpgradeService.class);
UpgradeTaskVo task = upgradeService.getUpgradeTask();
if (ObjectUtil.isNotEmpty(task) && ObjectUtil.isNotEmpty(task.getStatus()) && task.getStatus().equals("restarting")) {
task.setStatus("restarted");
upgradeService.setUpgradeTaskCache(task);
}
}
}
}

View File

@ -29,8 +29,7 @@ public class WechatQrcodeListener extends GetQrcodeOfChannelDefiner {
if (event.getOutfile()) {
String filePath = event.getFilePath();
QRCodeUtils.encode(url, WebAppEnvs.get().webRootDownResource + "upload/" + filePath);
result.setPath(filePath);
result.setPath(event.getFilePath() + "/" + QRCodeUtils.encode(url, WebAppEnvs.get().webRootDownResource + filePath));
} else {
ByteArrayOutputStream output = new ByteArrayOutputStream();
QRCodeUtils.encode(url, output);

View File

@ -12,6 +12,4 @@ import java.util.Map;
@Mapper
public interface MemberAccountLogMapper extends MPJBaseMapper<MemberAccountLog> {
Double sumAccountData(Map<String, Object> paramsMap);
}

View File

@ -0,0 +1,12 @@
package com.niu.core.mapper.sys;
import com.github.yulichang.base.MPJBaseMapper;
import com.niu.core.entity.sys.SysPrinter;
import org.apache.ibatis.annotations.Mapper;
/**
* 小票打印机 Mapper
*/
@Mapper
public interface SysPrinterMapper extends MPJBaseMapper<SysPrinter> {
}

View File

@ -0,0 +1,12 @@
package com.niu.core.mapper.sys;
import com.github.yulichang.base.MPJBaseMapper;
import com.niu.core.entity.sys.SysPrinterTemplate;
import org.apache.ibatis.annotations.Mapper;
/**
* 小票打印模板 Mapper
*/
@Mapper
public interface SysPrinterTemplateMapper extends MPJBaseMapper<SysPrinterTemplate> {
}

View File

@ -1,6 +1,7 @@
package com.niu.core.service.admin.addon.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
@ -270,35 +271,11 @@ public class AddonDevelopBuildServiceImpl implements IAddonDevelopBuildService {
try {
FileUtils.copyDirectory(new File(this.addonPath), new File(tempDir));
Path sourceDir = Paths.get(WebAppEnvs.get().webRootDownResource + "temp/" + this.addon + "/");
Path zipFile = Paths.get( WebAppEnvs.get().webRootDownResource + "temp/" + this.addon + ".zip");
String sourceDir = WebAppEnvs.get().webRootDownResource + "temp/" + this.addon;
String zipFile = WebAppEnvs.get().webRootDownResource + "temp/" + this.addon + ".zip";
ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(zipFile));
Files.walk(sourceDir)
.forEach(path -> {
try {
if (!Files.isDirectory(path)) {
Path source = path;
Path target = sourceDir.relativize(source);
ZipEntry zipEntry = new ZipEntry(target.toString());
zs.putNextEntry(zipEntry);
try (InputStream is = Files.newInputStream(source)) {
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
zs.write(buffer, 0, length);
}
}
zs.closeEntry();
}
} catch (IOException e) {
e.printStackTrace();
}
});
FileUtils.deleteDirectory(new File(tempDir));
ZipUtil.zip(sourceDir, zipFile);
FileUtils.deleteDirectory(new File(sourceDir));
} catch (IOException e) {
e.printStackTrace();
}

View File

@ -45,7 +45,7 @@ public class DictServiceImpl implements IDictService {
}
if (ObjectUtil.isNotEmpty(searchParam.getKey())) {
queryWrapper.eq("key", searchParam.getKey());
queryWrapper.eq("`key`", searchParam.getKey());
}
queryWrapper.orderByDesc("id");
@ -84,7 +84,7 @@ public class DictServiceImpl implements IDictService {
public DictInfoVo info(String key) {
SysDict model = dictMapper.selectOne(
new QueryWrapper<SysDict>()
.eq("key", key)
.eq("`key`", key)
.last("limit 1"));
Assert.notNull(model, "数据不存在");

View File

@ -98,20 +98,11 @@ public interface IGenerateService {
*/
List<TableFiledVo> getTableColumn(String tableName);
/**
* 获取模型
* @return
*/
List<String> getModels();
/**
* 获取表字段
* @param model
* @param mapper
* @return
*/
TableFiledVo getModelColumn(String model);
Map<String, Map<String, Object>> getTableColumnByMapper(String mapper);
}

View File

@ -8,6 +8,7 @@ import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -19,6 +20,7 @@ import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.exception.AdminException;
import com.niu.core.common.exception.CommonException;
import com.niu.core.common.loader.pay.BasePay;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.file.FileTools;
import com.niu.core.entity.generator.GenerateColumn;
@ -42,8 +44,10 @@ import com.niu.core.service.core.app.tools.SQLScriptRunnerTools;
import com.niu.core.service.core.generator.CoreGenerateService;
import com.niu.core.service.core.generator.vo.CoreGenerateColumnVo;
import com.niu.core.service.core.generator.vo.CoreGenerateTemplateVo;
import com.niu.core.service.core.generator.vo.MapperInfoVo;
import com.qiniu.storage.ApiUploadV2AbortUpload;
import org.apache.commons.io.IOUtils;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -55,6 +59,8 @@ import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@ -76,8 +82,8 @@ public class GenerateServiceImpl implements IGenerateService {
@Override
public PageResult<GenerateListVo> getPage(PageParam pageParam, GenerateSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit =pageParam.getLimit();
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
MPJQueryWrapper<GenerateTable> queryWrapper = new MPJQueryWrapper<>();
queryWrapper.setAlias("ngt");
@ -92,17 +98,16 @@ public class GenerateServiceImpl implements IGenerateService {
}
if (ObjectUtil.isNotEmpty(searchParam.getAddonName())) {
if(searchParam.getAddonName().equals("2"))
{
if (searchParam.getAddonName().equals("2")) {
queryWrapper.eq("ngt.addon_name", "");
}else{
} else {
queryWrapper.like("ngt.addon_name", searchParam.getAddonName());
}
}
queryWrapper.orderByDesc("ngt.create_time");
IPage<GenerateListVo> iPage = generateTableMapper.selectJoinPage(new Page<>(page, limit),GenerateListVo.class, queryWrapper);
IPage<GenerateListVo> iPage = generateTableMapper.selectJoinPage(new Page<>(page, limit), GenerateListVo.class, queryWrapper);
return PageResult.build(iPage);
}
@ -110,100 +115,86 @@ public class GenerateServiceImpl implements IGenerateService {
public GenerateDetailVo getInfo(Integer id) {
GenerateTable generateTable = generateTableMapper.selectById(id);
if(ObjectUtil.isEmpty(generateTable)) throw new AdminException("生成表不存在");
if (ObjectUtil.isEmpty(generateTable)) throw new AdminException("生成表不存在");
GenerateDetailVo vo = new GenerateDetailVo();
BeanUtils.copyProperties(generateTable, vo);
if(vo.getOrderType() != 0)
{
if (vo.getOrderType() != 0) {
GenerateColumn orderColumn = generateColumnMapper.selectOne(new QueryWrapper<GenerateColumn>().eq("table_id", id).eq("is_order", 1));
if(ObjectUtil.isNotEmpty(orderColumn))
{
if (ObjectUtil.isNotEmpty(orderColumn)) {
vo.setOrderColumnName(orderColumn.getColumnName());
}else{
} else {
vo.setOrderColumnName("");
}
}
GenerateColumn deleteColumn = generateColumnMapper.selectOne(new QueryWrapper<GenerateColumn>().eq("table_id", id).eq("is_delete", 1));
if(ObjectUtil.isNotEmpty(deleteColumn))
{
if (ObjectUtil.isNotEmpty(deleteColumn)) {
vo.setDeleteColumnName(deleteColumn.getColumnName());
vo.setIsDelete(1);
}else{
} else {
vo.setDeleteColumnName("");
vo.setIsDelete(0);
}
List<GenerateColumn> columnList = generateColumnMapper.selectList(new QueryWrapper<GenerateColumn>().eq("table_id", id));
if( ObjectUtil.isNotEmpty(columnList))
{
if (ObjectUtil.isNotEmpty(columnList)) {
List<GenerateColumnVo> columnVoList = new ArrayList<>();
for (GenerateColumn column : columnList) {
GenerateColumnVo generateColumnVo = new GenerateColumnVo();
BeanUtils.copyProperties(column, generateColumnVo);
if(column.getViewType().equals("number"))
{
if(!column.getValidateType().isEmpty())
{
if (column.getViewType().equals("number")) {
if (!column.getValidateType().isEmpty()) {
if (column.getValidateType().startsWith("[")) {
JSONArray numValidate = JSONUtil.parseArray(column.getValidateType());
if(numValidate.get(0).toString().equals("between"))
{
if (numValidate.get(0).toString().equals("between")) {
generateColumnVo.setViewMax(JSONUtil.parseArray(numValidate.get(1)).get(1).toString());
generateColumnVo.setViewMin(JSONUtil.parseArray(numValidate.get(1)).get(0).toString());
}else if(numValidate.get(0).toString().equals("max"))
{
} else if (numValidate.get(0).toString().equals("max")) {
generateColumnVo.setViewMax(JSONUtil.parseArray(numValidate.get(1)).get(0).toString());
}else if(numValidate.get(0).toString().equals("min"))
{
} else if (numValidate.get(0).toString().equals("min")) {
generateColumnVo.setViewMin(JSONUtil.parseArray(numValidate.get(1)).get(0).toString());
}else{
} else {
generateColumnVo.setViewMax("100");
generateColumnVo.setViewMin("0");
}
}else{
} else {
generateColumnVo.setViewMax("100");
generateColumnVo.setViewMin("0");
}
}else{
} else {
generateColumnVo.setViewMax("100");
generateColumnVo.setViewMin("0");
}
}else{
} else {
generateColumnVo.setViewMax("");
generateColumnVo.setViewMin("");
}
if(!column.getValidateType().isEmpty())
{
if (!column.getValidateType().isEmpty()) {
if (column.getValidateType().startsWith("[")) {
JSONArray num1Validate = JSONUtil.parseArray(column.getValidateType());
if(num1Validate.get(0).toString().equals("between"))
{
if (num1Validate.get(0).toString().equals("between")) {
generateColumnVo.setMaxNumber(JSONUtil.parseArray(num1Validate.get(1)).get(1).toString());
generateColumnVo.setMinNumber(JSONUtil.parseArray(num1Validate.get(1)).get(0).toString());
}else if(num1Validate.get(0).toString().equals("max"))
{
} else if (num1Validate.get(0).toString().equals("max")) {
generateColumnVo.setMaxNumber(JSONUtil.parseArray(num1Validate.get(1)).get(0).toString());
}else if(num1Validate.get(0).toString().equals("min"))
{
} else if (num1Validate.get(0).toString().equals("min")) {
generateColumnVo.setMinNumber(JSONUtil.parseArray(num1Validate.get(1)).get(0).toString());
}else{
} else {
generateColumnVo.setMaxNumber("120");
generateColumnVo.setMinNumber("1");
}
}else{
} else {
generateColumnVo.setMaxNumber("120");
generateColumnVo.setMinNumber("1");
}
}else{
} else {
generateColumnVo.setMaxNumber("120");
generateColumnVo.setMinNumber("1");
}
if(!column.getModel().isEmpty())
{
if (!column.getModel().isEmpty()) {
generateColumnVo.setSelectType(2);
}else{
} else {
generateColumnVo.setSelectType(1);
}
columnVoList.add(generateColumnVo);
@ -219,13 +210,13 @@ public class GenerateServiceImpl implements IGenerateService {
String sql = "SHOW TABLE STATUS WHERE 1=1 ";
String tablePrefix = GlobalConfig.tablePrefix;
if(!generateParam.getTableName().isEmpty()){
if (!generateParam.getTableName().isEmpty()) {
sql += " AND Name = '" + generateParam.getTableName() + "'";
}
List<Map<String, Object>> listData = jdbcTemplate.queryForList(sql);
if(ObjectUtil.isEmpty(listData)) throw new AdminException("数据表不存在");
if (ObjectUtil.isEmpty(listData)) throw new AdminException("数据表不存在");
Map<String, Object> table = listData.get(0);
if(ObjectUtil.isEmpty(table)) throw new AdminException("数据表不存在");
if (ObjectUtil.isEmpty(table)) throw new AdminException("数据表不存在");
String tableName = table.get("Name").toString().substring(tablePrefix.length());
//添加生成表数据
@ -238,7 +229,7 @@ public class GenerateServiceImpl implements IGenerateService {
generateTableMapper.insert(generateTable);
//添加生成字段数据
List<Map<String, Object>> columns = jdbcTemplate.queryForList("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = (SELECT DATABASE()) and TABLE_NAME='" + tablePrefix + tableName+"'");
List<Map<String, Object>> columns = jdbcTemplate.queryForList("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = (SELECT DATABASE()) and TABLE_NAME='" + tablePrefix + tableName + "'");
Integer id = generateTable.getId();
List<GenerateColumn> list = new ArrayList<>();
for (Map<String, Object> column : columns) {
@ -246,21 +237,21 @@ public class GenerateServiceImpl implements IGenerateService {
generateColumn.setIsRequired(0);
String[] defaultColumn = {"id", "create_time", "update_time"};
if(column.get("IS_NULLABLE").toString().equals("NO")&& !column.get("COLUMN_KEY").equals("PRI") && Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString())){
if (column.get("IS_NULLABLE").toString().equals("NO") && !column.get("COLUMN_KEY").equals("PRI") && Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString())) {
generateColumn.setIsRequired(1);
}
generateColumn.setTableId(id);
generateColumn.setColumnName(column.get("COLUMN_NAME").toString());
generateColumn.setColumnType(getDbFieldType(column.get("DATA_TYPE").toString()));
if(generateColumn.getColumnType().equals("Integer") && generateColumn.getColumnName().contains("time")){
if (generateColumn.getColumnType().equals("Integer") && generateColumn.getColumnName().contains("time")) {
generateColumn.setColumnType("Long");
}
generateColumn.setColumnComment(column.get("COLUMN_COMMENT").toString());
generateColumn.setIsPk(column.get("COLUMN_KEY").equals("PRI")?1:0);
generateColumn.setIsInsert(Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString())?0:1);
generateColumn.setIsUpdate(Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString())?0:1);
generateColumn.setIsLists(Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString())?0:1);
generateColumn.setIsPk(column.get("COLUMN_KEY").equals("PRI") ? 1 : 0);
generateColumn.setIsInsert(Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString()) ? 0 : 1);
generateColumn.setIsUpdate(Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString()) ? 0 : 1);
generateColumn.setIsLists(Arrays.asList(defaultColumn).contains(column.get("COLUMN_NAME").toString()) ? 0 : 1);
generateColumn.setIsDelete(0);
generateColumn.setQueryType("=");
generateColumn.setViewType("input");
@ -299,7 +290,7 @@ public class GenerateServiceImpl implements IGenerateService {
JSONArray columns = JSONUtil.parseArray(generateParam.getTableColumn());
List<GenerateColumn> list = new ArrayList<>();
for(int i = 0; i < columns.size(); i++){
for (int i = 0; i < columns.size(); i++) {
GenerateColumn generateColumn = new GenerateColumn();
JSONObject column = columns.getJSONObject(i);
generateColumn.setTableId(id);
@ -326,22 +317,18 @@ public class GenerateServiceImpl implements IGenerateService {
generateColumn.setValidateType(ObjectUtil.isEmpty(column.getStr("validate_type")) ? "" : column.getStr("validate_type"));
//传入字段rule暂时不知含义待定
if(generateParam.getIsDelete() == 1)
{
if(column.getStr("column_name").equals(generateParam.getDeleteColumnName()))
{
if (generateParam.getIsDelete() == 1) {
if (column.getStr("column_name").equals(generateParam.getDeleteColumnName())) {
generateColumn.setIsDelete(1);
}
}
if(generateParam.getOrderType() != 0)
{
if(column.getStr("column_name").equals(generateParam.getOrderColumnName()))
{
if (generateParam.getOrderType() != 0) {
if (column.getStr("column_name").equals(generateParam.getOrderColumnName())) {
generateColumn.setIsOrder(1);
}
}
if(ObjectUtil.isNotEmpty(column.getStr("validate_type")) && !column.getStr("view_type").equals("number")) {
if (ObjectUtil.isNotEmpty(column.getStr("validate_type")) && !column.getStr("view_type").equals("number")) {
if (column.getStr("validate_type").equals("between")) {
JSONArray jsonArray = new JSONArray();
jsonArray.add("between");
@ -360,14 +347,13 @@ public class GenerateServiceImpl implements IGenerateService {
}
}
if(column.getStr("view_type").equals("number")){
if (column.getStr("view_type").equals("number")) {
JSONArray numJsonArray = new JSONArray();
numJsonArray.add("between");
numJsonArray.add(new String[]{column.getStr("view_min"), column.getStr("view_max")});
generateColumn.setValidateType(numJsonArray.toString());
}
if(ObjectUtil.isNotEmpty(column.getStr("model")))
{
if (ObjectUtil.isNotEmpty(column.getStr("model"))) {
generateColumn.setDictType("");
}
list.add(generateColumn);
@ -391,7 +377,7 @@ public class GenerateServiceImpl implements IGenerateService {
GenerateTable generateTable = generateTableMapper.selectById(generateCodeParam.getId());
List<GenerateColumn> columnList = generateColumnMapper.selectList(new QueryWrapper<GenerateColumn>().eq("table_id", generateCodeParam.getId()));
CoreGenerateService coreGenerateService = new CoreGenerateService();
List<CoreGenerateTemplateVo> list =coreGenerateService.generateCode(generateTable, columnList);
List<CoreGenerateTemplateVo> list = coreGenerateService.generateCode(generateTable, columnList);
// 下载
if (generateCodeParam.getGenerateType().equals("2")) {
@ -424,7 +410,7 @@ public class GenerateServiceImpl implements IGenerateService {
GenerateTable generateTable = generateTableMapper.selectById(id);
List<GenerateColumn> list = generateColumnMapper.selectList(new QueryWrapper<GenerateColumn>().eq("table_id", id));
CoreGenerateService coreGenerateService = new CoreGenerateService();
List<CoreGenerateTemplateVo> columnList =coreGenerateService.generateCode(generateTable, list);
List<CoreGenerateTemplateVo> columnList = coreGenerateService.generateCode(generateTable, list);
List<GeneratePreviewVo> voList = new ArrayList<>();
for (CoreGenerateTemplateVo coreGenerateTemplateVo : columnList) {
GeneratePreviewVo vo = new GeneratePreviewVo();
@ -448,17 +434,17 @@ public class GenerateServiceImpl implements IGenerateService {
field = entry.getKey();
}
}
if(field.equals("")){
if (field.equals("")) {
field = "String";
}
return field;
}
@Override
public String getDbType(String columnType) {
if (StrUtil.contains(columnType, "(")) {
return StrUtil.subAfter(columnType, "(", true);
}
else {
} else {
return columnType;
}
}
@ -467,11 +453,11 @@ public class GenerateServiceImpl implements IGenerateService {
public List<Map<String, Object>> tableList(String name, String comment) {
String sql = "SHOW TABLE STATUS WHERE 1=1 ";
if(!(name == null)){
sql += " AND Name like '%" + name + "%'";
if (!(name == null)) {
sql += " AND Name like '%" + name + "%'";
}
if(!(comment == null)){
sql += " AND comment like '%" + comment + "%'";
if (!(comment == null)) {
sql += " AND comment like '%" + comment + "%'";
}
List<Map<String, Object>> listData = jdbcTemplate.queryForList(sql);
return listData;
@ -487,13 +473,27 @@ public class GenerateServiceImpl implements IGenerateService {
return null;
}
/**
* 获取表字段
*
* @param mapper
* @return
*/
@Override
public List<String> getModels() {
return null;
}
public Map<String, Map<String, Object>> getTableColumnByMapper(String mapper) {
MapperInfoVo mapperInfo = CoreGenerateService.getMapperInfo(mapper);
@Override
public TableFiledVo getModelColumn(String model) {
return null;
List<Map<String, Object>> columns = jdbcTemplate.queryForList("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = (SELECT DATABASE()) and TABLE_NAME='" + GlobalConfig.tablePrefix + mapperInfo.getTableName() + "'");
Map<String, Map<String, Object>> tableColumn = new HashMap<>();
for (Map<String, Object> column : columns) {
Map<String, Object> item = new HashMap<>();
item.put("name", column.get("COLUMN_NAME"));
item.put("comment", column.get("COLUMN_COMMENT"));
item.put("default", column.get("COLUMN_DEFAULT"));
item.put("primary", column.get("COLUMN_KEY").equals("PRI"));
tableColumn.put((String) column.get("COLUMN_NAME"), item);
}
return tableColumn;
}
}

View File

@ -29,6 +29,7 @@ import com.niu.core.service.admin.site.ISiteGroupService;
import com.niu.core.service.admin.site.vo.SiteGroupListVo;
import com.niu.core.service.core.addon.ICoreAddonService;
import com.niu.core.service.core.addon.vo.InstallAddonListVo;
import com.niu.core.service.core.site.ICoreSiteService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@ -63,6 +64,9 @@ public class SiteGroupServiceImpl implements ISiteGroupService {
ISiteService siteService;
@Resource
ICoreSiteService coreSiteService;
@Resource
private void setSiteService(@Lazy ISiteService siteService) {
this.siteService = siteService;
@ -207,6 +211,7 @@ public class SiteGroupServiceImpl implements ISiteGroupService {
for (Site site : siteList) {
siteService.siteAddonChange(site, model);
}
coreSiteService.clearSiteCache();
}
}
}

View File

@ -9,13 +9,13 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJQueryWrapper;
import com.google.gson.JsonArray;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.exception.CommonException;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.crypto.PasswordEncipher;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.entity.addon.Addon;
import com.niu.core.entity.site.Site;
import com.niu.core.entity.site.SiteGroup;
@ -31,8 +31,11 @@ import com.niu.core.mapper.site.SiteGroupMapper;
import com.niu.core.mapper.site.SiteMapper;
import com.niu.core.mapper.sys.SysUserRoleMapper;
import com.niu.core.service.admin.site.ISiteGroupService;
import com.niu.core.service.admin.site.param.*;
import com.niu.core.service.admin.site.ISiteService;
import com.niu.core.service.admin.site.param.SiteAddParam;
import com.niu.core.service.admin.site.param.SiteEditParam;
import com.niu.core.service.admin.site.param.SiteSearchParam;
import com.niu.core.service.admin.site.param.SiteUserParam;
import com.niu.core.service.admin.site.vo.SiteAdminVo;
import com.niu.core.service.admin.site.vo.SiteInfoVo;
import com.niu.core.service.admin.site.vo.SiteListVo;
@ -47,8 +50,12 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
@ -57,10 +64,14 @@ import java.util.*;
@Service
public class SiteServiceImpl implements ISiteService {
/** 站点tag */
/**
* 站点tag
*/
public static String cacheTagName = CacheTagEnum.SITE_CASH.getTagName();
/** 是否使用缓存 */
/**
* 是否使用缓存
*/
public static final boolean useCache = true;
@Resource
@ -95,14 +106,15 @@ public class SiteServiceImpl implements ISiteService {
/**
* 站点列表
* @param pageParam 分页参数
*
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<SiteListVo>
*/
@Override
public PageResult<SiteListVo> list(PageParam pageParam, SiteSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit =pageParam.getLimit();
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
//查询条件判断组装
@ -129,17 +141,14 @@ public class SiteServiceImpl implements ISiteService {
if (ObjectUtil.isNotEmpty(searchParam.getCreateTime())) {
String[] createTime = searchParam.getCreateTime();
Long startTime = (createTime[0] == null) ? 0: DateUtils.StringToTimestamp(createTime[0]);
Long startTime = (createTime[0] == null) ? 0 : DateUtils.StringToTimestamp(createTime[0]);
System.out.println(startTime);
Long endTime = (createTime[1] == null) ? 0: DateUtils.StringToTimestamp(createTime[1]);
if(startTime > 0 && endTime > 0)
{
Long endTime = (createTime[1] == null) ? 0 : DateUtils.StringToTimestamp(createTime[1]);
if (startTime > 0 && endTime > 0) {
queryWrapper.between("create_time", startTime, endTime);
}else if (startTime > 0 && endTime == 0)
{
} else if (startTime > 0 && endTime == 0) {
queryWrapper.ge("create_time", startTime);
}else if (startTime == 0 && endTime > 0)
{
} else if (startTime == 0 && endTime > 0) {
queryWrapper.le("create_time", startTime);
}
}
@ -147,17 +156,14 @@ public class SiteServiceImpl implements ISiteService {
if (ObjectUtil.isNotEmpty(searchParam.getExpireTime())) {
String[] expireTime = searchParam.getExpireTime();
Long startTime = (expireTime[0] == null) ? 0: DateUtils.StringToTimestamp(expireTime[0]);
Long startTime = (expireTime[0] == null) ? 0 : DateUtils.StringToTimestamp(expireTime[0]);
System.out.println(startTime);
Long endTime = (expireTime[1] == null) ? 0: DateUtils.StringToTimestamp(expireTime[1]);
if(startTime > 0 && endTime > 0)
{
Long endTime = (expireTime[1] == null) ? 0 : DateUtils.StringToTimestamp(expireTime[1]);
if (startTime > 0 && endTime > 0) {
queryWrapper.between("expire_time", startTime, endTime);
}else if (startTime > 0 && endTime == 0)
{
} else if (startTime > 0 && endTime == 0) {
queryWrapper.ge("expire_time", startTime);
}else if (startTime == 0 && endTime > 0)
{
} else if (startTime == 0 && endTime > 0) {
queryWrapper.le("expire_time", startTime);
}
}
@ -177,7 +183,7 @@ public class SiteServiceImpl implements ISiteService {
userRoleMPJQueryWrapper.eq("nsur.is_admin", 1);
userRoleMPJQueryWrapper.eq("nsur.site_id", item.getSiteId());
vo.setAdmin(sysUserRoleMapper.selectJoinOne(SiteAdminVo.class, userRoleMPJQueryWrapper));
SiteGroup siteGroup=siteGroupMapper.selectById(item.getGroupId());
SiteGroup siteGroup = siteGroupMapper.selectById(item.getGroupId());
vo.setGroupName(siteGroup.getGroupName());
list.add(vo);
}
@ -186,24 +192,26 @@ public class SiteServiceImpl implements ISiteService {
/**
* 站点详情
*
* @param id 主键
* @return SiteInfoVo
*/
@Override
public SiteInfoVo info(Integer id) {
SiteInfoVo siteInfoVo=iCoreSiteService.getSiteCache(id);
SiteInfoVo siteInfoVo = iCoreSiteService.getSiteCache(id);
return siteInfoVo;
}
/**
* 站点添加
*
* @param addParam 参数
*/
@Transactional
@Override
public void add(SiteAddParam addParam) {
SiteGroup siteGroup=siteGroupService.info(addParam.getGroupId());
if(ObjectUtil.isNull(siteGroup) || ObjectUtil.isEmpty(siteGroup)){
SiteGroup siteGroup = siteGroupService.info(addParam.getGroupId());
if (ObjectUtil.isNull(siteGroup) || ObjectUtil.isEmpty(siteGroup)) {
throw new CommonException("SITE_GROUP_NOT_EXIST");
}
Site model = new Site();
@ -216,10 +224,10 @@ public class SiteServiceImpl implements ISiteService {
model.setAddons("");
model.setSiteDomain(addParam.getSiteDomain());
siteMapper.insert(model);
Integer siteId=model.getSiteId();
if(ObjectUtil.isNull(addParam.getUid()) || addParam.getUid()==0){
Integer siteId = model.getSiteId();
if (ObjectUtil.isNull(addParam.getUid()) || addParam.getUid() == 0) {
//添加用户
SiteUserParam siteUserParam=new SiteUserParam();
SiteUserParam siteUserParam = new SiteUserParam();
siteUserParam.setUsername(addParam.getUsername());
siteUserParam.setHeadImg("");
siteUserParam.setStatus(1);
@ -227,8 +235,8 @@ public class SiteServiceImpl implements ISiteService {
siteUserParam.setPassword(PasswordEncipher.encode(addParam.getPassword()));
siteUserParam.setIsAdmin(1);
sysUserService.addSiteUser(siteUserParam, siteId);
}else{
SysUserRoleParam sysUserRoleParam=new SysUserRoleParam();
} else {
SysUserRoleParam sysUserRoleParam = new SysUserRoleParam();
sysUserRoleParam.setUid(addParam.getUid());
sysUserRoleParam.setRoleIds(new JsonArray().toString());
sysUserRoleParam.setIsAdmin(1);
@ -255,28 +263,27 @@ public class SiteServiceImpl implements ISiteService {
public void edit(Integer id, SiteEditParam editParam) {
Site model = siteMapper.selectOne(
new QueryWrapper<Site>()
.eq("site_id", id)
.last("limit 1"));
.eq("site_id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
if(ObjectUtil.isNotNull(editParam.getGroupId()) && ObjectUtil.isNotEmpty(editParam.getGroupId()) && editParam.getGroupId()!=model.getGroupId()){
if (ObjectUtil.isNotNull(editParam.getGroupId()) && ObjectUtil.isNotEmpty(editParam.getGroupId()) && editParam.getGroupId() != model.getGroupId()) {
model.setGroupId(editParam.getGroupId());
}
if(ObjectUtil.isNotNull(editParam.getSiteName()) && ObjectUtil.isNotEmpty(editParam.getSiteName())){
if (ObjectUtil.isNotNull(editParam.getSiteName()) && ObjectUtil.isNotEmpty(editParam.getSiteName())) {
model.setSiteName(editParam.getSiteName());
}
SiteGroup oldSiteGroup=siteGroupService.info(model.getGroupId());
SiteGroup oldSiteGroup = siteGroupService.info(model.getGroupId());
JSONArray initallJsonArray=new JSONArray();
if(ObjectUtil.isNull(model.getInitalledAddon()) || ObjectUtil.isEmpty(model.getInitalledAddon())){
JSONArray initallJsonArray = new JSONArray();
if (ObjectUtil.isNull(model.getInitalledAddon()) || ObjectUtil.isEmpty(model.getInitalledAddon())) {
initallJsonArray.addAll(JSONUtil.parseArray(oldSiteGroup.getApp()));
initallJsonArray.addAll(JSONUtil.parseArray(oldSiteGroup.getAddon()));
}
SiteGroup siteGroup=siteGroupService.info(editParam.getGroupId());
if(ObjectUtil.isNull(siteGroup) || ObjectUtil.isEmpty(siteGroup)){
SiteGroup siteGroup = siteGroupService.info(editParam.getGroupId());
if (ObjectUtil.isNull(siteGroup) || ObjectUtil.isEmpty(siteGroup)) {
throw new CommonException("SITE_GROUP_NOT_EXIST");
}
initallJsonArray.addAll(JSONUtil.parseArray(siteGroup.getApp()));
@ -285,9 +292,11 @@ public class SiteServiceImpl implements ISiteService {
model.setInitalledAddon(JSONUtil.toJsonStr(initallJsonArray));
model.setSiteDomain(editParam.getSiteDomain());
model.setExpireTime(new DateTime(editParam.getExpireTime()).getTime() / 1000);
model.setStatus(model.getExpireTime()>DateUtils.currTime()?SiteStatusEnum.ON.getCode():SiteStatusEnum.EXPIRE.getCode());
model.setStatus(model.getExpireTime() > DateUtils.currTime() ? SiteStatusEnum.ON.getCode() : SiteStatusEnum.EXPIRE.getCode());
siteMapper.updateById(model);
coreSiteService.clearSiteCache();
SiteEditAfterEvent event = new SiteEditAfterEvent();
event.setSiteId(model.getSiteId());
event.addAppSign("core");
@ -299,6 +308,7 @@ public class SiteServiceImpl implements ISiteService {
/**
* 站点删除
*
* @param id 主键ID
*/
@Transactional
@ -306,8 +316,8 @@ public class SiteServiceImpl implements ISiteService {
public void del(Integer id) {
Site model = siteMapper.selectOne(
new QueryWrapper<Site>()
.eq("site_id", id)
.last("limit 1"));
.eq("site_id", id)
.last("limit 1"));
Assert.notNull(model, "数据不存在!");
model.setStatus(SiteStatusEnum.DELETE.getCode());
@ -339,16 +349,16 @@ public class SiteServiceImpl implements ISiteService {
*/
@Override
public Map<String, List<String>> getSiteApiList(Integer siteId, Integer status) {
SiteInfoVo siteInfoVo= this.info(siteId);
Map<String, List<String>> siteApi=new HashMap<>();
if(ObjectUtil.isNull(siteInfoVo)){
SiteInfoVo siteInfoVo = this.info(siteId);
Map<String, List<String>> siteApi = new HashMap<>();
if (ObjectUtil.isNull(siteInfoVo)) {
return siteApi;
}
String appType=siteInfoVo.getAppType();
if(appType.equals(AppTypeEnum.ADMIN.getName())){
String appType = siteInfoVo.getAppType();
if (appType.equals(AppTypeEnum.ADMIN.getName())) {
return sysMenuService.getAllApiList(appType, status);
}else{
List<String> addonKeys= iCoreSiteService.getAddonKeysBySiteId(siteId);
} else {
List<String> addonKeys = iCoreSiteService.getAddonKeysBySiteId(siteId);
return sysMenuService.getApiListBySystem(appType, addonKeys);
}
}
@ -361,20 +371,17 @@ public class SiteServiceImpl implements ISiteService {
*/
@Override
public Integer getSiteCountByCondition(SiteSearchParam siteSearchParam) {
QueryWrapper<Site> queryWrapper=new QueryWrapper<>();
QueryWrapper<Site> queryWrapper = new QueryWrapper<>();
if (ObjectUtil.isNotEmpty(siteSearchParam.getCreateTime())) {
String[] createTime = siteSearchParam.getCreateTime();
Long startTime = (createTime[0] == null) ? 0: DateUtils.StringToTimestamp(createTime[0]);
Long endTime = (createTime[1] == null) ? 0: DateUtils.StringToTimestamp(createTime[1]);
if(startTime > 0 && endTime > 0)
{
Long startTime = (createTime[0] == null) ? 0 : DateUtils.StringToTimestamp(createTime[0]);
Long endTime = (createTime[1] == null) ? 0 : DateUtils.StringToTimestamp(createTime[1]);
if (startTime > 0 && endTime > 0) {
queryWrapper.between("create_time", startTime, endTime);
}else if (startTime > 0 && endTime == 0)
{
} else if (startTime > 0 && endTime == 0) {
queryWrapper.ge("create_time", startTime);
}else if (startTime == 0 && endTime > 0)
{
} else if (startTime == 0 && endTime > 0) {
queryWrapper.le("create_time", startTime);
}
}
@ -394,25 +401,23 @@ public class SiteServiceImpl implements ISiteService {
if (ObjectUtil.isNotEmpty(siteSearchParam.getExpireTime())) {
String[] expireTime = siteSearchParam.getExpireTime();
Long startTime = (expireTime[0] == null) ? 0: DateUtils.StringToTimestamp(expireTime[0]);
Long endTime = (expireTime[1] == null) ? 0: DateUtils.StringToTimestamp(expireTime[1]);
if(startTime > 0 && endTime > 0)
{
Long startTime = (expireTime[0] == null) ? 0 : DateUtils.StringToTimestamp(expireTime[0]);
Long endTime = (expireTime[1] == null) ? 0 : DateUtils.StringToTimestamp(expireTime[1]);
if (startTime > 0 && endTime > 0) {
queryWrapper.between("expire_time", startTime, endTime);
}else if (startTime > 0 && endTime == 0)
{
} else if (startTime > 0 && endTime == 0) {
queryWrapper.ge("expire_time", startTime);
}else if (startTime == 0 && endTime > 0)
{
} else if (startTime == 0 && endTime > 0) {
queryWrapper.le("expire_time", startTime);
}
}
Long siteCount=siteMapper.selectCount(queryWrapper);
Long siteCount = siteMapper.selectCount(queryWrapper);
return siteCount.intValue();
}
/**
* 获取站点的插件
*
* @return
*/
public List<Addon> getSiteAddons() {

View File

@ -0,0 +1,74 @@
package com.niu.core.service.admin.sys;
import cn.hutool.json.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.sys.param.SysPrinterModifyStatusParam;
import com.niu.core.service.admin.sys.param.SysPrinterParam;
import com.niu.core.service.admin.sys.param.SysPrinterSearchParam;
import com.niu.core.service.admin.sys.vo.SysPrinterInfoVo;
import com.niu.core.service.admin.sys.vo.SysPrinterListVo;
import com.niu.core.service.core.sys.param.SysPrinterPrintTicketParam;
import com.niu.core.service.core.sys.vo.SysPrinterPrintTicketVo;
import java.util.List;
/**
* 小票打印机服务接口
*/
public interface ISysPrinterService {
/**
* 小票打印机列表
*
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<SysPrinterListVo>
*/
PageResult<SysPrinterListVo> page(PageParam pageParam, SysPrinterSearchParam searchParam);
List<SysPrinterListVo> getList(SysPrinterSearchParam param);
/**
* 小票打印机详情
*
* @param id 主键ID
* @return SysPrinterInfoVo
*/
SysPrinterInfoVo info(Integer id);
/**
* 小票打印机添加
*
* @param addParam 添加参数
*/
void add(SysPrinterParam addParam);
/**
* 小票打印机编辑
*
* @param id 主键
* @param editParam 编辑参数
*/
void edit(Integer id, SysPrinterParam editParam);
/**
* 小票打印机删除
*
* @param id 主键ID
*/
void del(Integer id);
void modifyStatus(SysPrinterModifyStatusParam param);
String refreshToken(Integer id);
void testPrint(Integer id);
JSON getType();
JSONObject getBrand();
SysPrinterPrintTicketVo printTicket(SysPrinterPrintTicketParam param);
}

View File

@ -0,0 +1,58 @@
package com.niu.core.service.admin.sys;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.service.admin.sys.param.SysPrinterTemplateParam;
import com.niu.core.service.admin.sys.param.SysPrinterTemplateSearchParam;
import com.niu.core.service.admin.sys.vo.SysPrinterTemplateInfoVo;
import com.niu.core.service.admin.sys.vo.SysPrinterTemplateListVo;
import java.util.List;
/**
* 小票打印模板服务接口
*/
public interface ISysPrinterTemplateService {
/**
* 小票打印模板列表
*
* @param pageParam 分页参数
* @param searchParam 搜索参数
* @return PageResult<SysPrinterTemplateListVo>
*/
PageResult<SysPrinterTemplateListVo> page(PageParam pageParam, SysPrinterTemplateSearchParam searchParam);
List<SysPrinterTemplateListVo> getList(SysPrinterTemplateSearchParam searchParam);
/**
* 小票打印模板详情
*
* @param id 主键ID
* @return SysPrinterTemplateInfoVo
*/
SysPrinterTemplateInfoVo info(Integer id);
/**
* 小票打印模板添加
*
* @param addParam 添加参数
*/
void add(SysPrinterTemplateParam addParam);
/**
* 小票打印模板编辑
*
* @param id 主键
* @param editParam 编辑参数
*/
void edit(Integer id, SysPrinterTemplateParam editParam);
/**
* 小票打印模板删除
*
* @param id 主键ID
*/
void del(Integer id);
}

View File

@ -0,0 +1,279 @@
package com.niu.core.service.admin.sys.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.entity.sys.SysPrinter;
import com.niu.core.enums.sys.SysPrinterBrandEnum;
import com.niu.core.enums.sys.SysPrinterTypeEnum;
import com.niu.core.mapper.sys.SysPrinterMapper;
import com.niu.core.service.admin.sys.ISysPrinterService;
import com.niu.core.service.admin.sys.param.SysPrinterModifyStatusParam;
import com.niu.core.service.admin.sys.param.SysPrinterParam;
import com.niu.core.service.admin.sys.param.SysPrinterSearchParam;
import com.niu.core.service.admin.sys.vo.SysPrinterInfoVo;
import com.niu.core.service.admin.sys.vo.SysPrinterListVo;
import com.niu.core.service.core.sys.ICorePrinterService;
import com.niu.core.service.core.sys.param.SysPrinterAddPrinterYlyParam;
import com.niu.core.service.core.sys.param.SysPrinterPrintTicketParam;
import com.niu.core.service.core.sys.vo.SysPrinterPrintTicketVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
/**
* 小票打印机实现
*/
@Service
@RequiredArgsConstructor
public class SysPrinterServiceImpl implements ISysPrinterService {
private final SysPrinterMapper sysPrinterMapper;
private final ICorePrinterService corePrinterService;
@Override
public PageResult<SysPrinterListVo> page(PageParam pageParam, SysPrinterSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
QueryWrapper<SysPrinter> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("site_id", RequestUtils.siteId())
.orderByDesc("create_time");
if (ObjectUtil.isNotEmpty(searchParam.getPrinterName())) {
queryWrapper.like("printer_name", searchParam.getPrinterName());
}
IPage<SysPrinter> iPage = sysPrinterMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<SysPrinterListVo> list = new LinkedList<>();
for (SysPrinter item : iPage.getRecords()) {
SysPrinterListVo vo = new SysPrinterListVo();
BeanUtils.copyProperties(item, vo);
vo.setBrandName(SysPrinterBrandEnum.getNameByBrand(item.getBrand()));
vo.setTrigger(JSONArray.parseArray(item.getTrigger(), String.class));
list.add(vo);
}
return PageResult.build(page, limit, iPage.getTotal()).setData(list);
}
@Override
public List<SysPrinterListVo> getList(SysPrinterSearchParam param) {
QueryWrapper<SysPrinter> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("site_id", RequestUtils.siteId())
.orderByDesc("create_time")
.select("printer_id, apikey, brand, create_time, open_id, print_width, printer_code, printer_key, printer_name, site_id, status, template_type, 'trigger', update_time, value");
if (ObjectUtil.isNotEmpty(param.getPrinterName())) {
queryWrapper.like("printer_name", param.getPrinterName());
}
List<SysPrinterListVo> list = new LinkedList<>();
for (SysPrinter item : sysPrinterMapper.selectList(queryWrapper)) {
SysPrinterListVo vo = new SysPrinterListVo();
BeanUtils.copyProperties(item, vo);
vo.setBrandName(SysPrinterBrandEnum.getNameByBrand(item.getBrand()));
vo.setValue(JSON.parseObject(item.getValue()));
vo.setTrigger(JSONArray.parseArray(item.getTrigger(), String.class));
list.add(vo);
}
return list;
}
@Override
public SysPrinterInfoVo info(Integer id) {
SysPrinter model = sysPrinterMapper.selectOne(
new QueryWrapper<SysPrinter>()
.eq("printer_id", id)
.eq("site_id", RequestUtils.siteId()));
Assert.notNull(model, "小票打印机不存在");
SysPrinterInfoVo vo = new SysPrinterInfoVo();
BeanUtils.copyProperties(model, vo);
vo.setValue(JSON.parseObject(model.getValue()));
return vo;
}
@Override
@Transactional
public void add(SysPrinterParam addParam) {
SysPrinter model = new SysPrinter();
BeanUtils.copyProperties(addParam, model);
model.setSiteId(RequestUtils.siteId());
model.setValue(JSON.toJSONString(addParam.getValue()));
model.setTemplateType(addParam.getTemplateType().get(0));
model.setTrigger(JSON.toJSONString(addParam.getTrigger()));
model.setCreateTime(System.currentTimeMillis() / 1000);
sysPrinterMapper.insert(model);
if (addParam.getBrand().equals(SysPrinterBrandEnum.YI_LIAN_YUN.getBrand())) {
SysPrinterAddPrinterYlyParam addPrinterYlyParam = new SysPrinterAddPrinterYlyParam();
BeanUtils.copyProperties(addParam, addPrinterYlyParam);
corePrinterService.addPrinterYly(addPrinterYlyParam);
}
}
@Override
@Transactional
public void edit(Integer id, SysPrinterParam editParam) {
SysPrinter model = sysPrinterMapper.selectOne(
new QueryWrapper<SysPrinter>()
.eq("printer_id", id)
.eq("site_id", RequestUtils.siteId()));
Assert.notNull(model, "小票打印机不存在");
BeanUtils.copyProperties(editParam, model);
model.setValue(JSON.toJSONString(editParam.getValue()));
model.setTemplateType(editParam.getTemplateType().get(0));
model.setTrigger(JSON.toJSONString(editParam.getTrigger()));
model.setUpdateTime(System.currentTimeMillis() / 1000);
sysPrinterMapper.updateById(model);
if (editParam.getBrand().equals(SysPrinterBrandEnum.YI_LIAN_YUN.getBrand())) {
SysPrinterAddPrinterYlyParam addPrinterYlyParam = new SysPrinterAddPrinterYlyParam();
BeanUtils.copyProperties(editParam, addPrinterYlyParam);
corePrinterService.addPrinterYly(addPrinterYlyParam);
}
}
@Override
public void modifyStatus(SysPrinterModifyStatusParam param) {
SysPrinter model = sysPrinterMapper.selectOne(
new QueryWrapper<SysPrinter>()
.eq("printer_id", param.getPrinterId())
.eq("site_id", RequestUtils.siteId()));
model.setStatus(param.getStatus());
sysPrinterMapper.updateById(model);
}
@Override
public void del(Integer id) {
SysPrinter model = sysPrinterMapper.selectOne(
new QueryWrapper<SysPrinter>()
.eq("printer_id", id)
.eq("site_id", RequestUtils.siteId()));
if (ObjectUtil.isEmpty(model)) {
return;
}
sysPrinterMapper.deleteById(id);
if (model.getBrand().equals(SysPrinterBrandEnum.YI_LIAN_YUN.getBrand())) {
corePrinterService.deletePrinterYly(model);
}
}
@Override
public cn.hutool.json.JSON getType() {
return SysPrinterTypeEnum.getType();
}
@Override
public JSONObject getBrand() {
JSONObject jsonObject = new JSONObject();
for (SysPrinterBrandEnum value : SysPrinterBrandEnum.values()) {
if (ObjectUtil.isEmpty(value.getBrand())) {
continue;
}
jsonObject.put(value.getBrand(), value.getName());
}
return jsonObject;
}
@Override
public String refreshToken(Integer id) {
SysPrinter model = sysPrinterMapper.selectOne(
new QueryWrapper<SysPrinter>()
.eq("printer_id", id)
.eq("site_id", RequestUtils.siteId()));
if (ObjectUtil.isEmpty(model)) {
throw new RuntimeException("打印机不存在");
}
return corePrinterService.refreshToken(model);
}
@Override
public void testPrint(Integer id) {
SysPrinter model = sysPrinterMapper.selectOne(
new QueryWrapper<SysPrinter>()
.eq("printer_id", id)
.eq("site_id", RequestUtils.siteId()));
if (ObjectUtil.isEmpty(model)) {
throw new RuntimeException("打印机不存在");
}
if (model.getBrand().equals(SysPrinterBrandEnum.YI_LIAN_YUN.getBrand())) {
testYlyPrint(model);
}
}
@Override
public SysPrinterPrintTicketVo printTicket(SysPrinterPrintTicketParam param) {
param.setSiteId(RequestUtils.siteId());
return corePrinterService.printTicket(param);
}
private void testYlyPrint(SysPrinter printer) {
Random random = new Random();
String originId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + (random.nextInt(999) + 1); // 内部订单号(32位以内)
String content = "<MN>" + 1 + "</MN>" +
"<center>小票名称</center>" +
repeat('.', 32) +
"<FH2><FS><center>商城名称</center></FS></FH2>" +
repeat('.', 32) +
"订单时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) + "\n" +
"订单编号:" + originId + "\n" +
repeat('.', 32) +
"<table>" +
"<tr><td>商品名称</td><td></td><td>数量</td><td>金额</td></tr>" +
"</table>" +
repeat('.', 32) +
"<table>" +
"<tr><td>烤土豆(超级辣)</td><td></td><td>x3</td><td>5</td></tr>" +
"<tr><td>烤豆干(超级辣)</td><td></td><td>x2</td><td>10</td></tr>" +
"<tr><td>烤鸡翅(超级辣)</td><td></td><td>x3</td><td>15</td></tr>" +
"</table>" +
repeat('.', 32) +
"商品总额¥30 " + "\n" +
"订单共8件商品总计: ¥30 " + "\n" +
repeat('.', 32) +
"<FH2>买家留言:微辣,多放孜然</FH2>\n" +
repeat('.', 32) +
"<center>谢谢惠顾,欢迎下次光临</center>";
corePrinterService.printIndex(printer, content, originId);
}
private String repeat(char ch, int count) {
StringBuilder sb = new StringBuilder(count);
for (int i = 0; i < count; i++) {
sb.append(ch);
}
return sb.toString();
}
}

View File

@ -0,0 +1,165 @@
package com.niu.core.service.admin.sys.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.niu.core.common.domain.PageParam;
import com.niu.core.common.domain.PageResult;
import com.niu.core.common.utils.RequestUtils;
import com.niu.core.common.utils.date.DateUtils;
import com.niu.core.entity.sys.SysPrinter;
import com.niu.core.entity.sys.SysPrinterTemplate;
import com.niu.core.enums.sys.SysPrinterTypeEnum;
import com.niu.core.mapper.sys.SysPrinterMapper;
import com.niu.core.mapper.sys.SysPrinterTemplateMapper;
import com.niu.core.service.admin.sys.ISysPrinterTemplateService;
import com.niu.core.service.admin.sys.param.SysPrinterTemplateParam;
import com.niu.core.service.admin.sys.param.SysPrinterTemplateSearchParam;
import com.niu.core.service.admin.sys.vo.SysPrinterTemplateInfoVo;
import com.niu.core.service.admin.sys.vo.SysPrinterTemplateListVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
/**
* 小票打印模板实现
*/
@Service
@RequiredArgsConstructor
public class SysPrinterTemplateServiceImpl implements ISysPrinterTemplateService {
private final SysPrinterMapper sysPrinterMapper;
private final SysPrinterTemplateMapper sysPrinterTemplateMapper;
@Override
public PageResult<SysPrinterTemplateListVo> page(PageParam pageParam, SysPrinterTemplateSearchParam searchParam) {
Integer page = pageParam.getPage();
Integer limit = pageParam.getLimit();
QueryWrapper<SysPrinterTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("site_id", RequestUtils.siteId())
.orderByDesc("create_time");
if (ObjectUtil.isNotEmpty(searchParam.getTemplateId())) {
queryWrapper.eq("template_id", searchParam.getTemplateId());
}
if (ObjectUtil.isNotEmpty(searchParam.getTemplateName())) {
queryWrapper.like("template_name", searchParam.getTemplateName());
}
if (ObjectUtil.isNotEmpty(searchParam.getTemplateType())) {
queryWrapper.eq("template_type", searchParam.getTemplateType());
}
IPage<SysPrinterTemplate> iPage = sysPrinterTemplateMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<SysPrinterTemplateListVo> list = new LinkedList<>();
for (SysPrinterTemplate item : iPage.getRecords()) {
SysPrinterTemplateListVo vo = new SysPrinterTemplateListVo();
BeanUtils.copyProperties(item, vo);
vo.setTemplateTypeName(SysPrinterTypeEnum.getTypeName(item.getTemplateType()));
vo.setValue(JSON.parseObject(item.getValue()));
vo.setCreateTime(DateUtils.timestampToString(item.getCreateTime()));
list.add(vo);
}
return PageResult.build(page, limit, iPage.getTotal()).setData(list);
}
@Override
public List<SysPrinterTemplateListVo> getList(SysPrinterTemplateSearchParam searchParam) {
QueryWrapper<SysPrinterTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("site_id", RequestUtils.siteId())
.orderByDesc("create_time");
if (ObjectUtil.isNotEmpty(searchParam.getTemplateId())) {
queryWrapper.eq("template_id", searchParam.getTemplateId());
}
if (ObjectUtil.isNotEmpty(searchParam.getTemplateName())) {
queryWrapper.like("template_name", searchParam.getTemplateName());
}
if (ObjectUtil.isNotEmpty(searchParam.getTemplateType())) {
queryWrapper.eq("template_type", searchParam.getTemplateType());
}
List<SysPrinterTemplateListVo> voList = new LinkedList<>();
for (SysPrinterTemplate item : sysPrinterTemplateMapper.selectList(queryWrapper)) {
SysPrinterTemplateListVo vo = new SysPrinterTemplateListVo();
BeanUtils.copyProperties(item, vo);
vo.setTemplateTypeName(SysPrinterTypeEnum.getTypeName(item.getTemplateType()));
vo.setValue(JSON.parseObject(item.getValue()));
vo.setCreateTime(DateUtils.timestampToString(item.getCreateTime()));
voList.add(vo);
}
return voList;
}
@Override
public SysPrinterTemplateInfoVo info(Integer id) {
SysPrinterTemplate model = sysPrinterTemplateMapper.selectOne(
new QueryWrapper<SysPrinterTemplate>()
.eq("template_id", id)
.eq("site_id", RequestUtils.siteId()));
Assert.notNull(model, "小票打印模板不存在");
SysPrinterTemplateInfoVo vo = new SysPrinterTemplateInfoVo();
BeanUtils.copyProperties(model, vo);
vo.setValue(JSON.parseObject(model.getValue()));
vo.setCreateTime(DateUtils.timestampToString(model.getCreateTime()));
return vo;
}
@Override
public void add(SysPrinterTemplateParam addParam) {
SysPrinterTemplate model = new SysPrinterTemplate();
BeanUtils.copyProperties(addParam, model);
model.setValue(JSON.toJSONString(addParam.getValue()));
model.setCreateTime(System.currentTimeMillis() / 1000);
model.setSiteId(RequestUtils.siteId());
sysPrinterTemplateMapper.insert(model);
}
@Override
public void edit(Integer id, SysPrinterTemplateParam editParam) {
SysPrinterTemplate model = sysPrinterTemplateMapper.selectOne(
new QueryWrapper<SysPrinterTemplate>()
.eq("template_id", id)
.eq("site_id", RequestUtils.siteId()));
Assert.notNull(model, "小票打印模板不存在");
BeanUtils.copyProperties(editParam, model);
sysPrinterTemplateMapper.updateById(model);
}
@Override
public void del(Integer id) {
SysPrinterTemplate template = sysPrinterTemplateMapper.selectById(id);
LambdaQueryWrapper<SysPrinter> printerLambdaQueryWrapper = new LambdaQueryWrapper<>();
printerLambdaQueryWrapper.eq(SysPrinter::getSiteId, RequestUtils.siteId())
.like(SysPrinter::getTemplateType, template.getTemplateType());
List<SysPrinter> printers = sysPrinterMapper.selectList(printerLambdaQueryWrapper);
Optional<SysPrinter> illegalPrinter = printers.stream()
.filter(printer -> ObjectUtil.isNotEmpty(printer.getValue()))
.filter(printer -> JSON.parseArray(printer.getValue()).stream()
.anyMatch(value -> JSON.parseArray(value.toString()).stream()
.anyMatch(o -> id.equals(JSON.parseObject(o.toString()).getInteger("template_id")))))
.findFirst();
if (illegalPrinter.isPresent()) {
throw new RuntimeException("该模板已被打印机[" + illegalPrinter.get().getPrinterName() + "]使用,无法删除");
}
sysPrinterTemplateMapper.deleteById(id);
}
}

View File

@ -0,0 +1,9 @@
package com.niu.core.service.admin.sys.param;
import lombok.Data;
@Data
public class SysPrinterModifyStatusParam {
private Integer printerId;
private Integer status;
}

View File

@ -0,0 +1,82 @@
package com.niu.core.service.admin.sys.param;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 小票打印机参数
*/
@Data
public class SysPrinterParam implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 开发者密钥
*/
private String apikey;
/**
* 设备品牌易联云365飞鹅
*/
private String brand;
/**
* 开发者id
*/
private String openId;
/**
* 纸张宽度
*/
private String printWidth;
/**
* 打印机编号
*/
private String printerCode;
/**
*
*/
private Integer printerId;
/**
* 打印机秘钥
*/
private String printerKey;
/**
* 打印机名称
*/
private String printerName;
/**
* 站点id
*/
private Integer siteId;
/**
* 状态0关闭1开启
*/
private Integer status;
/**
* 小票打印模板类型多个逗号隔开
*/
private List<String> templateType;
/**
* 触发打印时机
*/
private List<String> trigger;
/**
* 打印模板数据json格式
*/
private Object value;
}

View File

@ -0,0 +1,91 @@
package com.niu.core.service.admin.sys.param;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印机参数
*/
@Data
public class SysPrinterSearchParam implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 开发者密钥
*/
private String apikey;
/**
* 设备品牌易联云365飞鹅
*/
private String brand;
/**
* 创建时间
*/
private Long createTime;
/**
* 开发者id
*/
private String openId;
/**
* 纸张宽度
*/
private String printWidth;
/**
* 打印机编号
*/
private String printerCode;
/**
*
*/
private Integer printerId;
/**
* 打印机秘钥
*/
private String printerKey;
/**
* 打印机名称
*/
private String printerName;
/**
* 站点id
*/
private Integer siteId;
/**
* 状态0关闭1开启
*/
private Integer status;
/**
* 小票打印模板类型多个逗号隔开
*/
private String templateType;
/**
* 触发打印时机
*/
private String trigger;
/**
* 修改时间
*/
private Long updateTime;
/**
* 打印模板数据json格式
*/
private String value;
}

View File

@ -0,0 +1,41 @@
package com.niu.core.service.admin.sys.param;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印模板参数
*/
@Data
public class SysPrinterTemplateParam implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 站点id
*/
private Integer siteId;
/**
*
*/
private Integer templateId;
/**
* 模板名称
*/
private String templateName;
/**
* 模板类型
*/
private String templateType;
/**
* 模板数据json格式
*/
private Object value;
}

View File

@ -0,0 +1,51 @@
package com.niu.core.service.admin.sys.param;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印模板参数
*/
@Data
public class SysPrinterTemplateSearchParam implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
private Long createTime;
/**
* 站点id
*/
private Integer siteId;
/**
*
*/
private Integer templateId;
/**
* 模板名称
*/
private String templateName;
/**
* 模板类型
*/
private String templateType;
/**
* 修改时间
*/
private Long updateTime;
/**
* 模板数据json格式
*/
private String value;
}

View File

@ -0,0 +1,106 @@
package com.niu.core.service.admin.sys.vo;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印机详情
*/
@Data
public class SysPrinterInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 开发者密钥
*/
private String apikey;
/**
* 设备品牌易联云365飞鹅
*/
private String brand;
/**
* 创建时间
*/
private Long createTime;
/**
* 开发者id
*/
private String openId;
/**
* 纸张宽度
*/
private String printWidth;
/**
* 打印机编号
*/
private String printerCode;
/**
*
*/
private Integer printerId;
/**
* 打印机秘钥
*/
private String printerKey;
/**
* 打印机名称
*/
private String printerName;
/**
* 站点id
*/
private Integer siteId;
/**
* 状态0关闭1开启
*/
private Integer status;
/**
* 小票打印模板类型多个逗号隔开
*/
private String templateType;
/**
* 触发打印时机
*/
private String trigger;
/**
* 修改时间
*/
private Long updateTime;
/**
* 打印模板数据json格式
*/
private JSONObject value;
}

View File

@ -0,0 +1,86 @@
package com.niu.core.service.admin.sys.vo;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 小票打印机列表
*/
@Data
public class SysPrinterListVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 开发者密钥
*/
private String apikey;
/**
* 设备品牌易联云365飞鹅
*/
private String brand;
/**
* 开发者id
*/
private String openId;
/**
* 纸张宽度
*/
private String printWidth;
/**
* 打印机编号
*/
private String printerCode;
/**
*
*/
private Integer printerId;
/**
* 打印机秘钥
*/
private String printerKey;
/**
* 打印机名称
*/
private String printerName;
/**
* 站点id
*/
private Integer siteId;
/**
* 状态0关闭1开启
*/
private Integer status;
/**
* 小票打印模板类型多个逗号隔开
*/
private String templateType;
/**
* 触发打印时机
*/
private List<String> trigger;
/**
* 打印模板数据json格式
*/
private JSONObject value;
private String brandName;
}

View File

@ -0,0 +1,58 @@
package com.niu.core.service.admin.sys.vo;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印模板详情
*/
@Data
public class SysPrinterTemplateInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
private String createTime;
/**
* 站点id
*/
private Integer siteId;
/**
*
*/
private Integer templateId;
/**
* 模板名称
*/
private String templateName;
/**
* 模板类型
*/
private String templateType;
/**
* 修改时间
*/
private Long updateTime;
/**
* 模板数据json格式
*/
private JSONObject value;
}

View File

@ -0,0 +1,47 @@
package com.niu.core.service.admin.sys.vo;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import java.io.Serializable;
/**
* 小票打印模板列表
*/
@Data
public class SysPrinterTemplateListVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 站点id
*/
private Integer siteId;
/**
*
*/
private Integer templateId;
/**
* 模板名称
*/
private String templateName;
/**
* 模板类型
*/
private String templateType;
/**
* 模板数据json格式
*/
private JSONObject value;
private String templateTypeName;
private String createTime;
}

View File

@ -5,6 +5,14 @@ import com.niu.core.service.admin.upgrade.vo.UpgradeTaskVo;
public interface IUpgradeService {
/**
* 升级检测
*
* @param addon
* @return
*/
JSONObject upgradeCheck(String addon);
/**
* 获取升级内容
* @param addon
@ -24,6 +32,12 @@ public interface IUpgradeService {
*/
UpgradeTaskVo getUpgradeTask();
/**
*
* @param vo
*/
void setUpgradeTaskCache(UpgradeTaskVo vo);
/**
* 清除升级任务
*/
@ -34,4 +48,10 @@ public interface IUpgradeService {
*
*/
void execute();
/**
* 升级异常处理
* @param vo
*/
void upgradeErrorHandle(UpgradeTaskVo vo);
}

View File

@ -15,6 +15,7 @@ import com.github.yulichang.query.MPJQueryWrapper;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.component.context.cache.CacheFactory;
import com.niu.core.common.component.context.cache.Cached;
import com.niu.core.common.component.upgrade.factory.UpgradeProviderFactory;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.config.dataization.AddonModuleContext;
import com.niu.core.common.exception.CommonException;
@ -42,6 +43,7 @@ import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
@ -76,6 +78,67 @@ public class UpgradeServiceImpl implements IUpgradeService {
this.upgradeService = upgradeService;
}
/**
* 升级检测
*
* @param addon
* @return
*/
@Override
public JSONObject upgradeCheck(String addon) {
boolean upgradeCheck = true;
JSONObject checkResult = new JSONObject();
String rootPath = "";
String runtimePath = "";
JSONArray readableDir = new JSONArray();
JSONArray writeDir = new JSONArray();
if (WebAppEnvs.get().envType.equals("dev")) {
rootPath = WebAppEnvs.get().projectRoot + "/";
runtimePath = rootPath;
readableDir.put(new JSONObject().set("dir", rootPath + "niucloud-addon").set("status", true));
writeDir.put(new JSONObject().set("dir", rootPath + "niucloud-addon").set("status", true));
readableDir.put(new JSONObject().set("dir", rootPath + "webroot").set("status", true));
writeDir.put(new JSONObject().set("dir", rootPath + "webroot").set("status", true));
} else {
rootPath = WebAppEnvs.get().webRoot + "/";
runtimePath = rootPath + "runtime/";
readableDir.put(new JSONObject().set("dir", runtimePath).set("status", true));
writeDir.put(new JSONObject().set("dir", runtimePath).set("status", true));
}
readableDir.put(new JSONObject().set("dir", runtimePath + "admin").set("status", true));
readableDir.put(new JSONObject().set("dir", runtimePath + "uni-app").set("status", true));
readableDir.put(new JSONObject().set("dir", runtimePath + "web").set("status", true));
writeDir.put(new JSONObject().set("dir", runtimePath + "admin").set("status", true));
writeDir.put(new JSONObject().set("dir", runtimePath + "uni-app").set("status", true));
writeDir.put(new JSONObject().set("dir", runtimePath + "web").set("status", true));
for (int i = 0; i < readableDir.size(); i++) {
JSONObject dir = readableDir.getJSONObject(i);
dir.set("status", new File(dir.getStr("dir")).canRead());
dir.set("dir", dir.getStr("dir").replace(rootPath, ""));
readableDir.set(i, dir);
if (!dir.getBool("status")) upgradeCheck = false;
}
for (int i = 0; i < writeDir.size(); i++) {
JSONObject dir = writeDir.getJSONObject(i);
dir.set("status", new File(dir.getStr("dir")).canWrite());
dir.set("dir", dir.getStr("dir").replace(rootPath, ""));
writeDir.set(i, dir);
if (!dir.getBool("status")) upgradeCheck = false;
}
checkResult.put("is_pass", upgradeCheck);
checkResult.put("dir", new JSONObject().set("is_readable", readableDir).set("is_write", writeDir));
return checkResult;
}
/**
* 获取升级内容
*
@ -98,7 +161,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
query.put("version", addonModel.getVersion());
}
return NiucloudUtils.Niucloud.get("member_app_upgrade/content", query);
return NiucloudUtils.Niucloud.get("member_app_upgrade/content", query).getJSONObject("data");
}
/**
@ -138,6 +201,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
if (body.getInt("code").equals(0)) throw new RuntimeException(body.getStr("msg"));
UpgradeTaskVo vo = new UpgradeTaskVo();
vo.setEnvType(WebAppEnvs.get().envType);
vo.setUpgradeTime(DateUtil.now());
vo.setAddon((String) actionQuery.get("data[app_key]"));
vo.setKey(RandomUtil.randomString(10));
@ -146,8 +210,9 @@ public class UpgradeServiceImpl implements IUpgradeService {
vo.getExecuted().add("requestUpgrade");
vo.getLog().add(vo.getSteps().get("requestUpgrade").getTitle());
vo.setParams(query);
vo.setUpgradeContent(this.getUpgradeContent(addon).getJSONObject("data"));
vo.setUpgradeContent(this.getUpgradeContent(addon));
vo.setVersion((String) actionQuery.get("data[version]"));
vo.setUpgradeVersion(vo.getUpgradeContent().getStr("upgrade_version"));
setUpgradeTaskCache(vo);
return vo;
@ -165,7 +230,8 @@ public class UpgradeServiceImpl implements IUpgradeService {
return JSONUtil.toBean(JSONUtil.parseObj(data), UpgradeTaskVo.class);
}
private void setUpgradeTaskCache(UpgradeTaskVo vo) {
@Override
public void setUpgradeTaskCache(UpgradeTaskVo vo) {
Cached cache = CacheFactory.getCacheOperator();
cache.put("upgrade", JSONUtil.parseObj(vo).toString());
}
@ -194,43 +260,19 @@ public class UpgradeServiceImpl implements IUpgradeService {
UpgradeTaskVo vo = this.getUpgradeTask();
if (vo == null) return;
if (ObjectUtil.isNotEmpty(vo.getStatus()) && vo.getStatus().equals("restarting")) return;
List<String> steps = vo.getSteps().keySet().stream().collect(Collectors.toList());
String step = steps.indexOf(vo.getStep()) < steps.size() - 1 ? steps.get(steps.indexOf(vo.getStep()) + 1) : "";
step ="downloadFile";
if (!step.isEmpty()) {
vo.getExecuted().add(step);
vo.getLog().add(vo.getSteps().get(step).getTitle());
if (!vo.getExecuted().contains(step)) {
vo.getExecuted().add(step);
vo.getLog().add(vo.getSteps().get(step).getTitle());
}
try {
Map<String, Object> param = null;
switch (step) {
case "downloadFile":
param = this.downloadFile(vo);
break;
case "backupCode":
this.backupCode(vo);
break;
case "backupSql":
this.backupSql(vo);
break;
case "coverCode":
this.coverCode(vo);
break;
case "handleUpgrade":
this.handleUpgrade(vo);
break;
case "handleVue":
this.handleVue(vo);
break;
case "refreshMenu":
this.refreshMenu(vo);
break;
case "installSchedule":
this.installSchedule(vo);
break;
case "upgradeComplete":
this.upgradeComplete(vo);
break;
}
param = (Map<String, Object>) dynamicMethodCall(step, vo);
if (param != null) {
vo.setParams(param);
} else {
@ -239,6 +281,11 @@ public class UpgradeServiceImpl implements IUpgradeService {
}
setUpgradeTaskCache(vo);
} catch (Exception e) {
vo.setStep(step);
vo.getError().add(e.getMessage());
setUpgradeTaskCache(vo);
this.upgradeErrorHandle(vo);
System.out.println("升级异常.");
e.printStackTrace();
}
}
@ -251,7 +298,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
* @return
*/
private String upgradeDir(UpgradeTaskVo vo) {
return WebAppEnvs.get().webRootDownRuntime + "upgrade/" + vo.getAddon() + "/" + vo.getUpgrade().get("data[version]") + "-" + vo.getUpgradeContent().getStr("upgrade_version");
return WebAppEnvs.get().webRootDownRuntime + "upgrade/" + vo.getAddon() + "/" + vo.getVersion() + "-" + vo.getUpgradeVersion();
}
/**
@ -260,7 +307,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
* @param vo
* @return
*/
private Map<String, Object> downloadFile(UpgradeTaskVo vo) throws Exception
public Map<String, Object> downloadFile(UpgradeTaskVo vo) throws Exception
{
Map<String, Object> param = vo.getParams();
@ -275,9 +322,11 @@ public class UpgradeServiceImpl implements IUpgradeService {
if (param.get("index") == null) {
FileTools.createDirs(downloadDir.getPath());
FileUtils.cleanDirectory(downloadDir);
HttpResponse response = new NiucloudUtils.Cloud().build("cloud/upgrade/download").query(query).header("Range", "bytes=0-").method(Method.HEAD).execute();
String length = response.header("Content-Length");
String totalLength = response.header("Content-range");
String length = ObjectUtil.defaultIfNull(totalLength.split("/")[1], "");
Double step = Math.ceil(Double.valueOf(length) / chunkSize);
param.put("index", 0);
@ -304,8 +353,10 @@ public class UpgradeServiceImpl implements IUpgradeService {
param.put("index", index + 1);
return param;
} else {
fos.close();
ZipUtil.unzip(file.getPath(), downloadDir.getPath());
file.deleteOnExit();
Thread.sleep(1000);
file.delete();
return null;
}
}
@ -316,55 +367,71 @@ public class UpgradeServiceImpl implements IUpgradeService {
*
* @param vo
*/
private void backupCode(UpgradeTaskVo vo) throws Exception {
public void backupCode(UpgradeTaskVo vo) throws Exception {
File backupDir = new File(upgradeDir(vo) + "/backup/code/");
FileTools.createDirs(backupDir.getPath());
FileUtils.cleanDirectory(backupDir);
WebAppEnvs envs = WebAppEnvs.get();
// 备份前端
FileUtils.copyDirectory(new File(WebAppEnvs.get().webRootDownPublic), new File(backupDir, "webroot/public"));
// 备份前端源码
String[] adminExclusionDir = {"node_modules", ".vscode", "dist", ".idea"};
if (new File(envs.projectRoot + "/admin").exists()) {
FileUtils.copyDirectory(new File(envs.projectRoot + "/admin"), new File(backupDir, "admin"), FileTools.createExclusionFilter(adminExclusionDir));
FileUtils.copyDirectory(new File(envs.webRootDownPublic), new File(backupDir, "webroot/public"));
String[] uniAppExclusionDir = {"node_modules", "unpackage", "dist"};
if (new File(envs.projectRoot, "uni-app").exists()) {
FileUtils.copyDirectory(new File(envs.projectRoot, "uni-app"), new File(backupDir, "webroot/runtime/uni-app"), FileTools.createExclusionFilter(uniAppExclusionDir));
}
if (new File(envs.webRootDownRuntime + "/admin").exists()) {
FileUtils.copyDirectory(new File(envs.webRootDownRuntime + "/admin"), new File(backupDir, "webroot/runtime/admin"), FileTools.createExclusionFilter(adminExclusionDir));
}
String[] uniappExclusionDir = {"node_modules", "unpackage", "dist"};
if (new File(envs.projectRoot + "/uni-app").exists()) {
FileUtils.copyDirectory(new File(envs.projectRoot + "/uni-app"), new File(backupDir, "uni-app"), FileTools.createExclusionFilter(uniappExclusionDir));
}
if (new File(envs.webRootDownRuntime + "/uni-app").exists()) {
FileUtils.copyDirectory(new File(envs.webRootDownRuntime + "/uni-app"), new File(backupDir, "webroot/runtime/uni-app"), FileTools.createExclusionFilter(uniappExclusionDir));
}
String[] webExclusionDir = {"node_modules", ".output", "nuxt", "dist", ".nuxt"};
if (new File(envs.projectRoot + "/web").exists()) {
FileUtils.copyDirectory(new File(envs.projectRoot + "/web"), new File(backupDir, "web"), FileTools.createExclusionFilter(webExclusionDir));
}
if (new File(envs.webRootDownRuntime + "/web").exists()) {
FileUtils.copyDirectory(new File(envs.webRootDownRuntime + "/web"), new File(backupDir, "webroot/runtime/web"), FileTools.createExclusionFilter(webExclusionDir));
if (new File(envs.webRootDownRuntime + "uni-app").exists()) {
FileUtils.copyDirectory(new File(envs.webRootDownRuntime + "uni-app"), new File(backupDir, "webroot/runtime/uni-app"), FileTools.createExclusionFilter(uniAppExclusionDir));
}
String[] adminExclusionDir = {"node_modules", ".vscode", "dist", ".idea"};
if (new File(envs.projectRoot, "admin").exists()) {
FileUtils.copyDirectory(new File(envs.projectRoot, "admin"), new File(backupDir, "webroot/runtime/admin"), FileTools.createExclusionFilter(adminExclusionDir));
}
if (new File(envs.webRootDownRuntime + "admin").exists()) {
FileUtils.copyDirectory(new File(envs.webRootDownRuntime + "admin"), new File(backupDir, "webroot/runtime/admin"), FileTools.createExclusionFilter(adminExclusionDir));
}
String[] webExclusionDir = {"node_modules", ".output", "nuxt", "dist", ".nuxt"};
if (new File(envs.projectRoot, "web").exists()) {
FileUtils.copyDirectory(new File(envs.projectRoot, "web"), new File(backupDir, "webroot/runtime/web"), FileTools.createExclusionFilter(webExclusionDir));
}
if (new File(envs.webRootDownRuntime + "web").exists()) {
FileUtils.copyDirectory(new File(envs.webRootDownRuntime + "web"), new File(backupDir, "webroot/runtime/web"), FileTools.createExclusionFilter(webExclusionDir));
}
File srcDir = null;
File destDir = null;
if (vo.getAddon().equals(GlobalConfig.appKey)) {
// 备份java源码
String[] addonExclusionDir = {".mvm", ".mvn", "target"};
File javaFile = new File(envs.projectRoot + "/niucloud-core");
if (javaFile.exists()) FileUtils.copyDirectory(javaFile, new File(backupDir, "niucloud-core"), FileTools.createExclusionFilter(addonExclusionDir));
// 备份jar文件
FileUtils.copyFile(new File(envs.webRootDownJar + "/web-app-exec.jar"), new File(backupDir, "webroot/jar/web-app-exec.jar"));
srcDir = new File(envs.projectRoot);
destDir = backupDir;
} else {
// 备份java源码
String[] addonExclusionDir = {".mvm", ".mvn", "target"};
File javaFile = new File(envs.projectNiucloudAddon + vo.getAddon());
if (javaFile.exists()) FileUtils.copyDirectory(javaFile, new File(backupDir, "niucloud-addon/" + vo.getAddon()), FileTools.createExclusionFilter(addonExclusionDir));
srcDir = new File(envs.webRootDownAddon + vo.getAddon());
destDir = new File(backupDir, "webroot/addon/" + vo.getAddon());
// 备份jar文件
File jarFile = new File(envs.webRootDownJar + "/addon/"+ vo.getAddon() +".jar");
if (jarFile.exists()) FileUtils.copyFile(jarFile, new File(backupDir, "webroot/jar/addon/"+ vo.getAddon() +".jar"));
// 备份webroot下的源码
File sourceFile = new File(envs.webRootDownAddon + vo.getAddon());
if (sourceFile.exists()) FileUtils.copyDirectory(sourceFile, new File(backupDir, "webroot/addon/" + vo.getAddon()));
File jarFile = new File(envs.webRootDownJar, "addon/" + vo.getAddon() + ".jar");
if (jarFile.exists()) FileUtils.copyFile(jarFile, new File(backupDir, "webroot/jar/addon/" + vo.getAddon() + ".jar"));
}
JSONArray versionList = vo.getUpgradeContent().getJSONArray("version_list");
for (int i = 0; i < versionList.size(); i++) {
String versionNo = versionList.getJSONObject(i).getStr("version_no");
File changeRecord = new File(upgradeDir(vo) + "/download/" + versionNo + ".txt");
if (changeRecord.exists()) {
List<String> change = Arrays.asList(FileUtils.readFileToString(changeRecord, "UTF-8").split("\n"));
for (String line : change) {
String[] content = line.split(" ");
if (!content[0].equals("+")) {
String path = content[2];
File changeFile = new File(srcDir, path);
if (changeFile.exists()) FileUtils.copyFile(changeFile, new File(destDir, path));
}
}
}
}
}
@ -372,9 +439,10 @@ public class UpgradeServiceImpl implements IUpgradeService {
* 备份数据库
* @param vo
*/
private void backupSql(UpgradeTaskVo vo) throws Exception {
public void backupSql(UpgradeTaskVo vo) throws Exception {
File backupDir = new File(upgradeDir(vo) + "/backup/sql/");
FileTools.createDirs(backupDir.getPath());
FileUtils.cleanDirectory(backupDir);
String url = env.getProperty("spring.datasource.url");
String user = env.getProperty("spring.datasource.username");
@ -394,10 +462,8 @@ public class UpgradeServiceImpl implements IUpgradeService {
* 合并更新文件
* @param vo
*/
private void coverCode(UpgradeTaskVo vo) throws Exception {
public void coverCode(UpgradeTaskVo vo) throws Exception {
if (WebAppEnvs.get().envType.equals("dev")) {
String upgradeVersion = vo.getUpgradeContent().getStr("upgrade_version");
File changeRecord = new File(upgradeDir(vo) + "/download/code/" + upgradeVersion + ".txt");
File sourceFile = null;
File projectFile = null;
@ -409,29 +475,58 @@ public class UpgradeServiceImpl implements IUpgradeService {
projectFile = new File(WebAppEnvs.get().projectNiucloudAddon + vo.getAddon());
}
// 移除已删除文件
if (changeRecord.exists()) {
List<String> change = Arrays.asList(FileUtils.readFileToString(changeRecord, "UTF-8").split("\n"));
for (String line : change) {
String[] content = line.split(" ");
if (content[0].equals("-")) {
(new File(sourceFile, content[2])).deleteOnExit();
if (projectFile != null && content[2].startsWith("/java/") && projectFile.exists()) (new File(projectFile, content[2].replaceFirst("^/java/", ""))).deleteOnExit();
JSONArray versionList = vo.getUpgradeContent().getJSONArray("version_list");
for (int i = 0; i < versionList.size(); i++) {
String versionNo = versionList.getJSONObject(i).getStr("version_no");
File changeRecord = new File(upgradeDir(vo) + "/download/" + versionNo + ".txt");
// 移除已删除文件
if (changeRecord.exists()) {
List<String> change = Arrays.asList(FileUtils.readFileToString(changeRecord, "UTF-8").split("\n"));
for (String line : change) {
String[] content = line.split(" ");
if (content[0].equals("-")) {
(new File(sourceFile, content[2])).deleteOnExit();
if (projectFile != null && content[2].startsWith("/java/") && projectFile.exists()) (new File(projectFile, content[2].replaceFirst("^/java/", ""))).deleteOnExit();
}
}
}
// 覆盖变更文件
File codeDir = new File(upgradeDir(vo) + "/download/" + versionNo);
if (vo.getAddon().equals(GlobalConfig.appKey)) {
File[] childFile = codeDir.listFiles();
for (File file : childFile) {
if (file.isDirectory()) {
if (new File(sourceFile, file.getName()).exists()) FileUtils.copyDirectory(file, new File(sourceFile, file.getName()));
} else {
FileUtils.copyFile(file, new File(sourceFile, file.getName()));
}
}
} else {
FileUtils.copyDirectory(codeDir, sourceFile);
if (projectFile != null && projectFile.exists() && new File(codeDir, "java").exists()) {
FileUtils.copyDirectory(new File(codeDir, "java"), projectFile);
}
}
}
// 覆盖变更文件
if (vo.getAddon().equals(GlobalConfig.appKey)) {
FileUtils.copyDirectory(new File(upgradeDir(vo) + "/download/code/"), sourceFile);
} else {
FileUtils.copyDirectory(new File(upgradeDir(vo) + "/download/code/"), sourceFile);
if (projectFile != null && projectFile.exists() && new File(upgradeDir(vo) + "/download/code/java/").exists()) {
FileUtils.copyDirectory(new File(upgradeDir(vo) + "/download/code/java/"), projectFile);
}
}
vo.setStatus("restarting");
setUpgradeTaskCache(vo);
} else {
PipeNameUtils.noticeBootRestart(GlobalConfig.applicationName, vo.getAddon().equals(GlobalConfig.appKey) ? "core" : vo.getAddon());
vo.setStep("coverCode");
vo.setStatus("restarting");
setUpgradeTaskCache(vo);
String dir = vo.getUpgrade().get("data[version]") + "-" + vo.getUpgradeContent().getStr("upgrade_version");
List<String> versions = new LinkedList<>();
JSONArray versionList = vo.getUpgradeContent().getJSONArray("version_list");
for (int i = 0; i < versionList.size(); i++) {
versions.add(versionList.getJSONObject(i).getStr("version_no"));
}
PipeNameUtils.noticeBootRestartByUpgrade(GlobalConfig.applicationName, vo.getAddon(), dir, String.join("-", versions));
Thread.sleep(3000);
}
}
@ -440,7 +535,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
* 处理升级方法
* @param vo
*/
private void handleUpgrade(UpgradeTaskVo vo) {
public void handleUpgrade(UpgradeTaskVo vo) {
JSONArray versionList = vo.getUpgradeContent().getJSONArray("version_list");
String addon = vo.getAddon().equals(GlobalConfig.appKey) ? "core" : vo.getAddon();
for (int i = 0; i < versionList.size(); i++) {
@ -457,17 +552,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
}
try {
try {
String className = "com.niu."+ addon +".upgrade.V" + versionNo.replaceAll(".", "") + ".Upgrade";
Class<?> clazz = Class.forName(className);
try {
Object instance = clazz.getDeclaredConstructor().newInstance();
java.lang.reflect.Method method = clazz.getMethod("handle");
method.invoke(instance);
} catch (NoSuchMethodException e) {
}
} catch (ClassNotFoundException e) {
}
UpgradeProviderFactory.handle(addon, versionNo);
} catch (Exception e) {
throw new CommonException(versionNo + "版本升级方法执行出错,错误原因:" + e.getMessage());
}
@ -478,7 +563,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
* 处理vue
* @param vo
*/
private void handleVue(UpgradeTaskVo vo) throws Exception {
public void handleVue(UpgradeTaskVo vo) throws Exception {
WebAppEnvs envs = WebAppEnvs.get();
if (!vo.getAddon().equals(GlobalConfig.appKey)) {
@ -516,7 +601,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
* 刷新菜单
* @param vo
*/
private void refreshMenu(UpgradeTaskVo vo) {
public void refreshMenu(UpgradeTaskVo vo) {
if (vo.getAddon().equals(GlobalConfig.appKey)) {
coreMenuService.refreshAddonMenu("core");
} else {
@ -528,7 +613,7 @@ public class UpgradeServiceImpl implements IUpgradeService {
* 安装计划任务
* @param vo
*/
private void installSchedule(UpgradeTaskVo vo) {
public void installSchedule(UpgradeTaskVo vo) {
if (vo.getAddon().equals(GlobalConfig.appKey)) {
coreScheduleService.installSystemSchedule();
} else {
@ -536,15 +621,162 @@ public class UpgradeServiceImpl implements IUpgradeService {
}
}
private void upgradeComplete(UpgradeTaskVo vo) {
public void upgradeComplete(UpgradeTaskVo vo) {
vo.setStatus("success");
if (!vo.getAddon().equals(GlobalConfig.appKey)) {
Addon addon = JSONUtil.toBean(coreAddonService.getAddonConfig(vo.getAddon()), Addon.class);
coreAddonService.set(addon);
}
File backupDir = new File(upgradeDir(vo));
FileUtil.writeUtf8String(JSONUtil.toJsonPrettyStr(JSONUtil.parseObj(vo)), new File(backupDir, "log.json"));
FileUtil.writeUtf8String(JSONUtil.toJsonPrettyStr(JSONUtil.parseObj(vo)), new File(backupDir, DateUtil.now() + ".log"));
upgradeService.clearUpgradeTask(5);
}
/**
* 升级异常处理
* @param vo
*/
public void upgradeErrorHandle(UpgradeTaskVo vo) {
File backupDir = new File(upgradeDir(vo));
FileUtil.writeUtf8String(JSONUtil.toJsonPrettyStr(JSONUtil.parseObj(vo)), new File(backupDir, DateUtil.now() + ".log"));
Map<String, UpgradeTaskVo.Step> steps = new LinkedHashMap<>();
steps.put("rollback", new UpgradeTaskVo.Step("rollback", "升级失败开始回滚"));
if (vo.getExecuted().contains("coverCode")) {
steps.put("restoreCover", new UpgradeTaskVo.Step("restoreCover", "恢复变更文件"));
}
if (vo.getExecuted().contains("handleUpgrade")) {
steps.put("restoreDatabase", new UpgradeTaskVo.Step("restoreDatabase", "恢复数据库"));
}
steps.put("rollbackComplete", new UpgradeTaskVo.Step("rollbackComplete", "回滚完成"));
vo.setSteps(steps);
vo.setStep("rollback");
vo.getLog().add(steps.get("rollback").getTitle());
vo.getExecuted().add("rollback");
setUpgradeTaskCache(vo);
}
/**
* 恢复文件备份
*/
public void restoreCover(UpgradeTaskVo vo) {
if (WebAppEnvs.get().envType.equals("dev")) {
try {
File backupDir = new File(upgradeDir(vo) + "/backup/code/");
WebAppEnvs envs = WebAppEnvs.get();
File rootDir = null;
if (vo.getAddon().equals(GlobalConfig.appKey)) {
rootDir = new File(envs.projectRoot);
} else {
rootDir = new File(envs.webRootDownAddon + vo.getAddon());
}
FileUtils.copyDirectory(backupDir, new File(envs.projectRoot));
JSONArray versionList = vo.getUpgradeContent().getJSONArray("version_list");
for (int i = 0; i < versionList.size(); i++) {
String versionNo = versionList.getJSONObject(i).getStr("version_no");
File changeRecord = new File(upgradeDir(vo) + "/download/" + versionNo + ".txt");
// 移除更新新增的文件
if (changeRecord.exists()) {
List<String> change = Arrays.asList(FileUtils.readFileToString(changeRecord, "UTF-8").split("\n"));
for (String line : change) {
String[] content = line.split(" ");
if (content[0].equals("+")) {
String path = content[2];
File changeFile = new File(rootDir, path);
if (changeFile.exists()) changeFile.delete();
}
}
}
}
if (!vo.getAddon().equals(GlobalConfig.appKey)) {
File sourceDir = new File(envs.webRootDownAddon + vo.getAddon() + "/java");
File projectDir = new File(envs.projectNiucloudAddon + vo.getAddon());
if (sourceDir.exists() && projectDir.exists()) FileUtils.copyDirectory(sourceDir, projectDir);
}
} catch (Exception e) {
vo.getError().add("变更文件恢复失败,错误信息:" + e.getMessage());
}
} else {
try {
vo.setStep("restoreCover");
vo.setStatus("restarting");
setUpgradeTaskCache(vo);
String dir = vo.getUpgrade().get("data[version]") + "-" + vo.getUpgradeContent().getStr("upgrade_version");
PipeNameUtils.noticeBootRestartByUpgradeRollback(GlobalConfig.applicationName, vo.getAddon(), dir);
Thread.sleep(3000);
} catch (Exception e) {
}
}
}
/**
* 恢复数据库
*/
public void restoreDatabase(UpgradeTaskVo vo) {
try {
File backupDir = new File(upgradeDir(vo), "/backup/sql/");
File[] files = backupDir.listFiles();
Arrays.sort(files);
for (File file : files) {
if (file.isFile()) {
SQLScriptRunnerTools.execScript(file);
}
}
} catch (Exception e) {
vo.getError().add("数据库回滚失败,错误信息:" + e.getMessage());
String dir = "webboot/upgrade/" + vo.getAddon() + "/" + vo.getVersion() + "-" + vo.getUpgradeVersion() + "/backup/sql";
vo.getError().add("数据库回滚失败请找到" + dir + "目录下的数据库备份文件手动进行恢复");
}
}
/**
* 回滚完成
* @param vo
*/
public void rollbackComplete(UpgradeTaskVo vo) {
vo.setStatus("rollback");
File backupDir = new File(upgradeDir(vo));
FileUtil.writeUtf8String(JSONUtil.toJsonPrettyStr(JSONUtil.parseObj(vo)), new File(backupDir, DateUtil.now() + ".log"));
upgradeService.clearUpgradeTask(5);
}
public Object dynamicMethodCall(String methodName, Object... args) {
try {
// 获取当前类的 Class 对象
Class<?> clazz = this.getClass();
// 获取方法对象
java.lang.reflect.Method method = clazz.getMethod(methodName, extractParameterTypes(args));
// 调用方法
Object result = method.invoke(this, args);
if (method.getReturnType() == void.class) {
return null;
} else {
return result;
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
}
private Class<?>[] extractParameterTypes(Object[] args) {
if (args == null || args.length == 0) {
return new Class<?>[0];
}
Class<?>[] parameterTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
parameterTypes[i] = args[i].getClass();
}
return parameterTypes;
}
}

View File

@ -5,16 +5,15 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
@Data
public class UpgradeTaskVo implements Serializable {
private static final long serialVersionUID = 1L;
private String envType;
private String upgradeTime;
private String addon;
@ -35,11 +34,16 @@ public class UpgradeTaskVo implements Serializable {
private String status;
private Map<String, Step> steps = new HashMap<>();
private List<String> error = new LinkedList<>();
private String version;
private String upgradeVersion;
private Map<String, Step> steps = new LinkedHashMap<>();
public UpgradeTaskVo() {
this.steps = new HashMap<>();
this.steps = new LinkedHashMap<>();
steps.put("requestUpgrade", new Step("requestUpgrade", "请求升级"));
steps.put("downloadFile", new Step("downloadFile", "下载更新文件"));
steps.put("backupCode", new Step("backupCode", "备份源码"));

View File

@ -16,6 +16,7 @@ import com.niu.core.common.utils.json.JsonModuleLoader;
import com.niu.core.common.utils.mapper.QueryMapperUtils;
import com.niu.core.entity.member.Member;
import com.niu.core.entity.member.MemberAccountLog;
import com.niu.core.enums.member.AccountTypeEnum;
import com.niu.core.mapper.member.MemberAccountLogMapper;
import com.niu.core.mapper.member.MemberMapper;
import com.niu.core.service.api.member.IMemberAccountService;
@ -46,9 +47,9 @@ public class MemberAccountServiceImpl implements IMemberAccountService {
queryWrapper.select("id, member_id, site_id, account_type, account_data, from_type, related_id, create_time, memo");
queryWrapper.eq("site_id", param.siteId());
queryWrapper.eq("member_id", param.memberId());
if ("income".equals(param.getAccountType())) {
if ("income".equals(param.getAmountType())) {
queryWrapper.gt("account_data", 0);
} else if ("disburse".equals(param.getAccountType())) {
} else if ("disburse".equals(param.getAmountType())) {
queryWrapper.lt("account_data", 0);
}
if (StrUtil.isNotEmpty(param.getAccountType())) {
@ -122,9 +123,8 @@ public class MemberAccountServiceImpl implements IMemberAccountService {
queryWrapper.select("id, member_id, site_id, account_type, account_data, from_type, related_id, create_time, memo");
queryWrapper.eq("site_id", param.siteId());
queryWrapper.eq("member_id", param.memberId());
if (StrUtil.isNotEmpty(param.getAccountType())) {
queryWrapper.eq("account_type", param.getAccountType());
}
queryWrapper.in("account_type", new String[]{ AccountTypeEnum.BALANCE.getType(), AccountTypeEnum.MONEY.getType() });
if (StrUtil.isNotEmpty(param.getFromType())) {
queryWrapper.eq("from_type", param.getFromType());
}
@ -140,6 +140,13 @@ public class MemberAccountServiceImpl implements IMemberAccountService {
if (StrUtil.isNotEmpty(param.getKeyword())) {
queryWrapper.eq("keyword", param.getKeyword());
}
if ("income".equals(param.getTradeType())) {
queryWrapper.gt("account_data", 0);
} else if ("disburse".equals(param.getTradeType())) {
queryWrapper.lt("account_data", 0);
} else if ("cash_out".equals(param.getTradeType())) {
queryWrapper.eq("from_type", "cash_out");
}
queryWrapper.orderByDesc(Arrays.asList("create_time"));
IPage<MemberAccountLog> iPage = this.memberAccountLogMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<AccountBalanceFlowVo> dataList = CollectUtils.convert(iPage.getRecords(), AccountBalanceFlowVo.class);
@ -175,6 +182,9 @@ public class MemberAccountServiceImpl implements IMemberAccountService {
} else {
queryWrapper.in("account_type", "balance", "money");
}
if (ObjectUtil.isNotEmpty(param.getCreateTime())) {
QueryMapperUtils.buildByTime(queryWrapper, "create_time", param.getCreateTime());
}
queryWrapper.orderByDesc(Arrays.asList("create_time"));
IPage<MemberAccountLog> iPage = this.memberAccountLogMapper.selectPage(new Page<>(page, limit), queryWrapper);
List<AccountBalanceListVo> dataList = CollectUtils.convert(iPage.getRecords(), AccountBalanceListVo.class);
@ -298,14 +308,17 @@ public class MemberAccountServiceImpl implements IMemberAccountService {
if (member.getPointGet() != null) {
accountPointCountVo.setPointGet(member.getPointGet());
}
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("site_id", param.siteId());
paramsMap.put("member_id", param.memberId());
paramsMap.put("account_type", "point");
paramsMap.put("account_data", 0);
Double use = memberAccountLogMapper.sumAccountData(paramsMap);
if (use != null) {
accountPointCountVo.setUse(Math.abs(use));
MemberAccountLog accountLog = memberAccountLogMapper.selectOne(new QueryWrapper<MemberAccountLog>()
.eq("site_id", param.siteId())
.eq("member_id", param.memberId())
.eq("account_type", AccountTypeEnum.POINT.getType())
.lt("account_data", 0)
.select("SUM(account_data) AS account_data")
.groupBy("member_id")
);
if (accountLog != null) {
accountPointCountVo.setUse(Math.abs(accountLog.getAccountData().doubleValue()));
}
return accountPointCountVo;
}

View File

@ -10,6 +10,8 @@ public class AccountBalanceFlowParam implements ApiBaseParam {
private String accountType = "balance";
private String tradeType;
private String[] createTime;
private String accountDataGt;

View File

@ -10,6 +10,6 @@ public class AccountBalanceListParam implements ApiBaseParam {
private String tradeType;
private String createTime;
private String[] createTime;
}

View File

@ -149,7 +149,7 @@ public class SysVerifyServiceImpl implements ISysVerifyService {
* @param timeoutSeconds
*/
private void createCode(String verifyCode, Map<String, Object> valueMap, Long timeoutSeconds) {
if (timeoutSeconds != null) {
if (timeoutSeconds != null && timeoutSeconds > 0) {
cached.tag(CACHE_VERIFY).put(verifyCode, valueMap, timeoutSeconds);
} else {
cached.tag(CACHE_VERIFY).put(verifyCode, valueMap);

View File

@ -19,6 +19,7 @@ import com.niu.core.service.core.schedule.ICoreScheduleService;
import com.niu.core.service.core.sys.ICoreMenuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.math3.analysis.function.Add;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@ -309,7 +310,9 @@ public class CoreAddonInstallServiceImpl extends CoreAddonBaseService implements
this.installSchedule();
JSONObject addonConfig = this.getAddonConfig(this.getInstallTask().getStr("addon"));
coreAddonService.set(JSONUtil.toBean(addonConfig, Addon.class));
Addon model = JSONUtil.toBean(addonConfig, Addon.class);
model.setIcon("addon/" + model.getKey() + "/icon.png");
coreAddonService.set(model);
ArrayList<String> tips = new ArrayList<String>();
String addon = this.installTask.getStr("addon");

View File

@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.niu.core.common.component.context.WebAppEnvs;
import com.niu.core.common.utils.image.ImageUtils;
import com.niu.core.entity.addon.Addon;
import com.niu.core.enums.addon.AddonStatusEnum;
import com.niu.core.mapper.addon.AddonMapper;
@ -87,6 +88,8 @@ public class CoreAddonServiceImpl extends CoreAddonBaseService implements ICoreA
{
InstallAddonListVo installAddonListVo = new InstallAddonListVo();
BeanUtils.copyProperties(item, installAddonListVo);
installAddonListVo.setIcon(ImageUtils.imageToBase64(new File(WebAppEnvs.get().webRootDownResource, item.getIcon()).getPath()));
installAddonListVo.setCover(ImageUtils.imageToBase64(new File(WebAppEnvs.get().webRootDownResource, item.getCover()).getPath()));
map.put(item.getKey(), installAddonListVo);
}
}

View File

@ -1,7 +1,9 @@
package com.niu.core.service.core.app.tools;
import cn.hutool.core.io.IoUtil;
import com.niu.core.common.component.context.SpringContext;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import java.io.*;
import java.sql.Connection;
@ -34,20 +36,9 @@ public final class SQLScriptRunnerTools {
* @param fileReader
*/
public static void execScript(Reader fileReader) {
try {
Connection connection = (Connection) SpringContext.getBean("dataSourceConnection");
ScriptRunner scriptRunner = new ScriptRunner(connection);
// 设置自动提交为false
scriptRunner.setAutoCommit(false);
// 每条命令间的分隔符
// scriptRunner.setDelimiter(";");
// scriptRunner.setLogWriter(null); //设置普通日志
// scriptRunner.setErrorLogWriter(null); //设置异常日志
scriptRunner.runScript(fileReader);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("执行脚本异常.");
}
JdbcTemplate jdbcTemplate = SpringContext.bean(JdbcTemplate.class);
String sql = IoUtil.read(fileReader);
jdbcTemplate.execute(sql);
}
/**

View File

@ -5,20 +5,24 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.niu.core.common.config.GlobalConfig;
import com.niu.core.common.exception.CommonException;
import com.niu.core.entity.generator.GenerateColumn;
import com.niu.core.entity.generator.GenerateTable;
import com.niu.core.entity.sys.SysMenu;
import com.niu.core.service.core.generator.vo.CoreGenerateColumnVo;
import com.niu.core.service.core.generator.vo.CoreGenerateTemplateVo;
import com.niu.core.service.core.generator.vo.MapperInfoVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.springframework.validation.annotation.Validated;
import java.io.StringWriter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/**
@ -44,9 +48,10 @@ public class CoreGenerateService {
/**
* 加载velocity容器
*
* @return VelocityContext
*/
public static VelocityContext velocityContext (GenerateTable table, List<GenerateColumn> columns) {
public static VelocityContext velocityContext(GenerateTable table, List<GenerateColumn> columns) {
String lowerClassName = StrUtil.toCamelCase(table.getClassName());
String className = StrUtil.upperFirst(lowerClassName);
String addonName = table.getAddonName().equals("") ? "core" : table.getAddonName();
@ -63,14 +68,20 @@ public class CoreGenerateService {
velocityContext.put("className", className);
velocityContext.put("lowerClassName", lowerClassName);
velocityContext.put("addonName", addonName);
velocityContext.put("orderType", table.getOrderType());
velocityContext.put("orderType", table.getOrderType());
velocityContext.put("editType", table.getEditType());
velocityContext.put("adminPath", table.getAddonName().equals("") ? "@/app" : "@/addon/" + table.getAddonName());
velocityContext.put("primaryField", "id");
velocityContext.put("sortColumn", "");
velocityContext.put("strUtil", StrUtil.class);
velocityContext.put("generateService", CoreGenerateService.class);
List<String> dictList = new LinkedList<>();
Map<String, Map> relateList = new HashMap<>();
List<CoreGenerateColumnVo> list = new ArrayList<>();
Integer isSiteId = 0;
for(GenerateColumn column : columns) {
Integer isBigDecimal = 0;
Integer isDate = 0;
for (GenerateColumn column : columns) {
CoreGenerateColumnVo vo = new CoreGenerateColumnVo();
if (column.getIsPk() == 1) {
velocityContext.put("primaryField", column.getColumnName());
@ -79,20 +90,56 @@ public class CoreGenerateService {
velocityContext.put("sortColumn", column.getColumnName());
}
//检测是否存在siteId
if(column.getColumnName().equals("site_id")){
if (column.getColumnName().equals("site_id")) {
isSiteId = 1;
}
if (column.getColumnType().equals("BigDecimal")) {
isBigDecimal = 1;
}
if (column.getColumnType().equals("Date")) {
isDate = 1;
}
BeanUtil.copyProperties(column, vo);
vo.setLowerColumnFiledName(StrUtil.toCamelCase(column.getColumnName()));
vo.setColumnFiledName(StrUtil.upperFirst(StrUtil.toCamelCase(column.getColumnName())));
list.add(vo);
// 数据字典
if (!column.getDictType().isEmpty() && !dictList.contains(column.getDictType())) {
dictList.add(column.getDictType());
}
// 远程下拉
if (!column.getModel().isEmpty()) {
Map<String, Object> relateItem = null;
MapperInfoVo mapperInfo = getMapperInfo(column.getModel());
if (relateList.get(mapperInfo.getTableName()) == null) {
relateItem = new HashMap<>();
relateItem.put("mapper_info", mapperInfo);
List<String> field = new LinkedList<>();
field.add(column.getLabelKey());
field.add(column.getValueKey());
relateItem.put("field", field);
} else {
relateItem = relateList.get(mapperInfo.getTableName());
List<String> field = (List<String>) relateItem.get("field");
if (!field.contains(column.getLabelKey())) field.add(column.getLabelKey());
if (!field.contains(column.getValueKey())) field.add(column.getValueKey());
relateItem.put("field", field);
}
relateList.put(mapperInfo.getTableName(), relateItem);
}
}
if(isSiteId == 1){
if (isSiteId == 1) {
velocityContext.put("isSiteId", 1);
}else{
} else {
velocityContext.put("isSiteId", 0);
}
velocityContext.put("isBigDecimal", isBigDecimal);
velocityContext.put("isDate", isDate);
velocityContext.put("dictList", dictList);
velocityContext.put("relateList", relateList);
velocityContext.put("columns", list);
searchForm(velocityContext, columns);
@ -112,6 +159,7 @@ public class CoreGenerateService {
/**
* 生成搜索表单
*
* @param velocityContext
* @param columns
* @return
@ -131,6 +179,12 @@ public class CoreGenerateService {
String template = column.getViewType();
if (column.getViewType().equals("radio") || column.getViewType().equals("select") || column.getViewType().equals("checkbox")) {
template = "select";
if (!column.getDictType().isEmpty()) {
template = "select2";
}
if (!column.getModel().isEmpty()) {
template = "select3";
}
}
if (column.getQueryType().equals("BETWEEN")) {
template = column.getViewType().equals("datetime") ? "datetime" : "rangeInput";
@ -176,6 +230,12 @@ public class CoreGenerateService {
if (column.getViewType().equals("datetime")) {
template = "datetime";
}
if (!column.getDictType().isEmpty()) {
template = "dictcolumn";
}
if (!column.getModel().isEmpty()) {
template = "relatecolumn";
}
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate("core/generator/vm/admin/table/" + template + ".vm", "UTF-8");
@ -188,6 +248,7 @@ public class CoreGenerateService {
/**
* 生成编辑表单
*
* @param velocityContext
* @param columns
* @return
@ -200,7 +261,7 @@ public class CoreGenerateService {
if (column.getIsPk().equals(1)) {
param.add(column.getColumnName() + ": 0");
}
if (column.getIsInsert().equals(0) || column.getIsUpdate().equals(0) || column.getColumnName().equals("site_id")) {
if (column.getIsPk().equals(1) || column.getIsInsert().equals(0) || column.getIsUpdate().equals(0) || column.getColumnName().equals("site_id")) {
continue;
}
@ -209,6 +270,12 @@ public class CoreGenerateService {
String template = column.getViewType();
if (column.getViewType().equals("radio") || column.getViewType().equals("select") || column.getViewType().equals("checkbox")) {
if (!column.getDictType().isEmpty()) {
template = column.getViewType() + "2";
}
if (!column.getModel().isEmpty()) {
template = column.getViewType() + "3";
}
}
StringWriter sw = new StringWriter();
@ -225,6 +292,7 @@ public class CoreGenerateService {
/**
* 表单验证规则
*
* @param velocityContext
* @param columns
*/
@ -240,7 +308,8 @@ public class CoreGenerateService {
// 验证规则
List<String> validateRule = new LinkedList<>();
if (column.getIsRequired().equals(1)) validateRule.add("{ required: true, message: t('"+ lowerColumnName +"Placeholder'), trigger: 'blur' }");
if (column.getIsRequired().equals(1))
validateRule.add("{ required: true, message: t('" + lowerColumnName + "Placeholder'), trigger: 'blur' }");
if (!column.getValidateType().isEmpty()) {
if (JSONUtil.isJson(column.getValidateType())) {
@ -250,8 +319,8 @@ public class CoreGenerateService {
case "min":
validateRule.add("{ validator: (rule: any, value: string, callback: any) => {" +
"value += ''\n" +
" if (value.length < "+ limit.getInt(0) +") {\n" +
" callback(new Error(t('generateMin') + "+ limit.getInt(0) +" + t('generateUnit')))\n" +
" if (value.length < " + limit.getInt(0) + ") {\n" +
" callback(new Error(t('generateMin') + " + limit.getInt(0) + " + t('generateUnit')))\n" +
" } else {\n" +
" callback()\n" +
" }" +
@ -260,8 +329,8 @@ public class CoreGenerateService {
case "max":
validateRule.add("{ validator: (rule: any, value: string, callback: any) => {" +
"value += ''\n" +
" if (value.length > "+ limit.getInt(0) +") {\n" +
" callback(new Error(t('generateMax') + "+ limit.getInt(0) +" + t('generateUnit')))\n" +
" if (value.length > " + limit.getInt(0) + ") {\n" +
" callback(new Error(t('generateMax') + " + limit.getInt(0) + " + t('generateUnit')))\n" +
" } else {\n" +
" callback()\n" +
" }" +
@ -270,10 +339,10 @@ public class CoreGenerateService {
case "between":
validateRule.add("{ validator: (rule: any, value: string, callback: any) => {" +
"value += ''\n" +
" if (value.length < "+ limit.getInt(0) +") {\n" +
" callback(new Error(t('generateMin') + "+ limit.getInt(0) +" + t('generateUnit')))\n" +
" } else if (value.length > "+ limit.getInt(1) +") {\n" +
" callback(new Error(t('generateMax') + "+ limit.getInt(0) +" + t('generateUnit')))\n" +
" if (value.length < " + limit.getInt(0) + ") {\n" +
" callback(new Error(t('generateMin') + " + limit.getInt(0) + " + t('generateUnit')))\n" +
" } else if (value.length > " + limit.getInt(1) + ") {\n" +
" callback(new Error(t('generateMax') + " + limit.getInt(0) + " + t('generateUnit')))\n" +
" } else {\n" +
" callback()\n" +
" }" +
@ -281,11 +350,12 @@ public class CoreGenerateService {
break;
}
} else {
validateRule.add("{ validator: Validate."+ column.getValidateType() +"Verify, trigger: 'blur' }");
validateRule.add("{ validator: Validate." + column.getValidateType() + "Verify, trigger: 'blur' }");
}
}
if (validateRule.size() > 0) validate.add(column.getColumnName() + ": [\n" + String.join(", \n", validateRule) + "\n]");
if (validateRule.size() > 0)
validate.add(column.getColumnName() + ": [\n" + String.join(", \n", validateRule) + "\n]");
}
velocityContext.put("formValidate", String.join(", \n", validate));
@ -306,12 +376,12 @@ public class CoreGenerateService {
lang.set("add" + className, "添加" + notes);
lang.set("update" + className, "编辑" + notes);
lang.set(lowerClassName + "DeleteTips", "定要刪除" + notes + "吗?");
lang.set(lowerClassName + "DeleteTips", "定要刪除" + notes + "吗?");
for (GenerateColumn column : columns) {
if (column.getIsPk().equals(1) || column.getColumnName().equals("site_id")) continue;
lang.set(StrUtil.toCamelCase(column.getColumnName()), column.getColumnComment());
if (column.getIsInsert().equals(1) || column.getIsUpdate().equals(1)) {
if (column.getIsInsert().equals(1) || column.getIsUpdate().equals(1) || column.getIsSearch().equals(1)) {
String prefix = "请输入";
if (column.getViewType().equals("radio") || column.getViewType().equals("select") || column.getViewType().equals("checkbox")) {
prefix = "请选择";
@ -327,6 +397,7 @@ public class CoreGenerateService {
/**
* 菜单sql
*
* @param velocityContext
*/
public static void menuSql(GenerateTable table, VelocityContext velocityContext) {
@ -346,30 +417,30 @@ public class CoreGenerateService {
String apiUrl = velocityContext.get("addonName").toString() + "/" + velocityContext.get("moduleName").toString() + "/" + velocityContext.get("tableName").toString();
sql.add("DELETE FROM "+ menuTable + " WHERE menu_key in (" + String.join(", ", menuKey.values()) + ");");
sql.add("DELETE FROM " + menuTable + " WHERE menu_key in (" + String.join(", ", menuKey.values()) + ");");
sql.add("INSERT INTO "+ menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '"+ notes +"', '"+ notes +"', "+ menuKey.get("root") + ", '"+ table.getParentMenu() +"', 0, '', '', '', '', '', 100, 1, 1, '"+ table.getAddonName() +"', 'generator');");
sql.add("INSERT INTO " + menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '" + notes + "', '" + notes + "', " + menuKey.get("root") + ", '" + table.getParentMenu() + "', 0, '', '', '', '', '', 100, 1, 1, '" + table.getAddonName() + "', 'generator');");
String routerPath = (table.getAddonName().equals("") ? "" : table.getAddonName() + "/") + table.getModuleName() + (className.equals("") ? "" : "/" + className);
String viewPath = table.getModuleName() +"/"+ table.getClassName();
sql.add("INSERT INTO "+ menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '"+ notes +"列表', '', "+ menuKey.get("list") + ", "+ menuKey.get("root") +", 1, '', '"+ apiUrl + "', '"+ routerPath +"', '"+ viewPath +"', 'get', 100, 1, 1, '"+ table.getAddonName() +"', 'generator');");
String viewPath = table.getModuleName() + "/" + table.getClassName();
sql.add("INSERT INTO " + menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '" + notes + "列表', '', " + menuKey.get("list") + ", " + menuKey.get("root") + ", 1, '', '" + apiUrl + "', '" + routerPath + "', '" + viewPath + "', 'get', 100, 1, 1, '" + table.getAddonName() + "', 'generator');");
sql.add("INSERT INTO "+ menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '"+ notes +"添加', '', "+ menuKey.get("add") + ", "+ menuKey.get("root") +", 2, '', '"+ apiUrl + "', '', '', 'post', 90, 1, 1, '"+ table.getAddonName() +"', 'generator');");
sql.add("INSERT INTO " + menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '" + notes + "添加', '', " + menuKey.get("add") + ", " + menuKey.get("root") + ", 2, '', '" + apiUrl + "', '', '', 'post', 90, 1, 1, '" + table.getAddonName() + "', 'generator');");
sql.add("INSERT INTO "+ menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '"+ notes +"编辑', '', "+ menuKey.get("edit") + ", "+ menuKey.get("root") +", 2, '', '"+ apiUrl + "/<id>', '', '', 'put', 80, 1, 1, '"+ table.getAddonName() +"', 'generator');");
sql.add("INSERT INTO " + menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '" + notes + "编辑', '', " + menuKey.get("edit") + ", " + menuKey.get("root") + ", 2, '', '" + apiUrl + "/<id>', '', '', 'put', 80, 1, 1, '" + table.getAddonName() + "', 'generator');");
sql.add("INSERT INTO "+ menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '"+ notes +"删除', '', "+ menuKey.get("delete") + ", "+ menuKey.get("root") +", 2, '', '"+ apiUrl +"/<id>', '', '', 'delete', 70, 1, 1, '"+ table.getAddonName() +"', 'generator');");
sql.add("INSERT INTO " + menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '" + notes + "删除', '', " + menuKey.get("delete") + ", " + menuKey.get("root") + ", 2, '', '" + apiUrl + "/<id>', '', '', 'delete', 70, 1, 1, '" + table.getAddonName() + "', 'generator');");
if (table.getEditType().equals(2)) {
String editRouterPath = routerPath + "_edit";
String editViewPath = table.getModuleName() +"/"+ table.getClassName() + "_edit";
sql.add("INSERT INTO "+ menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '"+ notes +"添加/编辑', '"+ notes +"', "+ menuKey.get("edit_page") + ", "+ menuKey.get("root") +", 1, '', '"+ apiUrl + "/<id>', '"+ editRouterPath +"', '"+ editViewPath +"', 'get', 100, 1, 0, '"+ table.getAddonName() +"', 'generator');");
String editViewPath = table.getModuleName() + "/" + table.getClassName() + "_edit";
sql.add("INSERT INTO " + menuTable + "(app_type, menu_name, menu_short_name, menu_key, parent_key, menu_type, icon, api_url, router_path, view_path, methods, sort, status, is_show, addon, source) VALUES\n" +
"('site', '" + notes + "添加/编辑', '" + notes + "', " + menuKey.get("edit_page") + ", " + menuKey.get("root") + ", 1, '', '" + apiUrl + "/<id>', '" + editRouterPath + "', '" + editViewPath + "', 'get', 100, 1, 0, '" + table.getAddonName() + "', 'generator');");
}
velocityContext.put("sql", String.join("\n", sql));
@ -377,6 +448,7 @@ public class CoreGenerateService {
/**
* 加载所有模板以及文件
*
* @param table
* @return
*/
@ -387,16 +459,15 @@ public class CoreGenerateService {
String className = StrUtil.upperFirst(lowerClassName);
String javaPath = "niucloud-core/src/main/java/com/niu/core";
if (!addonName.equals("core")) {
javaPath = "niucloud-addon/"+ addonName +"/src/main/java/com/niu/" + addonName;
javaPath = "niucloud-addon/" + addonName + "/src/main/java/com/niu/" + addonName;
}
String adminVueAddonName = table.getAddonName().equals("") ? "app" : table.getAddonName();
String adminVuePath = "";
if(adminVueAddonName.equals("app"))
{
if (adminVueAddonName.equals("app")) {
adminVuePath = "admin/src/" + adminVueAddonName;
}else{
} else {
adminVuePath = "admin/src/addon/" + adminVueAddonName;
}
@ -541,6 +612,7 @@ public class CoreGenerateService {
/**
* 生成对应的code代码
*
* @param table
* @param columns
* @return
@ -566,5 +638,45 @@ public class CoreGenerateService {
return list;
}
public static MapperInfoVo getMapperInfo(String mapper) {
MapperInfoVo vo = new MapperInfoVo();
try {
Class<?> mapperClass = Class.forName(mapper);
if (!mapperClass.isInterface() || !mapperClass.isAnnotationPresent(Mapper.class)) {
throw new CommonException("提供的类不是有效的MyBatis Mapper接口");
}
String tableName = "";
Type[] types = mapperClass.getGenericInterfaces();
for (Type type : types) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length == 1) {
Class<?> entityClass = (Class<?>) actualTypeArguments[0];
TableName tableNameAnnotation = entityClass.getAnnotation(TableName.class);
// 通过@TableName 注解获取表名
if (tableNameAnnotation != null) {
tableName = tableNameAnnotation.value();
} else {
// 如果没有 @TableName 注解使用实体类的简单名称作为表名
tableName = StrUtil.toUnderlineCase(entityClass.getSimpleName());
}
vo.setMapperName(mapperClass.getSimpleName());
vo.setEntity(entityClass.getName());
vo.setEntityName(entityClass.getSimpleName());
}
}
}
if (tableName.isEmpty()) throw new CommonException("未能通过mapper获取到表信息");
vo.setTableName(tableName);
vo.setMapper(mapper);
return vo;
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
}

View File

@ -0,0 +1,21 @@
package com.niu.core.service.core.generator.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class MapperInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
private String mapper;
private String mapperName;
private String tableName;
private String entityName;
private String entity;
}

Some files were not shown because too many files have changed in this diff Show More