1.优化工作台页面/dashboard/console

2.移除岗位管理相关代码和数据库
This commit is contained in:
2026-05-18 11:41:34 +08:00
parent 52b5ccb8e4
commit 085454fb78
30 changed files with 201 additions and 1123 deletions

View File

@@ -52,6 +52,16 @@ export interface NewPlayerItem {
name: string
coin: number
total_ticket_count: number
create_time: string
}
/** 玩家游玩记录项 */
export interface PlayRecordItem {
player_name: string
reward_tier: string
reward_tier_label: string
win_coin: number
create_time: string
}
/**
@@ -64,3 +74,13 @@ export function fetchNewPlayerList() {
})
}
/**
* 工作台-玩家游玩记录最新50条
* @returns 列表
*/
export function fetchPlayRecordList() {
return request.get<PlayRecordItem[]>({
url: '/core/dice/dashboard/playRecordList'
})
}

View File

@@ -1,75 +0,0 @@
import request from '@/utils/http'
/**
* 岗位API
*/
export default {
/**
* 获取数据列表
* @param params 搜索参数
* @returns 数据列表
*/
list(params: Record<string, any>) {
return request.get<Api.Common.ApiPage>({
url: '/core/post/index',
params
})
},
/**
* 读取数据
* @param id 数据ID
* @returns 数据详情
*/
read(id: number | string) {
return request.get<Api.Common.ApiData>({
url: '/core/post/read?id=' + id
})
},
/**
* 创建数据
* @param params 数据参数
* @returns 执行结果
*/
save(params: Record<string, any>) {
return request.post<any>({
url: '/core/post/save',
data: params
})
},
/**
* 更新数据
* @param params 数据参数
* @returns 执行结果
*/
update(params: Record<string, any>) {
return request.put<any>({
url: '/core/post/update',
data: params
})
},
/**
* 删除数据
* @param id 数据ID
* @returns 执行结果
*/
delete(params: Record<string, any>) {
return request.del<any>({
url: '/core/post/destroy',
data: params
})
},
/**
* 可操作岗位
* @returns 数据列表
*/
accessPost() {
return request.get<Api.Common.ApiData[]>({
url: '/core/post/accessPost'
})
}
}

View File

