feat: 赛事1.09
This commit is contained in:
+4
-4
@@ -52,10 +52,10 @@ system.roles.add # 角色权限-新增(筛选栏中的"新增
|
|||||||
system.roles.edit # 角色权限-编辑(表格操作列中的"编辑"按钮)
|
system.roles.edit # 角色权限-编辑(表格操作列中的"编辑"按钮)
|
||||||
system.roles.delete # 角色权限-删除(表格操作列中的"删除"按钮,红色危险样式)
|
system.roles.delete # 角色权限-删除(表格操作列中的"删除"按钮,红色危险样式)
|
||||||
|
|
||||||
system.notices.view # 公告管理-查看(页面默认查看权限)
|
system.announcement.view # 公告管理-查看(页面默认查看权限)
|
||||||
system.notices.add # 公告管理-新增(筛选栏中的"新增"按钮)
|
system.announcement.save # 公告管理-新增(筛选栏中的"新增"按钮)
|
||||||
system.notices.edit # 公告管理-编辑(表格操作列中的"修改"按钮)
|
system.announcement.edit # 公告管理-编辑(表格操作列中的"修改"按钮)
|
||||||
system.notices.delete # 公告管理-删除(表格操作列中的"删除"按钮,红色危险样式)
|
system.announcement.del # 公告管理-删除(表格操作列中的"删除"按钮,红色危险样式)
|
||||||
|
|
||||||
system.logs.view # 操作日志-查看(页面默认查看权限,无操作列按钮)
|
system.logs.view # 操作日志-查看(页面默认查看权限,无操作列按钮)
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function updateNotice(params: NoticeSaveParams): Promise<ApiResult<null>>
|
|||||||
return post(ANNOUNCEMENT_UPDATE, params);
|
return post(ANNOUNCEMENT_UPDATE, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除公告(物理删除,单个)— POST /admin/sys/announcement/delete?id=xxx */
|
/** 删除公告(物理删除,单个)— POST /admin/sys/announcement/delete(id 放在请求体) */
|
||||||
export function deleteNotice(id: number): Promise<ApiResult<null>> {
|
export function deleteNotice(id: number): Promise<ApiResult<null>> {
|
||||||
return post(ANNOUNCEMENT_DELETE, undefined, { id: String(id) });
|
return post(ANNOUNCEMENT_DELETE, { id });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,15 +165,13 @@ export const FALLBACK_MENU_NODES: MenuNode[] = [
|
|||||||
permission: 'system.roles.view',
|
permission: 'system.roles.view',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// 公告管理:后端 /op/permission 尚未下发 system.notices.view 权限码,
|
|
||||||
// 暂不挂 permission(否则整条菜单会被权限过滤掉);后端配置后可在下方补回
|
|
||||||
// permission: 'system.notices.view',
|
|
||||||
id: 'system_notices',
|
id: 'system_notices',
|
||||||
name: '公告管理',
|
name: '公告管理',
|
||||||
path: 'system/notices',
|
path: 'system/notices',
|
||||||
component: 'system/notices',
|
component: 'system/notices',
|
||||||
componentName: 'SystemNotices',
|
componentName: 'SystemNotices',
|
||||||
icon: 'AiOutlineSound',
|
icon: 'AiOutlineSound',
|
||||||
|
permission: 'system.announcement.view',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'system_params',
|
id: 'system_params',
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { getNoticeList, type NoticeVO } from '../model/services';
|
|||||||
import {
|
import {
|
||||||
TITLE_MAX,
|
TITLE_MAX,
|
||||||
CONTENT_MAX,
|
CONTENT_MAX,
|
||||||
|
DISPLAY_TIME_FORMAT,
|
||||||
SUBMIT_TIME_FORMAT,
|
SUBMIT_TIME_FORMAT,
|
||||||
typeRules,
|
typeRules,
|
||||||
timeRangeRules,
|
timeRangeRules,
|
||||||
@@ -56,10 +57,11 @@ export default defineComponent({
|
|||||||
Object.assign(formData, getDefaultForm());
|
Object.assign(formData, getDefaultForm());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const startTime = record.startTime ? dayjs(record.startTime) : null;
|
// 编辑回填时秒统一归零,界面只精确到分钟
|
||||||
const endTime = record.endTime ? dayjs(record.endTime) : null;
|
const startTime = record.startTime ? dayjs(record.startTime).second(0) : null;
|
||||||
|
const endTime = record.endTime ? dayjs(record.endTime).second(0) : null;
|
||||||
Object.assign(formData, {
|
Object.assign(formData, {
|
||||||
type: record.type || 1,
|
type: Number(record.type) || 1,
|
||||||
timeRange: startTime?.isValid() && endTime?.isValid() ? [startTime, endTime] : null,
|
timeRange: startTime?.isValid() && endTime?.isValid() ? [startTime, endTime] : null,
|
||||||
title: record.title || '',
|
title: record.title || '',
|
||||||
context: record.context || '',
|
context: record.context || '',
|
||||||
@@ -81,7 +83,11 @@ export default defineComponent({
|
|||||||
const validateTimeRange = async (startTime: Dayjs, endTime: Dayjs): Promise<boolean> => {
|
const validateTimeRange = async (startTime: Dayjs, endTime: Dayjs): Promise<boolean> => {
|
||||||
timeRangeChecking.value = true;
|
timeRangeChecking.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await getNoticeList({ page: '1', limit: '999', type: formData.type });
|
const res = await getNoticeList({
|
||||||
|
page: '1',
|
||||||
|
limit: '999',
|
||||||
|
type: Number(formData.type) || 1,
|
||||||
|
});
|
||||||
if (res.code != 200) return true;
|
if (res.code != 200) return true;
|
||||||
|
|
||||||
const editingId = props.record ? String(props.record.id) : '';
|
const editingId = props.record ? String(props.record.id) : '';
|
||||||
@@ -119,7 +125,7 @@ export default defineComponent({
|
|||||||
if (!isTimeRangeValid) return;
|
if (!isTimeRangeValid) return;
|
||||||
|
|
||||||
props.onSave({
|
props.onSave({
|
||||||
type: formData.type,
|
type: Number(formData.type) || 1,
|
||||||
title: formData.title.trim(),
|
title: formData.title.trim(),
|
||||||
context: formData.context.trim(),
|
context: formData.context.trim(),
|
||||||
startTime: startTime.format(SUBMIT_TIME_FORMAT),
|
startTime: startTime.format(SUBMIT_TIME_FORMAT),
|
||||||
@@ -146,24 +152,28 @@ export default defineComponent({
|
|||||||
{/* 类型 */}
|
{/* 类型 */}
|
||||||
<Form.Item label="类型" name="type" rules={typeRules}>
|
<Form.Item label="类型" name="type" rules={typeRules}>
|
||||||
<Select
|
<Select
|
||||||
value={formData.type}
|
value={Number(formData.type)}
|
||||||
options={NOTICE_TYPE_OPTIONS as any}
|
options={NOTICE_TYPE_OPTIONS as any}
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
onUpdate:value={(val: any) => (formData.type = val as number)}
|
onUpdate:value={(val: any) => (formData.type = Number(val) || 1)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{/* 生效时间 */}
|
{/* 生效时间 */}
|
||||||
<Form.Item label="生效时间" name="timeRange" rules={timeRangeRules}>
|
<Form.Item label="生效时间" name="timeRange" rules={timeRangeRules}>
|
||||||
<RangePicker
|
<RangePicker
|
||||||
showTime
|
showTime={{ format: 'HH:mm' }}
|
||||||
format={SUBMIT_TIME_FORMAT}
|
format={DISPLAY_TIME_FORMAT}
|
||||||
value={formData.timeRange as any}
|
value={formData.timeRange as any}
|
||||||
placeholder={['开始时间', '结束时间']}
|
placeholder={['开始时间', '结束时间']}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
allowClear
|
allowClear
|
||||||
onUpdate:value={(val: any) => {
|
onUpdate:value={(val: any) => {
|
||||||
formData.timeRange = (val as [Dayjs, Dayjs]) || null;
|
const range =
|
||||||
|
Array.isArray(val) && val.length === 2
|
||||||
|
? ([val[0].second(0), val[1].second(0)] as [Dayjs, Dayjs])
|
||||||
|
: null;
|
||||||
|
formData.timeRange = range;
|
||||||
formRef.value?.clearValidate('timeRange');
|
formRef.value?.clearValidate('timeRange');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ function confirmDelete({ record, onOk }: { record: any; onOk: (record: any) => v
|
|||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '删除确认',
|
title: '删除确认',
|
||||||
class: 'deleteConfirmModal',
|
class: 'deleteConfirmModal',
|
||||||
content: `确认要删除“${record.title}”吗?`,
|
content: `确认删除“${record.title}”吗?`,
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
okButtonProps: { danger: true } as ModalProps['okButtonProps'],
|
okButtonProps: { danger: true } as ModalProps['okButtonProps'],
|
||||||
@@ -100,17 +100,17 @@ export default defineComponent({
|
|||||||
const { hasPermission, hasAnyPermission } = usePermissionStore();
|
const { hasPermission, hasAnyPermission } = usePermissionStore();
|
||||||
|
|
||||||
// 公告模块的权限码后端尚未配置时(/op/permission 未下发),按钮默认放行,
|
// 公告模块的权限码后端尚未配置时(/op/permission 未下发),按钮默认放行,
|
||||||
// 待后端下发任意一个 system.notices.* 权限码后自动切换为按码控制
|
// 待后端下发任意一个 system.announcement.* 权限码后自动切换为按码控制
|
||||||
const noticePermsConfigured = hasAnyPermission([
|
const noticePermsConfigured = hasAnyPermission([
|
||||||
'system.notices.view',
|
'system.announcement.view',
|
||||||
'system.notices.add',
|
'system.announcement.save',
|
||||||
'system.notices.edit',
|
'system.announcement.edit',
|
||||||
'system.notices.delete',
|
'system.announcement.del',
|
||||||
]);
|
]);
|
||||||
const canAdd = !noticePermsConfigured || hasPermission('system.notices.add');
|
const canAdd = !noticePermsConfigured || hasPermission('system.announcement.save');
|
||||||
const operationPermissions = {
|
const operationPermissions = {
|
||||||
canEdit: !noticePermsConfigured || hasPermission('system.notices.edit'),
|
canEdit: !noticePermsConfigured || hasPermission('system.announcement.edit'),
|
||||||
canDelete: !noticePermsConfigured || hasPermission('system.notices.delete'),
|
canDelete: !noticePermsConfigured || hasPermission('system.announcement.del'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerDelete = (record: any) => confirmDelete({ record, onOk: handleDelete });
|
const triggerDelete = (record: any) => confirmDelete({ record, onOk: handleDelete });
|
||||||
|
|||||||
@@ -19,11 +19,8 @@ import {
|
|||||||
// 常量
|
// 常量
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** 公告类型选项(筛选 / 表单共用) */
|
/** 公告类型选项(筛选 / 表单共用):目前仅开放「首页公告提示」 */
|
||||||
export const NOTICE_TYPE_OPTIONS = [
|
export const NOTICE_TYPE_OPTIONS = [{ value: 1, label: '首页公告提示' }] as const;
|
||||||
{ value: 1, label: '首页公告提示' },
|
|
||||||
{ value: 2, label: '产品更新公告' },
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
/** 公告类型文案映射(兜底,后端 typeName 为空时使用) */
|
/** 公告类型文案映射(兜底,后端 typeName 为空时使用) */
|
||||||
export const NOTICE_TYPE_MAP: Record<number, string> = {
|
export const NOTICE_TYPE_MAP: Record<number, string> = {
|
||||||
@@ -67,9 +64,10 @@ export function useNoticeModel() {
|
|||||||
formatResult: (res) => res,
|
formatResult: (res) => res,
|
||||||
});
|
});
|
||||||
|
|
||||||
const dataSource = computed(() => {
|
const dataSource = computed<NoticeVO[]>(() => {
|
||||||
const res = data.value;
|
const list = (data.value as any)?.data?.list || [];
|
||||||
return res ? (res as any).data?.list || [] : [];
|
// 后端 type 可能返回字符串,统一归一化为数字,保证编辑弹窗 Select 能匹配选项
|
||||||
|
return list.map((item: NoticeVO) => ({ ...item, type: Number(item.type) }));
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user