1
This commit is contained in:
53
_script/add_authorization_fields.sql
Normal file
53
_script/add_authorization_fields.sql
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
-- 为 pla_account 表添加授权相关字段
|
||||||
|
-- 执行时间:2025-01-XX
|
||||||
|
-- 说明:添加授权日期和授权天数字段,用于控制账号的使用期限
|
||||||
|
|
||||||
|
-- 检查并添加授权日期字段
|
||||||
|
SET @dbname = DATABASE();
|
||||||
|
SET @tablename = 'pla_account';
|
||||||
|
SET @columnname = 'authorization_date';
|
||||||
|
SET @preparedStatement = (SELECT IF(
|
||||||
|
(
|
||||||
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
(TABLE_SCHEMA = @dbname)
|
||||||
|
AND (TABLE_NAME = @tablename)
|
||||||
|
AND (COLUMN_NAME = @columnname)
|
||||||
|
) > 0,
|
||||||
|
'SELECT 1', -- 字段已存在,不执行任何操作
|
||||||
|
CONCAT('ALTER TABLE `', @tablename, '` ADD COLUMN `', @columnname, '` DATETIME NULL COMMENT ''授权日期(授权开始时间)'' AFTER `active_actions`;')
|
||||||
|
));
|
||||||
|
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||||
|
EXECUTE alterIfNotExists;
|
||||||
|
DEALLOCATE PREPARE alterIfNotExists;
|
||||||
|
|
||||||
|
-- 检查并添加授权天数字段
|
||||||
|
SET @columnname = 'authorization_days';
|
||||||
|
SET @preparedStatement = (SELECT IF(
|
||||||
|
(
|
||||||
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
(TABLE_SCHEMA = @dbname)
|
||||||
|
AND (TABLE_NAME = @tablename)
|
||||||
|
AND (COLUMN_NAME = @columnname)
|
||||||
|
) > 0,
|
||||||
|
'SELECT 1', -- 字段已存在,不执行任何操作
|
||||||
|
CONCAT('ALTER TABLE `', @tablename, '` ADD COLUMN `', @columnname, '` INT(11) NOT NULL DEFAULT 0 COMMENT ''授权天数'' AFTER `authorization_date`;')
|
||||||
|
));
|
||||||
|
PREPARE alterIfNotExists FROM @preparedStatement;
|
||||||
|
EXECUTE alterIfNotExists;
|
||||||
|
DEALLOCATE PREPARE alterIfNotExists;
|
||||||
|
|
||||||
|
-- 验证字段是否添加成功
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME AS '字段名',
|
||||||
|
DATA_TYPE AS '数据类型',
|
||||||
|
IS_NULLABLE AS '允许NULL',
|
||||||
|
COLUMN_DEFAULT AS '默认值',
|
||||||
|
COLUMN_COMMENT AS '注释'
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'pla_account'
|
||||||
|
AND COLUMN_NAME IN ('authorization_date', 'authorization_days')
|
||||||
|
ORDER BY ORDINAL_POSITION;
|
||||||
|
|
||||||
12
_script/add_authorization_fields_simple.sql
Normal file
12
_script/add_authorization_fields_simple.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- 为 pla_account 表添加授权相关字段(简化版)
|
||||||
|
-- 执行时间:2025-01-XX
|
||||||
|
-- 说明:如果字段已存在会报错,可以先执行上面的版本(带检查的版本)
|
||||||
|
|
||||||
|
-- 添加授权日期字段
|
||||||
|
ALTER TABLE `pla_account`
|
||||||
|
ADD COLUMN `authorization_date` DATETIME NULL COMMENT '授权日期(授权开始时间)' AFTER `active_actions`;
|
||||||
|
|
||||||
|
-- 添加授权天数字段
|
||||||
|
ALTER TABLE `pla_account`
|
||||||
|
ADD COLUMN `authorization_days` INT(11) NOT NULL DEFAULT 0 COMMENT '授权天数' AFTER `authorization_date`;
|
||||||
|
|
||||||
@@ -26,11 +26,11 @@ const baseConfig = {
|
|||||||
// 开发环境配置
|
// 开发环境配置
|
||||||
const developmentConfig = {
|
const developmentConfig = {
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
// apiUrl: 'http://localhost:9097/admin_api/',
|
apiUrl: 'http://localhost:9097/admin_api/',
|
||||||
// uploadUrl: 'http://localhost:9097/admin_api/upload',
|
uploadUrl: 'http://localhost:9097/admin_api/upload',
|
||||||
|
|
||||||
apiUrl: 'https://work.light120.com/admin_api/',
|
// apiUrl: 'https://work.light120.com/admin_api/',
|
||||||
uploadUrl: 'https://work.light120.com/admin_api/upload',
|
// uploadUrl: 'https://work.light120.com/admin_api/upload',
|
||||||
// 开发环境显示更多调试信息
|
// 开发环境显示更多调试信息
|
||||||
debug: true
|
debug: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,6 +163,29 @@ class PlaAccountServer {
|
|||||||
batchParseLocation(ids) {
|
batchParseLocation(ids) {
|
||||||
return window.framework.http.post('/pla_account/batchParseLocation', { ids })
|
return window.framework.http.post('/pla_account/batchParseLocation', { ids })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查账号授权状态
|
||||||
|
* @param {Object} param - 参数对象
|
||||||
|
* @param {Number|String} param.id - 账号ID(可选)
|
||||||
|
* @param {String} param.sn_code - 设备SN码(可选)
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
checkAuthorization(param) {
|
||||||
|
return window.framework.http.post('/account/check-authorization', param)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新账号授权信息
|
||||||
|
* @param {Object} param - 参数对象
|
||||||
|
* @param {Number|String} param.id - 账号ID
|
||||||
|
* @param {String} param.authorization_date - 授权日期(可选,不提供则使用当前时间)
|
||||||
|
* @param {Number} param.authorization_days - 授权天数
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
updateAuthorization(param) {
|
||||||
|
return window.framework.http.post('/account/update-authorization', param)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new PlaAccountServer()
|
export default new PlaAccountServer()
|
||||||
|
|||||||
@@ -49,6 +49,56 @@
|
|||||||
<!-- 编辑组件(使用 FloatPanel,包含所有字段) -->
|
<!-- 编辑组件(使用 FloatPanel,包含所有字段) -->
|
||||||
<PlaAccountEdit ref="accountEdit" @on-save="handleSaveSuccess" />
|
<PlaAccountEdit ref="accountEdit" @on-save="handleSaveSuccess" />
|
||||||
|
|
||||||
|
<!-- 授权设置弹窗 -->
|
||||||
|
<Modal
|
||||||
|
v-model="authorizationModal.visible"
|
||||||
|
title="设置授权"
|
||||||
|
:mask-closable="false"
|
||||||
|
width="600"
|
||||||
|
@on-ok="handleSaveAuthorization"
|
||||||
|
@on-cancel="handleCancelAuthorization"
|
||||||
|
>
|
||||||
|
<Form ref="authorizationForm" :model="authorizationModal.formData" :label-width="120">
|
||||||
|
<FormItem label="账号名称">
|
||||||
|
<Input v-model="authorizationModal.formData.accountName" disabled />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="设备SN码">
|
||||||
|
<Input v-model="authorizationModal.formData.sn_code" disabled />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="授权日期">
|
||||||
|
<DatePicker
|
||||||
|
v-model="authorizationModal.formData.authorization_date"
|
||||||
|
type="date"
|
||||||
|
placeholder="请选择授权日期(不选择则使用当前时间)"
|
||||||
|
style="width: 100%;"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="授权天数">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
|
||||||
|
<InputNumber
|
||||||
|
v-model="authorizationModal.formData.authorization_days"
|
||||||
|
:min="0"
|
||||||
|
placeholder="请输入授权天数"
|
||||||
|
style="width: 200px;"
|
||||||
|
/>
|
||||||
|
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
||||||
|
<Button size="small" @click="setQuickAuthorizationDays(7)">7天</Button>
|
||||||
|
<Button size="small" @click="setQuickAuthorizationDays(30)">30天</Button>
|
||||||
|
<Button size="small" @click="setQuickAuthorizationDays(90)">90天</Button>
|
||||||
|
<Button size="small" @click="setQuickAuthorizationDays(180)">180天</Button>
|
||||||
|
<Button size="small" @click="setQuickAuthorizationDays(365)">365天</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="过期时间" v-if="authorizationModal.formData.authorization_date && authorizationModal.formData.authorization_days">
|
||||||
|
<span :style="{ color: getExpireDateColor(authorizationModal.formData) }">
|
||||||
|
{{ getExpireDate(authorizationModal.formData) }}
|
||||||
|
</span>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<!-- 简历详情弹窗 -->
|
<!-- 简历详情弹窗 -->
|
||||||
<Modal v-model="resumeModal.visible" :title="resumeModal.title" width="900" :footer-hide="true">
|
<Modal v-model="resumeModal.visible" :title="resumeModal.title" width="900" :footer-hide="true">
|
||||||
<div v-if="resumeModal.loading" style="text-align: center; padding: 40px;">
|
<div v-if="resumeModal.loading" style="text-align: center; padding: 40px;">
|
||||||
@@ -253,6 +303,16 @@ export default {
|
|||||||
title: '在线简历详情',
|
title: '在线简历详情',
|
||||||
data: null
|
data: null
|
||||||
},
|
},
|
||||||
|
authorizationModal: {
|
||||||
|
visible: false,
|
||||||
|
formData: {
|
||||||
|
id: null,
|
||||||
|
accountName: '',
|
||||||
|
sn_code: '',
|
||||||
|
authorization_date: null,
|
||||||
|
authorization_days: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
gridOption: {
|
gridOption: {
|
||||||
param: {
|
param: {
|
||||||
seachOption: {
|
seachOption: {
|
||||||
@@ -356,6 +416,51 @@ export default {
|
|||||||
}, params.row.auto_chat ? '开启' : '关闭')
|
}, params.row.auto_chat ? '开启' : '关闭')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '剩余天数',
|
||||||
|
key: 'remaining_days',
|
||||||
|
minWidth: 100,
|
||||||
|
render: (h, params) => {
|
||||||
|
const remainingDays = params.row.remaining_days || 0
|
||||||
|
let color = 'success'
|
||||||
|
if (remainingDays <= 0) {
|
||||||
|
color = 'error'
|
||||||
|
} else if (remainingDays <= 7) {
|
||||||
|
color = 'warning'
|
||||||
|
}
|
||||||
|
return h('Tag', {
|
||||||
|
props: { color: color }
|
||||||
|
}, remainingDays > 0 ? `${remainingDays} 天` : '已过期')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '授权日期',
|
||||||
|
key: 'authorization_date',
|
||||||
|
minWidth: 150,
|
||||||
|
render: (h, params) => {
|
||||||
|
if (!params.row.authorization_date) {
|
||||||
|
return h('span', { style: { color: '#999' } }, '未授权')
|
||||||
|
}
|
||||||
|
const date = new Date(params.row.authorization_date)
|
||||||
|
return h('span', this.formatDate(date))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '过期时间',
|
||||||
|
key: 'expire_date',
|
||||||
|
minWidth: 150,
|
||||||
|
render: (h, params) => {
|
||||||
|
if (!params.row.authorization_date || !params.row.authorization_days) {
|
||||||
|
return h('span', { style: { color: '#999' } }, '未授权')
|
||||||
|
}
|
||||||
|
const authDate = new Date(params.row.authorization_date)
|
||||||
|
const expireDate = new Date(authDate.getTime() + params.row.authorization_days * 24 * 60 * 60 * 1000)
|
||||||
|
const remainingDays = params.row.remaining_days || 0
|
||||||
|
return h('span', {
|
||||||
|
style: { color: remainingDays <= 0 ? '#ed4014' : remainingDays <= 7 ? '#ff9900' : '#515a6e' }
|
||||||
|
}, this.formatDate(expireDate))
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '自动活跃',
|
title: '自动活跃',
|
||||||
key: 'auto_active',
|
key: 'auto_active',
|
||||||
@@ -418,6 +523,13 @@ export default {
|
|||||||
this.showEditWarp(params.row)
|
this.showEditWarp(params.row)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '设置授权',
|
||||||
|
type: 'warning',
|
||||||
|
click: () => {
|
||||||
|
this.showAuthorizationModal(params.row)
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '解析位置',
|
title: '解析位置',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
@@ -597,6 +709,108 @@ export default {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 格式化日期
|
||||||
|
formatDate(date) {
|
||||||
|
if (!date) return '-'
|
||||||
|
const d = new Date(date)
|
||||||
|
const year = d.getFullYear()
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
},
|
||||||
|
// 显示授权设置弹窗
|
||||||
|
showAuthorizationModal(row) {
|
||||||
|
this.authorizationModal.formData = {
|
||||||
|
id: row.id,
|
||||||
|
accountName: row.name,
|
||||||
|
sn_code: row.sn_code,
|
||||||
|
// 如果有授权日期则使用,否则默认使用当天
|
||||||
|
authorization_date: row.authorization_date ? new Date(row.authorization_date) : new Date(),
|
||||||
|
authorization_days: row.authorization_days || 0
|
||||||
|
}
|
||||||
|
this.authorizationModal.visible = true
|
||||||
|
},
|
||||||
|
// 设置快捷授权天数
|
||||||
|
setQuickAuthorizationDays(days) {
|
||||||
|
this.authorizationModal.formData.authorization_days = days
|
||||||
|
// 如果没有设置授权日期,自动设置为当前日期
|
||||||
|
if (!this.authorizationModal.formData.authorization_date) {
|
||||||
|
this.authorizationModal.formData.authorization_date = new Date()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 保存授权信息
|
||||||
|
async handleSaveAuthorization() {
|
||||||
|
if (!this.authorizationModal.formData.id) {
|
||||||
|
this.$Message.error('账号ID不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.authorizationModal.formData.authorization_days || this.authorizationModal.formData.authorization_days <= 0) {
|
||||||
|
this.$Message.error('请输入授权天数')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const param = {
|
||||||
|
id: this.authorizationModal.formData.id,
|
||||||
|
authorization_days: this.authorizationModal.formData.authorization_days
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果设置了授权日期,添加到参数中
|
||||||
|
if (this.authorizationModal.formData.authorization_date) {
|
||||||
|
param.authorization_date = this.authorizationModal.formData.authorization_date
|
||||||
|
}
|
||||||
|
|
||||||
|
await plaAccountServer.updateAuthorization(param)
|
||||||
|
this.$Message.success('授权设置成功!')
|
||||||
|
this.authorizationModal.visible = false
|
||||||
|
// 刷新列表
|
||||||
|
this.query(this.gridOption.param.pageOption.page || 1)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('设置授权失败:', error)
|
||||||
|
this.$Message.error('设置授权失败:' + (error.message || '请稍后重试'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 取消授权设置
|
||||||
|
handleCancelAuthorization() {
|
||||||
|
this.authorizationModal.visible = false
|
||||||
|
this.authorizationModal.formData = {
|
||||||
|
id: null,
|
||||||
|
accountName: '',
|
||||||
|
sn_code: '',
|
||||||
|
authorization_date: null,
|
||||||
|
authorization_days: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取过期时间
|
||||||
|
getExpireDate(formData) {
|
||||||
|
if (!formData.authorization_date || !formData.authorization_days) {
|
||||||
|
return '未授权'
|
||||||
|
}
|
||||||
|
const authDate = new Date(formData.authorization_date)
|
||||||
|
const expireDate = new Date(authDate.getTime() + formData.authorization_days * 24 * 60 * 60 * 1000)
|
||||||
|
const year = expireDate.getFullYear()
|
||||||
|
const month = String(expireDate.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(expireDate.getDate()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
},
|
||||||
|
// 获取过期时间颜色
|
||||||
|
getExpireDateColor(formData) {
|
||||||
|
if (!formData.authorization_date || !formData.authorization_days) {
|
||||||
|
return '#999'
|
||||||
|
}
|
||||||
|
const authDate = new Date(formData.authorization_date)
|
||||||
|
const expireDate = new Date(authDate.getTime() + formData.authorization_days * 24 * 60 * 60 * 1000)
|
||||||
|
const now = new Date()
|
||||||
|
const remaining = Math.ceil((expireDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000))
|
||||||
|
if (remaining <= 0) {
|
||||||
|
return '#ed4014'
|
||||||
|
} else if (remaining <= 7) {
|
||||||
|
return '#ff9900'
|
||||||
|
} else {
|
||||||
|
return '#515a6e'
|
||||||
|
}
|
||||||
|
},
|
||||||
// 解析工作经历
|
// 解析工作经历
|
||||||
parseWorkExp(workExp) {
|
parseWorkExp(workExp) {
|
||||||
if (!workExp) return []
|
if (!workExp) return []
|
||||||
|
|||||||
@@ -92,6 +92,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<!-- 授权信息卡片 -->
|
||||||
|
<Card class="config-card" title="授权信息" :bordered="false" style="margin-bottom: 16px;">
|
||||||
|
<Row :gutter="16">
|
||||||
|
<Col span="8">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="label">授权日期:</span>
|
||||||
|
<span class="value">{{ formatDateTime(accountInfo.authorization_date) || '未授权' }}</span>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col span="8">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="label">授权天数:</span>
|
||||||
|
<span class="value">{{ accountInfo.authorization_days || 0 }} 天</span>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col span="8">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="label">剩余天数:</span>
|
||||||
|
<span class="value">
|
||||||
|
<Tag :color="getRemainingDaysColor(accountInfo.remaining_days)">
|
||||||
|
{{ accountInfo.remaining_days || 0 }} 天
|
||||||
|
</Tag>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row :gutter="16" style="margin-top: 12px;">
|
||||||
|
<Col span="8">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="label">过期时间:</span>
|
||||||
|
<span class="value" :class="{'text-danger': isExpired(accountInfo)}">
|
||||||
|
{{ getExpireDate(accountInfo) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col span="8">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="label">授权状态:</span>
|
||||||
|
<span class="value">
|
||||||
|
<Tag :color="getAuthorizationStatusColor(accountInfo)">
|
||||||
|
{{ getAuthorizationStatus(accountInfo) }}
|
||||||
|
</Tag>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<!-- 配置信息卡片 -->
|
<!-- 配置信息卡片 -->
|
||||||
<Card class="config-card" title="基础配置" :bordered="false" style="margin-bottom: 16px;">
|
<Card class="config-card" title="基础配置" :bordered="false" style="margin-bottom: 16px;">
|
||||||
<Row :gutter="16">
|
<Row :gutter="16">
|
||||||
@@ -177,13 +225,13 @@
|
|||||||
<span class="value">{{ deliverConfig.max_deliver || '-' }}</span>
|
<span class="value">{{ deliverConfig.max_deliver || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span="12">
|
<Col span="8">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="label">过滤关键词:</span>
|
<span class="label">过滤关键词:</span>
|
||||||
<span class="value">{{ deliverConfig.filter_keywords || '-' }}</span>
|
<span class="value">{{ deliverConfig.filter_keywords || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span="12">
|
<Col span="8">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="label">排除关键词:</span>
|
<span class="label">排除关键词:</span>
|
||||||
<span class="value">{{ deliverConfig.exclude_keywords || '-' }}</span>
|
<span class="value">{{ deliverConfig.exclude_keywords || '-' }}</span>
|
||||||
@@ -1371,6 +1419,63 @@ export default {
|
|||||||
this.$Message.warning('二维码图片加载失败,请刷新重试')
|
this.$Message.warning('二维码图片加载失败,请刷新重试')
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 获取剩余天数颜色
|
||||||
|
getRemainingDaysColor(remainingDays) {
|
||||||
|
if (!remainingDays || remainingDays <= 0) {
|
||||||
|
return 'error'
|
||||||
|
} else if (remainingDays <= 7) {
|
||||||
|
return 'warning'
|
||||||
|
} else {
|
||||||
|
return 'success'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取过期时间
|
||||||
|
getExpireDate(accountInfo) {
|
||||||
|
if (!accountInfo.authorization_date || !accountInfo.authorization_days) {
|
||||||
|
return '未授权'
|
||||||
|
}
|
||||||
|
const authDate = new Date(accountInfo.authorization_date)
|
||||||
|
const expireDate = new Date(authDate.getTime() + accountInfo.authorization_days * 24 * 60 * 60 * 1000)
|
||||||
|
return this.formatDateTime(expireDate)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 判断是否过期
|
||||||
|
isExpired(accountInfo) {
|
||||||
|
const remainingDays = accountInfo.remaining_days || 0
|
||||||
|
return remainingDays <= 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取授权状态
|
||||||
|
getAuthorizationStatus(accountInfo) {
|
||||||
|
if (!accountInfo.authorization_date || !accountInfo.authorization_days) {
|
||||||
|
return '未授权'
|
||||||
|
}
|
||||||
|
const remainingDays = accountInfo.remaining_days || 0
|
||||||
|
if (remainingDays <= 0) {
|
||||||
|
return '已过期'
|
||||||
|
} else if (remainingDays <= 7) {
|
||||||
|
return '即将过期'
|
||||||
|
} else {
|
||||||
|
return '正常'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取授权状态颜色
|
||||||
|
getAuthorizationStatusColor(accountInfo) {
|
||||||
|
if (!accountInfo.authorization_date || !accountInfo.authorization_days) {
|
||||||
|
return 'default'
|
||||||
|
}
|
||||||
|
const remainingDays = accountInfo.remaining_days || 0
|
||||||
|
if (remainingDays <= 0) {
|
||||||
|
return 'error'
|
||||||
|
} else if (remainingDays <= 7) {
|
||||||
|
return 'warning'
|
||||||
|
} else {
|
||||||
|
return 'success'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// 格式化日期时间
|
// 格式化日期时间
|
||||||
formatDateTime(datetime) {
|
formatDateTime(datetime) {
|
||||||
if (!datetime) return '-'
|
if (!datetime) return '-'
|
||||||
|
|||||||
@@ -56,6 +56,45 @@
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card title="授权信息" style="margin-bottom: 16px;">
|
||||||
|
<FormItem label="授权日期">
|
||||||
|
<DatePicker
|
||||||
|
v-model="formData.authorization_date"
|
||||||
|
type="date"
|
||||||
|
placeholder="请选择授权日期(不选择则使用当前时间)"
|
||||||
|
style="width: 100%;"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="授权天数">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
|
||||||
|
<InputNumber
|
||||||
|
v-model="formData.authorization_days"
|
||||||
|
:min="0"
|
||||||
|
placeholder="请输入授权天数"
|
||||||
|
style="width: 200px;"
|
||||||
|
/>
|
||||||
|
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
||||||
|
<Button size="small" @click="setAuthorizationDays(7)">7天</Button>
|
||||||
|
<Button size="small" @click="setAuthorizationDays(30)">30天</Button>
|
||||||
|
<Button size="small" @click="setAuthorizationDays(90)">90天</Button>
|
||||||
|
<Button size="small" @click="setAuthorizationDays(180)">180天</Button>
|
||||||
|
<Button size="small" @click="setAuthorizationDays(365)">365天</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="剩余天数" v-if="formData.remaining_days !== undefined">
|
||||||
|
<span :style="{ color: getRemainingDaysColor(formData.remaining_days) }">
|
||||||
|
{{ formData.remaining_days || 0 }} 天
|
||||||
|
</span>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="过期时间" v-if="formData.authorization_date && formData.authorization_days">
|
||||||
|
<span :style="{ color: getExpireDateColor(formData) }">
|
||||||
|
{{ getExpireDate(formData) }}
|
||||||
|
</span>
|
||||||
|
</FormItem>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card title="排序优先级配置" style="margin-bottom: 16px;">
|
<Card title="排序优先级配置" style="margin-bottom: 16px;">
|
||||||
<FormItem label="排序优先级">
|
<FormItem label="排序优先级">
|
||||||
<div class="priority-config">
|
<div class="priority-config">
|
||||||
@@ -230,7 +269,11 @@ export default {
|
|||||||
chat_workdays_only: 1,
|
chat_workdays_only: 1,
|
||||||
auto_active: 0,
|
auto_active: 0,
|
||||||
active_interval: 60,
|
active_interval: 60,
|
||||||
active_actions_json: ''
|
active_actions_json: '',
|
||||||
|
// 授权相关字段
|
||||||
|
authorization_date: null,
|
||||||
|
authorization_days: 0,
|
||||||
|
remaining_days: 0
|
||||||
},
|
},
|
||||||
// 排序优先级列表
|
// 排序优先级列表
|
||||||
priorityList: [
|
priorityList: [
|
||||||
@@ -284,6 +327,16 @@ export default {
|
|||||||
},
|
},
|
||||||
// 处理 JSON 配置字段
|
// 处理 JSON 配置字段
|
||||||
processJsonFields(row) {
|
processJsonFields(row) {
|
||||||
|
// 处理授权信息
|
||||||
|
if (row.authorization_date) {
|
||||||
|
this.formData.authorization_date = new Date(row.authorization_date)
|
||||||
|
} else {
|
||||||
|
// 如果没有授权日期,默认使用当天
|
||||||
|
this.formData.authorization_date = new Date()
|
||||||
|
}
|
||||||
|
this.formData.authorization_days = row.authorization_days || 0
|
||||||
|
this.formData.remaining_days = row.remaining_days || 0
|
||||||
|
|
||||||
// is_salary_priority 配置
|
// is_salary_priority 配置
|
||||||
if (row.is_salary_priority) {
|
if (row.is_salary_priority) {
|
||||||
const priorityConfig = typeof row.is_salary_priority === 'string'
|
const priorityConfig = typeof row.is_salary_priority === 'string'
|
||||||
@@ -400,6 +453,56 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 获取过期时间
|
||||||
|
getExpireDate(formData) {
|
||||||
|
if (!formData.authorization_date || !formData.authorization_days) {
|
||||||
|
return '未授权'
|
||||||
|
}
|
||||||
|
const authDate = new Date(formData.authorization_date)
|
||||||
|
const expireDate = new Date(authDate.getTime() + formData.authorization_days * 24 * 60 * 60 * 1000)
|
||||||
|
const year = expireDate.getFullYear()
|
||||||
|
const month = String(expireDate.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(expireDate.getDate()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
},
|
||||||
|
// 获取过期时间颜色
|
||||||
|
getExpireDateColor(formData) {
|
||||||
|
const remainingDays = formData.remaining_days || 0
|
||||||
|
if (remainingDays <= 0) {
|
||||||
|
return '#ed4014'
|
||||||
|
} else if (remainingDays <= 7) {
|
||||||
|
return '#ff9900'
|
||||||
|
} else {
|
||||||
|
return '#515a6e'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取剩余天数颜色
|
||||||
|
getRemainingDaysColor(remainingDays) {
|
||||||
|
if (!remainingDays || remainingDays <= 0) {
|
||||||
|
return '#ed4014'
|
||||||
|
} else if (remainingDays <= 7) {
|
||||||
|
return '#ff9900'
|
||||||
|
} else {
|
||||||
|
return '#19be6b'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 设置授权天数(快捷按钮)
|
||||||
|
setAuthorizationDays(days) {
|
||||||
|
this.formData.authorization_days = days
|
||||||
|
// 如果没有设置授权日期,自动设置为当前日期
|
||||||
|
if (!this.formData.authorization_date) {
|
||||||
|
this.formData.authorization_date = new Date()
|
||||||
|
}
|
||||||
|
// 计算剩余天数(如果已有授权日期)
|
||||||
|
if (this.formData.authorization_date && days > 0) {
|
||||||
|
const authDate = new Date(this.formData.authorization_date)
|
||||||
|
const expireDate = new Date(authDate.getTime() + days * 24 * 60 * 60 * 1000)
|
||||||
|
const now = new Date()
|
||||||
|
const remaining = Math.ceil((expireDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000))
|
||||||
|
this.formData.remaining_days = Math.max(0, remaining)
|
||||||
|
}
|
||||||
|
this.$Message.success(`已设置授权天数为 ${days} 天`)
|
||||||
|
},
|
||||||
// 返回
|
// 返回
|
||||||
handleBack() {
|
handleBack() {
|
||||||
this.$refs.floatPanel.hide()
|
this.$refs.floatPanel.hide()
|
||||||
|
|||||||
@@ -509,6 +509,158 @@ module.exports = {
|
|||||||
const { ids } = body;
|
const { ids } = body;
|
||||||
const result = await plaAccountService.batchParseLocation(ids);
|
const result = await plaAccountService.batchParseLocation(ids);
|
||||||
return ctx.success(result);
|
return ctx.success(result);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /admin_api/account/check-authorization:
|
||||||
|
* post:
|
||||||
|
* summary: 检查账号授权状态
|
||||||
|
* description: 根据账号ID或SN码检查账号的授权状态(剩余天数、是否过期等)
|
||||||
|
* tags: [后台-账号管理]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* id:
|
||||||
|
* type: integer
|
||||||
|
* description: 账号ID(可选,如果提供id则不需要sn_code)
|
||||||
|
* sn_code:
|
||||||
|
* type: string
|
||||||
|
* description: 设备SN码(可选,如果提供sn_code则不需要id)
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 检查成功
|
||||||
|
*/
|
||||||
|
'POST /account/check-authorization': async (ctx) => {
|
||||||
|
const { id, sn_code } = ctx.getBody();
|
||||||
|
const models = await Framework.getModels();
|
||||||
|
const { pla_account } = models;
|
||||||
|
const dayjs = require('dayjs');
|
||||||
|
|
||||||
|
if (!id && !sn_code) {
|
||||||
|
return ctx.fail('请提供账号ID或SN码');
|
||||||
|
}
|
||||||
|
|
||||||
|
const where = id ? { id } : { sn_code };
|
||||||
|
const account = await pla_account.findOne({ where });
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
return ctx.fail('账号不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountData = account.toJSON();
|
||||||
|
const authDate = accountData.authorization_date;
|
||||||
|
const authDays = accountData.authorization_days || 0;
|
||||||
|
|
||||||
|
// 计算剩余天数
|
||||||
|
let remaining_days = 0;
|
||||||
|
let is_expired = false;
|
||||||
|
let end_date = null;
|
||||||
|
|
||||||
|
if (authDate && authDays > 0) {
|
||||||
|
const startDate = dayjs(authDate);
|
||||||
|
end_date = startDate.add(authDays, 'day').toDate();
|
||||||
|
const now = dayjs();
|
||||||
|
const remaining = dayjs(end_date).diff(now, 'day', true);
|
||||||
|
remaining_days = Math.max(0, Math.ceil(remaining));
|
||||||
|
is_expired = remaining_days <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
id: accountData.id,
|
||||||
|
sn_code: accountData.sn_code,
|
||||||
|
name: accountData.name,
|
||||||
|
authorization_date: authDate,
|
||||||
|
authorization_days: authDays,
|
||||||
|
remaining_days: remaining_days,
|
||||||
|
end_date: end_date,
|
||||||
|
is_expired: is_expired,
|
||||||
|
is_authorized: !is_expired && remaining_days > 0
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /admin_api/account/update-authorization:
|
||||||
|
* post:
|
||||||
|
* summary: 更新账号授权信息
|
||||||
|
* description: 更新账号的授权日期和授权天数
|
||||||
|
* tags: [后台-账号管理]
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - id
|
||||||
|
* properties:
|
||||||
|
* id:
|
||||||
|
* type: integer
|
||||||
|
* description: 账号ID
|
||||||
|
* authorization_date:
|
||||||
|
* type: string
|
||||||
|
* format: date-time
|
||||||
|
* description: 授权日期(可选,不提供则使用当前时间)
|
||||||
|
* authorization_days:
|
||||||
|
* type: integer
|
||||||
|
* description: 授权天数(必填)
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: 更新成功
|
||||||
|
*/
|
||||||
|
'POST /account/update-authorization': async (ctx) => {
|
||||||
|
const { id, authorization_date, authorization_days } = ctx.getBody();
|
||||||
|
const models = await Framework.getModels();
|
||||||
|
const { pla_account } = models;
|
||||||
|
const dayjs = require('dayjs');
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return ctx.fail('账号ID不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authorization_days === undefined || authorization_days === null) {
|
||||||
|
return ctx.fail('授权天数不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authorization_days < 0) {
|
||||||
|
return ctx.fail('授权天数不能为负数');
|
||||||
|
}
|
||||||
|
|
||||||
|
const account = await pla_account.findOne({ where: { id } });
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
return ctx.fail('账号不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果提供了授权日期,使用提供的日期;否则使用当前时间
|
||||||
|
const authDate = authorization_date ? new Date(authorization_date) : new Date();
|
||||||
|
|
||||||
|
await account.update({
|
||||||
|
authorization_date: authDate,
|
||||||
|
authorization_days: authorization_days
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算更新后的剩余天数
|
||||||
|
const end_date = dayjs(authDate).add(authorization_days, 'day').toDate();
|
||||||
|
const now = dayjs();
|
||||||
|
const remaining = dayjs(end_date).diff(now, 'day', true);
|
||||||
|
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||||||
|
|
||||||
|
return ctx.success({
|
||||||
|
message: '授权信息更新成功',
|
||||||
|
data: {
|
||||||
|
id: account.id,
|
||||||
|
authorization_date: authDate,
|
||||||
|
authorization_days: authorization_days,
|
||||||
|
remaining_days: remaining_days,
|
||||||
|
end_date: end_date
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ module.exports = {
|
|||||||
"POST /user/login": async (ctx) => {
|
"POST /user/login": async (ctx) => {
|
||||||
|
|
||||||
const { sn_code, device_id } = ctx.getBody();
|
const { sn_code, device_id } = ctx.getBody();
|
||||||
|
const dayjs = require('dayjs');
|
||||||
|
|
||||||
const { pla_account,device_status} = await Framework.getModels();
|
const { pla_account,device_status} = await Framework.getModels();
|
||||||
|
|
||||||
@@ -79,6 +80,26 @@ module.exports = {
|
|||||||
return ctx.fail('用户不存在');
|
return ctx.fail('用户不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查授权状态
|
||||||
|
const userData = user.toJSON();
|
||||||
|
const authDate = userData.authorization_date;
|
||||||
|
const authDays = userData.authorization_days || 0;
|
||||||
|
|
||||||
|
if (authDate && authDays > 0) {
|
||||||
|
const startDate = dayjs(authDate);
|
||||||
|
const endDate = startDate.add(authDays, 'day');
|
||||||
|
const now = dayjs();
|
||||||
|
const remaining = endDate.diff(now, 'day', true);
|
||||||
|
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||||||
|
|
||||||
|
if (remaining_days <= 0) {
|
||||||
|
return ctx.fail('账号授权已过期,请联系管理员续费');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有授权信息,检查是否允许登录(可以根据业务需求决定是否允许)
|
||||||
|
// 这里暂时允许登录,但可以添加配置项控制
|
||||||
|
}
|
||||||
|
|
||||||
// 更新设备状态
|
// 更新设备状态
|
||||||
|
|
||||||
const device = await device_status.findOne({ where: { sn_code } });
|
const device = await device_status.findOne({ where: { sn_code } });
|
||||||
@@ -99,7 +120,20 @@ module.exports = {
|
|||||||
device_id: user.device_id
|
device_id: user.device_id
|
||||||
});
|
});
|
||||||
|
|
||||||
return ctx.success({ token, user: user.toJSON() });
|
// 计算剩余天数并返回
|
||||||
|
let remaining_days = 0;
|
||||||
|
if (authDate && authDays > 0) {
|
||||||
|
const startDate = dayjs(authDate);
|
||||||
|
const endDate = startDate.add(authDays, 'day');
|
||||||
|
const now = dayjs();
|
||||||
|
const remaining = endDate.diff(now, 'day', true);
|
||||||
|
remaining_days = Math.max(0, Math.ceil(remaining));
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo = user.toJSON();
|
||||||
|
userInfo.remaining_days = remaining_days;
|
||||||
|
|
||||||
|
return ctx.success({ token, user: userInfo });
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,6 +97,18 @@ class MqttDispatcher {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查授权状态(对于需要授权的操作)
|
||||||
|
const authorizationService = require('../../services/authorization_service');
|
||||||
|
const authCheck = await authorizationService.checkAuthorization(deviceCode, 'sn_code');
|
||||||
|
if (!authCheck.is_authorized) {
|
||||||
|
console.log(`[MQTT分发器] 设备 ${deviceCode} 授权检查失败: ${authCheck.message}`);
|
||||||
|
return this.sendMqttResponse(mqttClient, uuid, {
|
||||||
|
code: 403,
|
||||||
|
message: authCheck.message,
|
||||||
|
data: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 获取对应的处理器
|
// 获取对应的处理器
|
||||||
const handler = this.actionHandlers.get(action);
|
const handler = this.actionHandlers.get(action);
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const db = require('../dbProxy');
|
|||||||
const jobManager = require('../job/index');
|
const jobManager = require('../job/index');
|
||||||
const ScheduleUtils = require('./utils');
|
const ScheduleUtils = require('./utils');
|
||||||
const ScheduleConfig = require('./config');
|
const ScheduleConfig = require('./config');
|
||||||
|
const authorizationService = require('../../services/authorization_service');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +92,12 @@ class CommandManager {
|
|||||||
throw new Error(`任务不存在: ${task_id}`);
|
throw new Error(`任务不存在: ${task_id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1.5 检查账号授权状态
|
||||||
|
const authCheck = await authorizationService.checkAuthorization(task.sn_code, 'sn_code');
|
||||||
|
if (!authCheck.is_authorized) {
|
||||||
|
throw new Error(`授权检查失败: ${authCheck.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
// 2. 获取指令信息
|
// 2. 获取指令信息
|
||||||
const command_name = command.command_name || command.name || '未知指令';
|
const command_name = command.command_name || command.name || '未知指令';
|
||||||
const command_type = command.command_type || command.type;
|
const command_type = command.command_type || command.type;
|
||||||
|
|||||||
@@ -48,6 +48,18 @@ class TaskHandlers {
|
|||||||
|
|
||||||
console.log(`[任务处理器] 自动投递任务 - 设备: ${sn_code}, 关键词: ${keyword}`);
|
console.log(`[任务处理器] 自动投递任务 - 设备: ${sn_code}, 关键词: ${keyword}`);
|
||||||
|
|
||||||
|
// 检查授权状态
|
||||||
|
const authorizationService = require('../../services/authorization_service');
|
||||||
|
const authCheck = await authorizationService.checkAuthorization(sn_code, 'sn_code');
|
||||||
|
if (!authCheck.is_authorized) {
|
||||||
|
console.log(`[任务处理器] 自动投递任务 - 设备: ${sn_code} 授权检查失败: ${authCheck.message}`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
deliveredCount: 0,
|
||||||
|
message: authCheck.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
deviceManager.recordTaskStart(sn_code, task);
|
deviceManager.recordTaskStart(sn_code, task);
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
|
|
||||||
@@ -543,6 +555,18 @@ class TaskHandlers {
|
|||||||
const { sn_code, taskParams } = task;
|
const { sn_code, taskParams } = task;
|
||||||
console.log(`[任务处理器] 自动沟通任务 - 设备: ${sn_code}`);
|
console.log(`[任务处理器] 自动沟通任务 - 设备: ${sn_code}`);
|
||||||
|
|
||||||
|
// 检查授权状态
|
||||||
|
const authorizationService = require('../../services/authorization_service');
|
||||||
|
const authCheck = await authorizationService.checkAuthorization(sn_code, 'sn_code');
|
||||||
|
if (!authCheck.is_authorized) {
|
||||||
|
console.log(`[任务处理器] 自动沟通任务 - 设备: ${sn_code} 授权检查失败: ${authCheck.message}`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
chatCount: 0,
|
||||||
|
message: authCheck.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
deviceManager.recordTaskStart(sn_code, task);
|
deviceManager.recordTaskStart(sn_code, task);
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
|||||||
@@ -264,6 +264,39 @@ module.exports = (db) => {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 授权相关字段
|
||||||
|
authorization_date: {
|
||||||
|
comment: '授权日期(授权开始时间)',
|
||||||
|
type: Sequelize.DATE,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: null
|
||||||
|
},
|
||||||
|
authorization_days: {
|
||||||
|
comment: '授权天数',
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 0
|
||||||
|
},
|
||||||
|
remaining_days: {
|
||||||
|
comment: '剩余天数(虚拟字段,通过计算得出)',
|
||||||
|
type: Sequelize.VIRTUAL,
|
||||||
|
get: function () {
|
||||||
|
const authDate = this.getDataValue('authorization_date');
|
||||||
|
const authDays = this.getDataValue('authorization_days') || 0;
|
||||||
|
|
||||||
|
if (!authDate || authDays <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startDate = dayjs(authDate);
|
||||||
|
const endDate = startDate.add(authDays, 'day');
|
||||||
|
const now = dayjs();
|
||||||
|
|
||||||
|
// 计算剩余天数
|
||||||
|
const remaining = endDate.diff(now, 'day', true);
|
||||||
|
return Math.max(0, Math.ceil(remaining));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
80
api/services/authorization_service.js
Normal file
80
api/services/authorization_service.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* 授权服务
|
||||||
|
* 提供账号授权检查功能
|
||||||
|
*/
|
||||||
|
|
||||||
|
const db = require('../middleware/dbProxy');
|
||||||
|
const dayjs = require('dayjs');
|
||||||
|
|
||||||
|
class AuthorizationService {
|
||||||
|
/**
|
||||||
|
* 检查账号授权状态
|
||||||
|
* @param {string|number} identifier - 账号标识(sn_code 或 id)
|
||||||
|
* @param {string} identifierType - 标识类型:'sn_code' 或 'id'
|
||||||
|
* @returns {Promise<Object>} 授权检查结果 {is_authorized: boolean, remaining_days: number, message: string}
|
||||||
|
*/
|
||||||
|
async checkAuthorization(identifier, identifierType = 'sn_code') {
|
||||||
|
const pla_account = db.getModel('pla_account');
|
||||||
|
|
||||||
|
const where = {};
|
||||||
|
where[identifierType] = identifier;
|
||||||
|
|
||||||
|
const account = await pla_account.findOne({ where });
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
return {
|
||||||
|
is_authorized: false,
|
||||||
|
remaining_days: 0,
|
||||||
|
message: '账号不存在'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountData = account.toJSON();
|
||||||
|
const authDate = accountData.authorization_date;
|
||||||
|
const authDays = accountData.authorization_days || 0;
|
||||||
|
|
||||||
|
// 如果没有授权信息,默认不允许
|
||||||
|
if (!authDate || authDays <= 0) {
|
||||||
|
return {
|
||||||
|
is_authorized: false,
|
||||||
|
remaining_days: 0,
|
||||||
|
message: '账号未授权,请联系管理员'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算剩余天数
|
||||||
|
const startDate = dayjs(authDate);
|
||||||
|
const endDate = startDate.add(authDays, 'day');
|
||||||
|
const now = dayjs();
|
||||||
|
const remaining = endDate.diff(now, 'day', true);
|
||||||
|
const remaining_days = Math.max(0, Math.ceil(remaining));
|
||||||
|
|
||||||
|
if (remaining_days <= 0) {
|
||||||
|
return {
|
||||||
|
is_authorized: false,
|
||||||
|
remaining_days: 0,
|
||||||
|
message: '账号授权已过期,请联系管理员续费'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
is_authorized: true,
|
||||||
|
remaining_days: remaining_days,
|
||||||
|
message: `授权有效,剩余 ${remaining_days} 天`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查账号授权状态(快速检查,只返回是否授权)
|
||||||
|
* @param {string|number} identifier - 账号标识(sn_code 或 id)
|
||||||
|
* @param {string} identifierType - 标识类型:'sn_code' 或 'id'
|
||||||
|
* @returns {Promise<boolean>} 是否授权
|
||||||
|
*/
|
||||||
|
async isAuthorized(identifier, identifierType = 'sn_code') {
|
||||||
|
const result = await this.checkAuthorization(identifier, identifierType);
|
||||||
|
return result.is_authorized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new AuthorizationService();
|
||||||
|
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
const db = require('../middleware/dbProxy');
|
const db = require('../middleware/dbProxy');
|
||||||
const scheduleManager = require('../middleware/schedule/index.js');
|
const scheduleManager = require('../middleware/schedule/index.js');
|
||||||
const locationService = require('./locationService');
|
const locationService = require('./locationService');
|
||||||
|
const authorizationService = require('./authorization_service');
|
||||||
|
|
||||||
class PlaAccountService {
|
class PlaAccountService {
|
||||||
/**
|
/**
|
||||||
@@ -382,6 +383,12 @@ class PlaAccountService {
|
|||||||
throw new Error('账号不存在');
|
throw new Error('账号不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查授权状态
|
||||||
|
const authCheck = await authorizationService.checkAuthorization(id, 'id');
|
||||||
|
if (!authCheck.is_authorized) {
|
||||||
|
throw new Error(authCheck.message);
|
||||||
|
}
|
||||||
|
|
||||||
// 从 device_status 检查账号是否在线
|
// 从 device_status 检查账号是否在线
|
||||||
const deviceStatus = await device_status.findByPk(account.sn_code);
|
const deviceStatus = await device_status.findByPk(account.sn_code);
|
||||||
if (!deviceStatus || !deviceStatus.isOnline) {
|
if (!deviceStatus || !deviceStatus.isOnline) {
|
||||||
|
|||||||
Reference in New Issue
Block a user