@@ -303,7 +303,16 @@
"subtitle": "Latest 50 new player records",
"player": "Player",
"balance": "Balance",
"ticket": "Tickets"
"ticket": "Tickets",
"registerTime": "Register Time"
},
"playRecord": {
"title": "Player Play Records",
"subtitle": "Latest 50 play records",
"player": "Player",
"reward": "Reward Tier",
"winCoin": "Win Amount",
"playTime": "Play Time"
},
"walletRecord": {
"title": "Player Charge Records",
@@ -379,7 +388,6 @@
"userCenter": "User Center",
"menu": "Menu Management",
"dept": "Department Management",
"post": "Post Management",
"config": "System Config"
},
"safeguard": {
@@ -445,8 +453,6 @@
"placeholderDeptCode": "Dept Code",
"placeholderRoleName": "Role Name",
"placeholderRoleCode": "Role Code",
"placeholderPostName": "Post Name",
"placeholderPostCode": "Post Code",
"placeholderMenuName": "Menu Name",
"placeholderMenuRoute": "Menu Route",
"placeholderOperator": "Operator",
@@ -514,8 +520,6 @@
"dashboard": "Dashboard",
"loginTime": "Last Login",
"agentId": "Agent ID",
"postName": "Post Name",
"postCode": "Post Code",
"deptName": "Dept Name",
"deptCode": "Dept Code",
"leader": "Leader",

View File

@@ -1,34 +0,0 @@
{
"search": {
"postName": "Post Name",
"postCode": "Post Code",
"status": "Status",
"placeholderPostName": "Please enter post name",
"placeholderPostCode": "Please enter post code",
"searchSelectPlaceholder": "Please select"
},
"table": {
"postName": "Post Name",
"postCode": "Post Code",
"sort": "Sort",
"status": "Status",
"createTime": "Create Time"
},
"form": {
"titleAdd": "Add Post",
"titleEdit": "Edit Post",
"labelName": "Post Name",
"labelCode": "Post Code",
"labelRemark": "Description",
"labelSort": "Sort",
"labelStatus": "Enabled",
"placeholderName": "Please enter post name",
"placeholderCode": "Please enter post code",
"placeholderRemark": "Please enter description",
"placeholderSort": "Please enter sort",
"ruleNameRequired": "Please enter post name",
"ruleCodeRequired": "Please enter post code",
"addSuccess": "Added successfully",
"editSuccess": "Updated successfully"
}
}

View File

@@ -30,7 +30,6 @@
"labelPhone": "Phone",
"labelDept": "Department",
"labelRole": "Role",
"labelPost": "Post",
"labelGender": "Gender",
"labelStatus": "Status",
"labelRemark": "Remark",

View File

@@ -303,7 +303,16 @@
"subtitle": "最新50条新增玩家记录",
"player": "玩家",
"balance": "余额",
"ticket": "抽奖券"
"ticket": "抽奖券",
"registerTime": "注册时间"
},
"playRecord": {
"title": "玩家游玩记录",
"subtitle": "最新50条游玩记录",
"player": "玩家",
"reward": "中奖档位",
"winCoin": "赢取平台币",
"playTime": "游玩时间"
},
"walletRecord": {
"title": "玩家充值记录",
@@ -375,7 +384,6 @@
"userCenter": "个人中心",
"menu": "菜单管理",
"dept": "渠道(部门)管理",
"post": "岗位管理",
"config": "系统配置"
},
"safeguard": {
@@ -441,8 +449,6 @@
"placeholderDeptCode": "请输入部门编码",
"placeholderRoleName": "请输入角色名称",
"placeholderRoleCode": "请输入角色编码",
"placeholderPostName": "请输入岗位名称",
"placeholderPostCode": "请输入岗位编码",
"placeholderMenuName": "请输入菜单名称",
"placeholderMenuRoute": "请输入菜单路由",
"placeholderOperator": "请输入操作用户",
@@ -510,8 +516,6 @@
"dashboard": "首页",
"loginTime": "上次登录",
"agentId": "代理ID",
"postName": "岗位名称",
"postCode": "岗位编码",
"deptName": "部门名称",
"deptCode": "部门编码",
"leader": "部门领导",

View File

@@ -1,34 +0,0 @@
{
"search": {
"postName": "岗位名称",
"postCode": "岗位编码",
"status": "状态",
"placeholderPostName": "请输入岗位名称",
"placeholderPostCode": "请输入岗位编码",
"searchSelectPlaceholder": "请选择"
},
"table": {
"postName": "岗位名称",
"postCode": "岗位编码",
"sort": "排序",
"status": "状态",
"createTime": "创建时间"
},
"form": {
"titleAdd": "新增岗位",
"titleEdit": "编辑岗位",
"labelName": "岗位名称",
"labelCode": "岗位编码",
"labelRemark": "描述",
"labelSort": "排序",
"labelStatus": "启用",
"placeholderName": "请输入岗位名称",
"placeholderCode": "请输入岗位编码",
"placeholderRemark": "请输入岗位描述",
"placeholderSort": "请输入排序",
"ruleNameRequired": "请输入岗位名称",
"ruleCodeRequired": "请输入岗位编码",
"addSuccess": "新增成功",
"editSuccess": "修改成功"
}
}

View File

@@ -30,7 +30,6 @@
"labelPhone": "手机号",
"labelDept": "部门",
"labelRole": "角色",
"labelPost": "岗位",
"labelGender": "性别",
"labelStatus": "状态",
"labelRemark": "备注",

View File

@@ -25,7 +25,6 @@ export const MAP_PATH_TO_MENU_I18N_KEY: Record<string, string> = {
'/system/user-center': 'menus.system.userCenter',
'/system/menu': 'menus.system.menu',
'/system/dept': 'menus.system.dept',
'/system/post': 'menus.system.post',
'/system/config': 'menus.system.config',
'/safeguard': 'menus.safeguard.title',
'/safeguard/dict': 'menus.safeguard.dict',

View File

@@ -1,9 +1,9 @@
<!-- 工作台页面 -->
<!-- 工作台页面大富翁色子游戏数据统计 -->
<template>
<div>
<template v-if="userInfo.dashboard === 'statistics'">
<CardList></CardList>
<CardList />
<template v-if="isStatisticsDashboard">
<ElRow :gutter="20">
<ElCol :sm="24" :md="12" :lg="10">
<ActiveUser />
@@ -12,30 +12,22 @@
<SalesOverview />
</ElCol>
</ElRow>
<ElRow :gutter="20">
<ElCol :sm="24" :md="12" :lg="12">
<WalletRecordList />
</ElCol>
<ElCol :sm="24" :md="12" :lg="12">
<NewPlayerList />
</ElCol>
</ElRow>
</template>
<template v-if="userInfo.dashboard === 'work'">
<ElRow :gutter="20">
<ElCol :sm="24" :md="24" :lg="12">
<NewUser />
</ElCol>
<ElCol :sm="24" :md="12" :lg="6">
<Dynamic />
</ElCol>
<ElCol :sm="24" :md="12" :lg="6">
<TodoList />
</ElCol>
</ElRow>
</template>
<ElRow :gutter="20">
<ElCol :sm="24" :md="12" :lg="12">
<NewPlayerList />
</ElCol>
<ElCol :sm="24" :md="12" :lg="12">
<WalletRecordList />
</ElCol>
</ElRow>
<ElRow :gutter="20">
<ElCol :sm="24" :md="24" :lg="24">
<PlayRecordList />
</ElCol>
</ElRow>
</div>
</template>
@@ -45,16 +37,18 @@
import SalesOverview from './modules/sales-overview.vue'
import WalletRecordList from './modules/wallet-record-list.vue'
import NewPlayerList from './modules/new-player-list.vue'
import NewUser from './modules/new-user.vue'
import Dynamic from './modules/dynamic-stats.vue'
import TodoList from './modules/todo-list.vue'
import PlayRecordList from './modules/play-record-list.vue'
import { useCommon } from '@/hooks/core/useCommon'
import { useUserStore } from '@/store/modules/user'
defineOptions({ name: 'Console' })
const userStore = useUserStore()
const userInfo = userStore.getUserInfo
/** 统计页额外展示充值图表 */
const isStatisticsDashboard = computed(
() => userStore.getUserInfo.dashboard === 'statistics'
)
const { scrollToTop } = useCommon()
scrollToTop()

View File

@@ -17,11 +17,23 @@
>
<template #default>
<ElTableColumn :label="$t('console.newPlayer.player')" prop="name" min-width="120" align="center" />
<ElTableColumn :label="$t('console.newPlayer.balance')" prop="coin" min-width="120" align="center">
<ElTableColumn :label="$t('console.newPlayer.balance')" prop="coin" min-width="100" align="center">
<template #default="scope">
{{ formatCoin(scope.row.coin) }}
</template>
</ElTableColumn>
<ElTableColumn
:label="$t('console.newPlayer.ticket')"
prop="total_ticket_count"
min-width="90"
align="center"
/>
<ElTableColumn
:label="$t('console.newPlayer.registerTime')"
prop="create_time"
min-width="170"
align="center"
/>
</template>
</ArtTable>
</div>

View File

@@ -0,0 +1,67 @@
<template>
<div class="art-card p-5 overflow-hidden mb-5 max-sm:mb-4">
<div class="art-card-header mb-4">
<div class="title">
<h4>{{ $t('console.playRecord.title') }}</h4>
<p class="text-g-600 text-sm mt-1">{{ $t('console.playRecord.subtitle') }}</p>
</div>
</div>
<ArtTable
class="w-full"
:data="tableData"
style="width: 100%"
size="default"
:border="false"
:stripe="true"
:header-cell-style="{ background: 'transparent' }"
>
<template #default>
<ElTableColumn
:label="$t('console.playRecord.player')"
prop="player_name"
min-width="120"
align="center"
/>
<ElTableColumn
:label="$t('console.playRecord.reward')"
prop="reward_tier_label"
min-width="140"
align="center"
/>
<ElTableColumn
:label="$t('console.playRecord.winCoin')"
prop="win_coin"
min-width="120"
align="center"
>
<template #default="scope">
{{ formatCoin(scope.row.win_coin) }}
</template>
</ElTableColumn>
<ElTableColumn
:label="$t('console.playRecord.playTime')"
prop="create_time"
min-width="170"
align="center"
/>
</template>
</ArtTable>
</div>
</template>
<script setup lang="ts">
import { fetchPlayRecordList, type PlayRecordItem } from '@/api/dashboard'
const tableData = ref<PlayRecordItem[]>([])
function formatCoin(val: number | undefined): string {
if (val === undefined || val === null) return '0.00'
return Number(val).toFixed(2)
}
onMounted(() => {
fetchPlayRecordList().then((data) => {
tableData.value = Array.isArray(data) ? data : []
})
})
</script>

View File

@@ -1,142 +0,0 @@
<template>
<div class="art-full-height">
<!-- 搜索面板 -->
<TableSearch v-model="searchForm" @search="handleSearch" @reset="resetSearchParams" />
<ElCard class="art-table-card" shadow="never">
<!-- 表格头部 -->
<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
<template #left>
<ElSpace wrap>
<ElButton v-permission="'core:post:save'" @click="showDialog('add')" v-ripple>
<template #icon>
<ArtSvgIcon icon="ri:add-fill" />
</template>
{{ $t('table.actions.add') }}
</ElButton>
<ElButton
v-permission="'core:post:destroy'"
:disabled="selectedRows.length === 0"
@click="deleteSelectedRows(api.delete, refreshData)"
v-ripple
>
<template #icon>
<ArtSvgIcon icon="ri:delete-bin-5-line" />
</template>
{{ $t('table.actions.delete') }}
</ElButton>
<SaImport
v-permission="'core:post:import'"
download-url="/core/post/downloadTemplate"
upload-url="/core/post/import"
@success="refreshData"
/>
<SaExport v-permission="'core:post:export'" url="/core/post/export" />
</ElSpace>
</template>
</ArtTableHeader>
<!-- 表格 -->
<ArtTable
ref="tableRef"
rowKey="id"
:loading="loading"
:data="data"
:columns="columns"
:pagination="pagination"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange"
@pagination:size-change="handleSizeChange"
@pagination:current-change="handleCurrentChange"
>
<!-- 操作列 -->
<template #operation="{ row }">
<div class="flex gap-2">
<SaButton
v-permission="'core:post:update'"
type="secondary"
@click="showDialog('edit', row)"
/>
<SaButton
v-permission="'core:post:destroy'"
type="error"
@click="deleteRow(row, api.delete, refreshData)"
/>
</div>
</template>
</ArtTable>
</ElCard>
<!-- 编辑弹窗 -->
<EditDialog
v-model="dialogVisible"
:dialog-type="dialogType"
:data="dialogData"
@success="refreshData"
/>
</div>
</template>
<script setup lang="ts">
import { useTable } from '@/hooks/core/useTable'
import { useSaiAdmin } from '@/composables/useSaiAdmin'
import api from '@/api/system/post'
import TableSearch from './modules/table-search.vue'
import EditDialog from './modules/edit-dialog.vue'
// 搜索表单
const searchForm = ref({
name: undefined,
code: undefined,
status: undefined
})
// 搜索处理
const handleSearch = (params: Record<string, any>) => {
Object.assign(searchParams, params)
getData()
}
// 表格配置
const {
columns,
columnChecks,
data,
loading,
getData,
searchParams,
pagination,
resetSearchParams,
handleSortChange,
handleSizeChange,
handleCurrentChange,
refreshData
} = useTable({
core: {
apiFn: api.list,
columnsFactory: () => [
{ type: 'selection' },
{ prop: 'id', label: 'table.columns.common.no', width: 100, align: 'center' },
{ prop: 'name', label: 'page.table.postName', minWidth: 120 },
{ prop: 'code', label: 'page.table.postCode', minWidth: 120 },
{ prop: 'remark', label: 'table.columns.common.description', minWidth: 150, showOverflowTooltip: true },
{ prop: 'sort', label: 'page.table.sort', width: 100 },
{ prop: 'status', label: 'page.table.status', saiType: 'dict', saiDict: 'data_status', width: 100 },
{ prop: 'create_time', label: 'page.table.createTime', width: 180, sortable: true },
{ prop: 'operation', label: 'table.actions.operation', width: 100, fixed: 'right', useSlot: true }
]
}
})
// 编辑配置
const {
dialogType,
dialogVisible,
dialogData,
showDialog,
deleteRow,
deleteSelectedRows,
handleSelectionChange,
selectedRows
} = useSaiAdmin()
</script>

View File

@@ -1,166 +0,0 @@
<template>
<el-dialog
v-model="visible"
:title="dialogType === 'add' ? $t('page.form.titleAdd') : $t('page.form.titleEdit')"
width="600px"
align-center
:close-on-click-modal="false"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
<el-form-item :label="$t('page.form.labelName')" prop="name">
<el-input v-model="formData.name" :placeholder="$t('page.form.placeholderName')" />
</el-form-item>
<el-form-item :label="$t('page.form.labelCode')" prop="code">
<el-input v-model="formData.code" :placeholder="$t('page.form.placeholderCode')" />
</el-form-item>
<el-form-item :label="$t('page.form.labelRemark')" prop="remark">
<el-input
v-model="formData.remark"
type="textarea"
:rows="3"
:placeholder="$t('page.form.placeholderRemark')"
/>
</el-form-item>
<el-form-item :label="$t('page.form.labelSort')" prop="sort">
<el-input-number v-model="formData.sort" :placeholder="$t('page.form.placeholderSort')" />
</el-form-item>
<el-form-item :label="$t('page.form.labelStatus')" prop="status">
<sa-radio v-model="formData.status" dict="data_status" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import api from '@/api/system/post'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { useI18n } from 'vue-i18n'
interface Props {
modelValue: boolean
dialogType: string
data?: Record<string, any>
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
(e: 'success'): void
}
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
dialogType: 'add',
data: undefined
})
const emit = defineEmits<Emits>()
const { t } = useI18n()
const formRef = ref<FormInstance>()
/**
* 弹窗显示状态双向绑定
*/
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
/**
* 表单验证规则
*/
const rules = computed<FormRules>(() => ({
name: [{ required: true, message: t('page.form.ruleNameRequired'), trigger: 'blur' }],
code: [{ required: true, message: t('page.form.ruleCodeRequired'), trigger: 'blur' }]
}))
/**
* 初始数据
*/
const initialFormData = {
id: null,
name: '',
code: '',
remark: '',
sort: 100,
status: 1
}
/**
* 表单数据
*/
const formData = reactive({ ...initialFormData })
/**
* 监听弹窗打开,初始化表单数据
*/
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
initPage()
}
}
)
/**
* 初始化页面数据
*/
const initPage = async () => {
// 先重置为初始值
Object.assign(formData, initialFormData)
// 如果有数据,则填充数据
if (props.data) {
await nextTick()
initForm()
}
}
/**
* 初始化表单数据
*/
const initForm = () => {
if (props.data) {
for (const key in formData) {
if (props.data[key] != null && props.data[key] != undefined) {
;(formData as any)[key] = props.data[key]
}
}
}
}
/**
* 关闭弹窗并重置表单
*/
const handleClose = () => {
visible.value = false
formRef.value?.resetFields()
}
/**
* 提交表单
*/
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
if (props.dialogType === 'add') {
await api.save(formData)
ElMessage.success(t('page.form.addSuccess'))
} else {
await api.update(formData)
ElMessage.success(t('page.form.editSuccess'))
}
emit('success')
handleClose()
} catch (error) {
console.log('表单验证失败:', error)
}
}
</script>

View File

@@ -1,77 +0,0 @@
<template>
<sa-search-bar
ref="searchBarRef"
v-model="formData"
label-width="100px"
:showExpand="false"
@reset="handleReset"
@search="handleSearch"
@expand="handleExpand"
>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.postName')" prop="name">
<el-input v-model="formData.name" :placeholder="$t('page.search.placeholderPostName')" clearable />
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.postCode')" prop="code">
<el-input v-model="formData.code" :placeholder="$t('page.search.placeholderPostCode')" clearable />
</el-form-item>
</el-col>
<el-col v-bind="setSpan(6)">
<el-form-item :label="$t('page.search.status')" prop="status">
<sa-select v-model="formData.status" dict="data_status" :placeholder="$t('page.search.searchSelectPlaceholder')" clearable />
</el-form-item>
</el-col>
</sa-search-bar>
</template>
<script setup lang="ts">
interface Props {
modelValue: Record<string, any>
}
interface Emits {
(e: 'update:modelValue', value: Record<string, any>): void
(e: 'search', params: Record<string, any>): void
(e: 'reset'): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
// 展开/收起
const isExpanded = ref<boolean>(false)
// 表单数据双向绑定
const searchBarRef = ref()
const formData = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
// 重置
function handleReset() {
searchBarRef.value?.ref.resetFields()
emit('reset')
}
// 搜索
async function handleSearch() {
emit('search', formData.value)
}
// 展开/收起
function handleExpand(expanded: boolean) {
isExpanded.value = expanded
}
// 栅格占据的列数
const setSpan = (span: number) => {
return {
span: span,
xs: 24, // 手机:满宽显示
sm: span >= 12 ? span : 12, // 平板大于等于12保持否则用半宽
md: span >= 8 ? span : 8, // 中等屏幕大于等于8保持否则用三分之一宽
lg: span,
xl: span
}
}
</script>

View File

@@ -76,18 +76,6 @@
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('page.form.labelPost')" prop="post_ids">
<el-select v-model="formData.post_ids" multiple clearable>
<el-option
v-for="post in optionData.postList"
:key="(post as any)?.id"
:value="(post as any)?.id"
:label="(post as any)?.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('page.form.labelGender')" prop="gender">
<sa-radio v-model="formData.gender" dict="gender" valueType="string" />
@@ -129,7 +117,6 @@
import api from '@/api/system/user'
import deptApi from '@/api/system/dept'
import roleApi from '@/api/system/role'
import postApi from '@/api/system/post'
import { ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
@@ -156,8 +143,7 @@
const formRef = ref<FormInstance>()
const optionData = reactive({
deptData: <any>[],
roleList: <any>[],
postList: <any>[]
roleList: <any>[]
})
/**
@@ -207,7 +193,6 @@
phone: '',
email: '',
role_ids: [],
post_ids: [],
status: 1,
gender: '',
remark: ''
@@ -239,18 +224,11 @@
// 角色数据
const roleData = await roleApi.accessRole()
optionData.roleList = roleData
// 岗位数据
const postData = await postApi.accessPost()
optionData.postList = postData
// 如果有数据,则填充数据
if (props.data) {
await nextTick()
if (props.data.id) {
let data = await api.read(props.data.id)
if (data.postList) {
const post = (data.postList as any[])?.map((item: any) => item.id)
data.post_ids = post
}
const role = (data.roleList as any[])?.map((item: any) => item.id)
data.role_ids = role
data.password = ''

View File

@@ -7,6 +7,7 @@ use app\dice\helper\AdminScopeHelper;
use app\dice\model\player\DicePlayer;
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
use app\dice\model\play_record\DicePlayRecord;
use app\dice\model\reward\DiceRewardConfig;
use plugin\saiadmin\basic\BaseController;
use plugin\saiadmin\service\Permission;
use support\Response;
@@ -222,11 +223,66 @@ class DiceDashboardController extends BaseController
'name' => $row->getAttr('username'),
'coin' => $row->getAttr('coin'),
'total_ticket_count' => $row->getAttr('total_ticket_count'),
'create_time' => $row->getAttr('create_time'),
];
}
return $this->success($rows);
}
/**
* 工作台-玩家游玩记录最新50条
* 返回:玩家账号、中奖档位、赢取平台币、游玩时间
*/
#[Permission('工作台数据统计', 'core:console:list')]
public function playRecordList(): Response
{
$adminInfo = $this->adminInfo ?? null;
$query = DicePlayRecord::with([
'dicePlayer' => function ($q) {
$q->field('id,username');
},
])
->where('status', 1)
->field('id,player_id,reward_tier,win_coin,create_time')
->order('create_time', 'desc')
->limit(50);
AdminScopeHelper::applyAdminScope($query, $adminInfo);
$list = $query->select();
$tierLabels = $this->buildRewardTierLabels();
$rows = [];
foreach ($list as $row) {
$player = $row->dicePlayer;
$tier = $row->getAttr('reward_tier');
$rows[] = [
'player_name' => $player ? $player->getAttr('username') : '',
'reward_tier' => $tier,
'reward_tier_label' => $tierLabels[$tier] ?? $tier,
'win_coin' => $row->getAttr('win_coin'),
'create_time' => $row->getAttr('create_time'),
];
}
return $this->success($rows);
}
/**
* @return array<string, string>
*/
private function buildRewardTierLabels(): array
{
$rows = DiceRewardConfig::field('tier,ui_text')->select();
$labels = [];
foreach ($rows as $row) {
$tier = $row->getAttr('tier');
if ($tier === '' || $tier === null) {
continue;
}
if (!isset($labels[$tier])) {
$labels[$tier] = $row->getAttr('ui_text') ?: $tier;
}
}
return $labels;
}
private function calcWeekChange($current, $last): float
{
if ($last == 0) {

View File

@@ -27,7 +27,6 @@ class UserInfoCache
'expire' => 60 * 60 * 4,
'dept' => 'saiadmin:user_cache:dept_',
'role' => 'saiadmin:user_cache:role_',
'post' => 'saiadmin:user_cache:post_',
]);
}
@@ -73,11 +72,6 @@ class UserInfoCache
$tags[] = $cache['role'] . $role['id'];
}
}
if (!empty($data['postList'])) {
foreach ($data['postList'] as $post) {
$tags[] = $cache['post'] . $post['id'];
}
}
Cache::tag($tags)->set($cache['prefix'] . $uid, $data, $cache['expire']);
return $data;
}
@@ -125,21 +119,4 @@ class UserInfoCache
return Cache::tag($tags)->clear();
}
/**
* 清理岗位下所有用户缓存
*/
public static function clearUserInfoByPostId($post_id): bool
{
$cache = static::cacheConfig();
if (is_array($post_id)) {
$tags = [];
foreach ($post_id as $id) {
$tags[] = $cache['post'] . $id;
}
} else {
$tags = $cache['post'] . $post_id;
}
return Cache::tag($tags)->clear();
}
}

View File

@@ -1,177 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\app\controller\system;
use plugin\saiadmin\basic\BaseController;
use plugin\saiadmin\app\logic\system\SystemPostLogic;
use plugin\saiadmin\app\validate\system\SystemPostValidate;
use plugin\saiadmin\service\Permission;
use support\Request;
use support\Response;
/**
* 岗位信息控制器
*/
class SystemPostController extends BaseController
{
/**
* 构造
*/
public function __construct()
{
$this->logic = new SystemPostLogic();
$this->validate = new SystemPostValidate;
parent::__construct();
}
/**
* 数据列表
* @param Request $request
* @return Response
*/
#[Permission('岗位数据列表', 'core:post:index')]
public function index(Request $request): Response
{
$where = $request->more([
['name', ''],
['code', ''],
['status', ''],
]);
$query = $this->logic->search($where);
$data = $this->logic->getList($query);
return $this->success($data);
}
/**
* 读取数据
* @param Request $request
* @return Response
*/
#[Permission('岗位数据读取', 'core:post:read')]
public function read(Request $request): Response
{
$id = $request->input('id', '');
$model = $this->logic->read($id);
if ($model) {
$data = is_array($model) ? $model : $model->toArray();
return $this->success($data);
} else {
return $this->fail('not found');
}
}
/**
* 保存数据
* @param Request $request
* @return Response
*/
#[Permission('岗位数据添加', 'core:post:save')]
public function save(Request $request): Response
{
$data = $request->post();
$this->validate('save', $data);
$result = $this->logic->add($data);
if ($result) {
return $this->success('add success');
} else {
return $this->fail('add failed');
}
}
/**
* 更新数据
* @param Request $request
* @return Response
*/
#[Permission('岗位数据修改', 'core:post:update')]
public function update(Request $request): Response
{
$data = $request->post();
$this->validate('update', $data);
$result = $this->logic->edit($data['id'], $data);
if ($result) {
return $this->success('update success');
} else {
return $this->fail('update failed');
}
}
/**
* 删除数据
* @param Request $request
* @return Response
*/
#[Permission('岗位数据删除', 'core:post:destroy')]
public function destroy(Request $request): Response
{
$ids = $request->post('ids', '');
if (empty($ids)) {
return $this->fail('please select data to delete');
}
$result = $this->logic->destroy($ids);
if ($result) {
return $this->success('delete success');
} else {
return $this->fail('delete failed');
}
}
/**
* 导入数据
* @param Request $request
* @return Response
*/
#[Permission('岗位数据导入', 'core:post:import')]
public function import(Request $request): Response
{
$file = current($request->file());
if (!$file || !$file->isValid()) {
return $this->fail('uploaded file not found');
}
$this->logic->import($file);
return $this->success('import success');
}
/**
* 导出数据
* @param Request $request
* @return Response
*/
#[Permission('岗位数据导出', 'core:post:export')]
public function export(Request $request): Response
{
$where = $request->more([
['name', ''],
['code', ''],
['status', ''],
]);
return $this->logic->export($where);
}
/**
* 下载导入模板
* @return Response
*/
public function downloadTemplate(): Response
{
$file_name = "template.xlsx";
return downloadFile($file_name);
}
/**
* 可操作岗位
* @param Request $request
* @return Response
*/
public function accessPost(Request $request): Response
{
$where = ['status' => 1];
$data = $this->logic->accessPost($where);
return $this->success($data);
}
}

View File

@@ -182,7 +182,6 @@ class SystemUserController extends BaseController
{
$data = $request->post();
unset($data['deptList']);
unset($data['postList']);
unset($data['roleList']);
$result = $this->logic->updateInfo($this->adminId, $data);
if ($result) {

View File

@@ -1,95 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\app\logic\system;
use plugin\saiadmin\app\model\system\SystemPost;
use plugin\saiadmin\basic\think\BaseLogic;
use plugin\saiadmin\exception\ApiException;
use plugin\saiadmin\service\OpenSpoutWriter;
use OpenSpout\Reader\XLSX\Reader;
/**
* 岗位管理逻辑层
*/
class SystemPostLogic extends BaseLogic
{
/**
* 构造函数
*/
public function __construct()
{
$this->model = new SystemPost();
}
/**
* 可操作岗位
* @param array $where
* @return array
*/
public function accessPost(array $where = []): array
{
$query = $this->search($where);
$query->field('id, id as value, name as label, name, code');
return $this->getAll($query);
}
/**
* 导入数据
*/
public function import($file)
{
$path = $this->getImport($file);
$reader = new Reader();
try {
$reader->open($path);
$data = [];
foreach ($reader->getSheetIterator() as $sheet) {
$isHeader = true;
foreach ($sheet->getRowIterator() as $row) {
if ($isHeader) {
$isHeader = false;
continue;
}
$cells = $row->getCells();
$data[] = [
'name' => $cells[0]->getValue(),
'code' => $cells[1]->getValue(),
'sort' => $cells[2]->getValue(),
'status' => $cells[3]->getValue(),
];
}
}
$this->saveAll($data);
} catch (\Exception $e) {
throw new ApiException('Import file error, please upload correct xlsx file');
}
}
/**
* 导出数据
*/
public function export($where = [])
{
$query = $this->search($where)->field('id,name,code,sort,status,create_time');
$data = $this->getAll($query);
$file_name = '岗位数据.xlsx';
$header = ['编号', '岗位名称', '岗位标识', '排序', '状态', '创建时间'];
$filter = [
'status' => [
['value' => 1, 'label' => '正常'],
['value' => 2, 'label' => '禁用']
]
];
$writer = new OpenSpoutWriter($file_name);
$writer->setWidth([15, 15, 20, 15, 15, 25]);
$writer->setHeader($header);
$writer->setData($data, null, $filter);
$file_path = $writer->returnFile();
return response()->download($file_path, urlencode($file_name));
}
}

View File

@@ -69,7 +69,6 @@ class SystemUserLogic extends BaseLogic
$admin = $this->model->findOrEmpty($id);
$data = $admin->hidden(['password'])->toArray();
$data['roleList'] = $admin->roles->toArray() ?: [];
$data['postList'] = $admin->posts->toArray() ?: [];
$data['deptList'] = $admin->depts ? $admin->depts->toArray() : [];
return $data;
}
@@ -101,7 +100,6 @@ class SystemUserLogic extends BaseLogic
$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
return $this->transaction(function () use ($data) {
$role_ids = $data['role_ids'] ?? [];
$post_ids = $data['post_ids'] ?? [];
if ($this->adminInfo['id'] > 1) {
// 部门保护
if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
@@ -114,11 +112,7 @@ class SystemUserLogic extends BaseLogic
}
$user = SystemUser::create($data);
$user->roles()->detach();
$user->posts()->detach();
$user->roles()->saveAll($role_ids);
if (!empty($post_ids)) {
$user->posts()->save($post_ids);
}
return $user;
});
}
@@ -134,7 +128,6 @@ class SystemUserLogic extends BaseLogic
unset($data['password']);
return $this->transaction(function () use ($data, $id) {
$role_ids = $data['role_ids'] ?? [];
$post_ids = $data['post_ids'] ?? [];
// 超级管理员可修改任意用户,普通管理员仅可修改当前部门和子部门的用户
$query = $this->model->where('id', $id);
if (isset($this->adminInfo['id']) && $this->adminInfo['id'] > 1) {
@@ -157,11 +150,7 @@ class SystemUserLogic extends BaseLogic
$result = parent::edit($id, $data);
if ($result) {
$user->roles()->detach();
$user->posts()->detach();
$user->roles()->saveAll($role_ids);
if (!empty($post_ids)) {
$user->posts()->save($post_ids);
}
UserInfoCache::clearUserInfo($id);
UserAuthCache::clearUserAuth($id);
UserMenuCache::clearUserMenu($id);

View File

@@ -1,37 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\app\model\system;
use plugin\saiadmin\basic\think\BaseModel;
/**
* 岗位模型
*
* sa_system_post 岗位信息表
*
* @property $id 主键
* @property $name 岗位名称
* @property $code 岗位代码
* @property $sort 排序
* @property $status 状态
* @property $remark 备注
* @property $created_by 创建者
* @property $updated_by 更新者
* @property $create_time 创建时间
* @property $update_time 修改时间
*/
class SystemPost extends BaseModel
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
protected $table = 'sa_system_post';
}

View File

@@ -103,14 +103,6 @@ class SystemUser extends BaseModel
return $this->belongsToMany(SystemRole::class, SystemUserRole::class, 'role_id', 'user_id');
}
/**
* 通过中间表关联岗位
*/
public function posts()
{
return $this->belongsToMany(SystemPost::class, SystemUserPost::class, 'post_id', 'user_id');
}
/**
* 通过中间表关联部门
*/

View File

@@ -1,25 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\app\model\system;
use think\model\Pivot;
/**
* 用户岗位关联模型
*
* sa_system_user_post 用户与岗位关联表
*
* @property $id 主键
* @property $user_id 用户主键
* @property $post_id 岗位主键
*/
class SystemUserPost extends Pivot
{
protected $pk = 'id';
protected $table = 'sa_system_user_post';
}

View File

@@ -1,50 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\app\validate\system;
use plugin\saiadmin\basic\BaseValidate;
/**
* 用户角色验证器
*/
class SystemPostValidate extends BaseValidate
{
/**
* 定义验证规则
*/
protected $rule = [
'name' => 'require',
'code' => 'require',
'status' => 'require',
];
/**
* 定义错误信息
*/
protected $message = [
'name' => '岗位名称必须填写',
'code' => '岗位标识必须填写',
'status' => '状态必须填写',
];
/**
* 定义场景
*/
protected $scene = [
'save' => [
'name',
'code',
'status',
],
'update' => [
'name',
'code',
'status',
],
];
}

View File

@@ -23,6 +23,7 @@ Route::group('/core', function () {
Route::get('/dice/dashboard/rechargeBarChart', [\app\dice\controller\DiceDashboardController::class, 'rechargeBarChart']);
Route::get('/dice/dashboard/walletRecordList', [\app\dice\controller\DiceDashboardController::class, 'walletRecordList']);
Route::get('/dice/dashboard/newPlayerList', [\app\dice\controller\DiceDashboardController::class, 'newPlayerList']);
Route::get('/dice/dashboard/playRecordList', [\app\dice\controller\DiceDashboardController::class, 'playRecordList']);
Route::get('/system/clearAllCache', [plugin\saiadmin\app\controller\SystemController::class, 'clearAllCache']);
Route::get("/system/getResourceCategory", [plugin\saiadmin\app\controller\SystemController::class, 'getResourceCategory']);
@@ -53,11 +54,6 @@ Route::group('/core', function () {
fastRoute("dept", \plugin\saiadmin\app\controller\system\SystemDeptController::class);
Route::get("/dept/accessDept", [\plugin\saiadmin\app\controller\system\SystemDeptController::class, 'accessDept']);
// 岗位管理
fastRoute('post', \plugin\saiadmin\app\controller\system\SystemPostController::class);
Route::get("/post/accessPost", [\plugin\saiadmin\app\controller\system\SystemPostController::class, 'accessPost']);
Route::post("/post/downloadTemplate", [plugin\saiadmin\app\controller\system\SystemPostController::class, 'downloadTemplate']);
// 菜单管理
fastRoute('menu', \plugin\saiadmin\app\controller\system\SystemMenuController::class);
Route::get("/menu/accessMenu", [\plugin\saiadmin\app\controller\system\SystemMenuController::class, 'accessMenu']);

View File

@@ -33,7 +33,6 @@ return [
'expire' => 60 * 60 * 4,
'dept' => 'saiadmin:user_cache:dept_',
'role' => 'saiadmin:user_cache:role_',
'post' => 'saiadmin:user_cache:post_',
],
// 用户权限缓存

View File

@@ -391,7 +391,6 @@ INSERT INTO `sa_system_menu` VALUES (3, 0, '系统管理', 'System', NULL, 1, '/
INSERT INTO `sa_system_menu` VALUES (4, 3, '用户管理', 'User', NULL, 2, 'user', '/system/user', NULL, 'ri:user-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (5, 3, '部门管理', 'Dept', NULL, 2, 'dept', '/system/dept', NULL, 'ri:node-tree', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (6, 3, '角色管理', 'Role', NULL, 2, 'role', '/system/role', NULL, 'ri:admin-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (7, 3, '岗位管理', 'Post', '', 2, 'post', '/system/post', NULL, 'ri:signpost-line', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (8, 3, '菜单管理', 'Menu', NULL, 2, 'menu', '/system/menu', NULL, 'ri:menu-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (10, 0, '运维管理', 'Safeguard', NULL, 1, '/safeguard', '', NULL, 'ri:shield-check-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (11, 10, '缓存管理', 'Cache', '', 2, 'cache', '/safeguard/cache', NULL, 'ri:keyboard-box-line', 80, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
@@ -423,13 +422,6 @@ INSERT INTO `sa_system_menu` VALUES (36, 6, '修改', '', 'core:role:update', 3,
INSERT INTO `sa_system_menu` VALUES (37, 6, '读取', '', 'core:role:read', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (38, 6, '删除', '', 'core:role:destroy', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (39, 6, '菜单权限', '', 'core:role:menu', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (41, 7, '数据列表', '', 'core:post:index', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (42, 7, '添加', '', 'core:post:save', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (43, 7, '修改', '', 'core:post:update', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (44, 7, '读取', '', 'core:post:read', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (45, 7, '删除', '', 'core:post:destroy', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (46, 7, '导入', '', 'core:post:import', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (47, 7, '导出', '', 'core:post:export', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (48, 8, '数据列表', '', 'core:menu:index', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (49, 8, '读取', '', 'core:menu:read', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (50, 8, '添加', '', 'core:menu:save', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
@@ -501,31 +493,6 @@ CREATE TABLE `sa_system_oper_log` (
-- Records of sa_system_oper_log
-- ----------------------------
-- ----------------------------
-- Table structure for sa_system_post
-- ----------------------------
DROP TABLE IF EXISTS `sa_system_post`;
CREATE TABLE `sa_system_post` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(50) NULL DEFAULT NULL COMMENT '岗位名称',
`code` varchar(100) NULL DEFAULT NULL COMMENT '岗位代码',
`sort` smallint(5) UNSIGNED NULL DEFAULT 0 COMMENT '排序',
`status` smallint(6) NULL DEFAULT 1 COMMENT '状态 (1正常 2停用)',
`remark` varchar(255) NULL DEFAULT NULL COMMENT '备注',
`created_by` int(11) NULL DEFAULT NULL COMMENT '创建者',
`updated_by` int(11) NULL DEFAULT NULL COMMENT '更新者',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
`delete_time` datetime(0) NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 87 COMMENT = '岗位信息表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sa_system_post
-- ----------------------------
INSERT INTO `sa_system_post` VALUES (1, '司机岗', 'driver', 100, 1, '', 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_post` VALUES (2, '保安岗', 'security', 100, 1, '', 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
-- ----------------------------
-- Table structure for sa_system_role
-- ----------------------------
@@ -635,23 +602,6 @@ INSERT INTO `sa_system_user` VALUES (10, 'timi_boss', '$2y$10$sY/4StKVV.N/8Ock8J
INSERT INTO `sa_system_user` VALUES (100, 'dev_wang', '$2y$10$sY/4StKVV.N/8Ock8J8kdeIOK4jS4tAUoYjkzvB8Tzy0fLh.wA2KS', '王程序员', NULL, 'https://image.saithink.top/saiadmin/avatar.jpg', NULL, '15888888888', NULL, 'work', 1111, 0, 1, NULL, NULL, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_user` VALUES (101, 'dev_li', '$2y$10$sY/4StKVV.N/8Ock8J8kdeIOK4jS4tAUoYjkzvB8Tzy0fLh.wA2KS', '李策划', NULL, 'https://image.saithink.top/saiadmin/avatar.jpg', NULL, '15888888888', NULL, 'work', 1111, 0, 1, NULL, NULL, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
-- ----------------------------
-- Table structure for sa_system_user_post
-- ----------------------------
DROP TABLE IF EXISTS `sa_system_user_post`;
CREATE TABLE `sa_system_user_post` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户主键',
`post_id` bigint(20) UNSIGNED NOT NULL COMMENT '岗位主键',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_user_id`(`user_id`) USING BTREE,
INDEX `idx_post_id`(`post_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 COMMENT = '用户与岗位关联表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sa_system_user_post
-- ----------------------------
-- ----------------------------
-- Table structure for sa_system_user_role
-- ----------------------------

View File

@@ -380,7 +380,6 @@ INSERT INTO `sa_system_menu` VALUES (3, 0, '系统管理', 'System', NULL, 1, '/
INSERT INTO `sa_system_menu` VALUES (4, 3, '用户管理', 'User', NULL, 2, 'user', '/system/user', NULL, 'ri:user-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (5, 3, '部门管理', 'Dept', NULL, 2, 'dept', '/system/dept', NULL, 'ri:node-tree', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (6, 3, '角色管理', 'Role', NULL, 2, 'role', '/system/role', NULL, 'ri:admin-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (7, 3, '岗位管理', 'Post', '', 2, 'post', '/system/post', NULL, 'ri:signpost-line', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (8, 3, '菜单管理', 'Menu', NULL, 2, 'menu', '/system/menu', NULL, 'ri:menu-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (10, 0, '运维管理', 'Safeguard', NULL, 1, '/safeguard', '', NULL, 'ri:shield-check-line', 100, NULL, 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (11, 10, '缓存管理', 'Cache', '', 2, 'cache', '/safeguard/cache', NULL, 'ri:keyboard-box-line', 80, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
@@ -412,13 +411,6 @@ INSERT INTO `sa_system_menu` VALUES (36, 6, '修改', '', 'core:role:update', 3,
INSERT INTO `sa_system_menu` VALUES (37, 6, '读取', '', 'core:role:read', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (38, 6, '删除', '', 'core:role:destroy', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (39, 6, '菜单权限', '', 'core:role:menu', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (41, 7, '数据列表', '', 'core:post:index', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (42, 7, '添加', '', 'core:post:save', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (43, 7, '修改', '', 'core:post:update', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (44, 7, '读取', '', 'core:post:read', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (45, 7, '删除', '', 'core:post:destroy', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (46, 7, '导入', '', 'core:post:import', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (47, 7, '导出', '', 'core:post:export', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (48, 8, '数据列表', '', 'core:menu:index', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (49, 8, '读取', '', 'core:menu:read', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
INSERT INTO `sa_system_menu` VALUES (50, 8, '添加', '', 'core:menu:save', 3, '', '', NULL, '', 100, '', 2, 2, 2, 2, 2, 0, NULL, 1, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
@@ -490,25 +482,6 @@ CREATE TABLE `sa_system_oper_log` (
-- Records of sa_system_oper_log
-- ----------------------------
-- ----------------------------
-- Table structure for sa_system_post
-- ----------------------------
DROP TABLE IF EXISTS `sa_system_post`;
CREATE TABLE `sa_system_post` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(50) NULL DEFAULT NULL COMMENT '岗位名称',
`code` varchar(100) NULL DEFAULT NULL COMMENT '岗位代码',
`sort` smallint(5) UNSIGNED NULL DEFAULT 0 COMMENT '排序',
`status` smallint(6) NULL DEFAULT 1 COMMENT '状态 (1正常 2停用)',
`remark` varchar(255) NULL DEFAULT NULL COMMENT '备注',
`created_by` int(11) NULL DEFAULT NULL COMMENT '创建者',
`updated_by` int(11) NULL DEFAULT NULL COMMENT '更新者',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
`delete_time` datetime(0) NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 87 COMMENT = '岗位信息表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for sa_system_role
-- ----------------------------
@@ -606,23 +579,6 @@ CREATE TABLE `sa_system_user` (
-- ----------------------------
INSERT INTO `sa_system_user` VALUES (1, 'admin', '$2y$10$wnixh48uDnaW/6D9EygDd.OHJK0vQY/4nHaTjMKBCVDBP2NiTatqS', '祭道之上', '2', 'https://image.saithink.top/saiadmin/avatar.jpg', 'saiadmin@admin.com', '15888888888', 'SaiAdmin是兼具设计美学与高效开发的后台系统!', 'statistics', 1, 1, 1, NULL, NULL, NULL, 1, 1, '2026-01-01 00:00:00', '2026-01-01 00:00:00', NULL);
-- ----------------------------
-- Table structure for sa_system_user_post
-- ----------------------------
DROP TABLE IF EXISTS `sa_system_user_post`;
CREATE TABLE `sa_system_user_post` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户主键',
`post_id` bigint(20) UNSIGNED NOT NULL COMMENT '岗位主键',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_user_id`(`user_id`) USING BTREE,
INDEX `idx_post_id`(`post_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 COMMENT = '用户与岗位关联表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sa_system_user_post
-- ----------------------------
-- ----------------------------
-- Table structure for sa_system_user_role
-- ----------------------------