wujingjing
2024-10-24 da056d7380fff877f01c88769af3fc6d5cad7c00
角色管理和访问日志
已修改5个文件
已添加1个文件
459 ■■■■■ 文件已修改
src/api/auth/log.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/systemManage/accessLog/AccessLog.vue 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/systemManage/roleMgr/RoleMgr.vue 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/systemManage/userMgr/UserMgr.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/auth/log.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
import request, { ExtraConfig } from '/@/utils/request';
/**
 * @description èŽ·å–æ—¥å¿—ä¿¡æ¯
 * @param {FormData} params
 **/
export const getOperateLog = (
    params,
    extraData: ExtraConfig = {}
) =>
    request({
        url: `/admin/log/get_operate_log`,
        method: 'post',
        params: {},
        data: params,
        ...extraData,
    });
src/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue
@@ -47,7 +47,7 @@
<script setup lang="ts">
import { ElDatePicker } from 'element-plus';
import { definePropType } from 'element-plus/es/utils/vue/props/runtime';
import { ref, type PropType, computed, watch, nextTick } from 'vue';
import { ref, type PropType, computed, watch, nextTick, onMounted } from 'vue';
import type { TimeRangeParam } from '../types';
import type { TimeRangeEnum } from './types';
import { timeRangeEnumMapTitle, timeRangeEnumMapValue } from './types';
@@ -71,6 +71,11 @@
        type: Boolean,
        default: false,
    },
    quickActive: {
        type: Number as PropType<TimeRangeEnum>,
        required: false,
    },
});
const dateValue = defineModel({
    type: definePropType<[string, string]>(Array),
@@ -91,11 +96,16 @@
    quickPickValue.value = null;
};
const quickPickValue = ref<TimeRangeEnum>(null);
const quickPickRangeClick = (val: TimeRangeEnum) => {
    if (quickPickValue.value === val) return;
const pickQuickRange = (val: TimeRangeEnum) => {
    if(val==undefined) return;
    quickPickValue.value = val;
    dateValue.value = timeRangeEnumMapValue[val]().map((item) => formatDate(item)) as [string, string];
};
const quickPickRangeClick = (val: TimeRangeEnum) => {
    if (quickPickValue.value === val) return;
    pickQuickRange(val);
    dateChange();
};
@@ -121,6 +131,12 @@
    dateChange();
};
onMounted(() => {
    if(props.quickActive !=null){
        pickQuickRange(props.quickActive);
    }
});
defineExpose({
    formatDateValue: dateValue,
});
src/views/project/yw/systemManage/accessLog/AccessLog.vue
@@ -1,6 +1,174 @@
<template>
    <div>AccessLog</div>
    <HMContainer type="card">
        <template #header>
            <el-form ref="queryFormRef" :inline="true" :model="queryParams">
                <el-form-item label="日期范围" prop="timeRange">
                    <TimeRange v-model="queryParams.timeRange" :quickActive="TimeRangeEnum.CurrentDay" @change="handleQueryTable" />
                </el-form-item>
                <el-form-item label="操作类型" prop="type">
                    <el-input v-model="queryParams.type" style="width: 226.4px" placeholder="操作类型" clearable @input="debounceQueryTable" />
                </el-form-item>
                <el-form-item label="操作人员" prop="user">
                    <el-input v-model="queryParams.user" style="width: 226.4px" placeholder="操作人员" clearable @input="debounceQueryTable" />
                </el-form-item>
            </el-form>
        </template>
        <template #main>
            <div class="h-full" ref="chatDragContainerRef">
                <el-table
                    v-loading="tableLoading"
                    ref="draggableTableRef"
                    class="h100"
                    border
                    :row-class-name="isDragStatus ? 'cursor-move' : 'cursor-pointer'"
                    :data="tableData"
                    highlight-current-row
                >
                    <el-table-column prop="time" label="时间" width="185" fixed="left" show-overflow-tooltip> </el-table-column>
                    <el-table-column label="用户" prop="user" width="70" show-overflow-tooltip> </el-table-column>
                    <el-table-column label="类型" prop="type" show-overflow-tooltip> </el-table-column>
                </el-table>
            </div>
        </template>
    </HMContainer>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { debounce, getItemMap } from '/@/utils/util';
import { onMounted, ref } from 'vue';
import * as userApi from '/@/api/auth/user';
import { getRoleInfoListByPost } from '/@/api/auth/role';
import HMContainer from '/@/components/layout/HMContainer.vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { computed } from 'vue';
import TimeRange from '/@/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue';
import { TimeRangeEnum } from '/@/components/chat/chatComponents/summaryCom/components/recordSet/components/types';
import { getOperateLog } from '/@/api/auth/log';
import { nextTick } from 'vue';
//#region ====================== è¡¨æ ¼æ•°æ®ï¼Œtable init ======================
const tableLoading = ref(false);
const tableData = ref([]);
const isDragStatus = ref(false);
//#endregion
//#region ====================== è¡¨æ ¼æŸ¥è¯¢ã€æŽ’序,search form init ======================
const queryParams = ref({
    timeRange: [],
    type: '',
    user: '',
});
const handleQueryTable = async () => {
    const res = await getOperateLog({
        start_time: queryParams.value.timeRange[0],
        end_time: queryParams.value.timeRange[1],
        type: queryParams.value.type,
        user: queryParams.value.user,
    });
    tableData.value = res?.values ?? [];
};
const debounceQueryTable = debounce(handleQueryTable, 400);
//#endregion
//#region ====================== æ·»åŠ ä¿®æ”¹æ“ä½œ ======================
const optDlgIsShow = ref(false);
const optDlgMapRow = ref(null);
const openOptDlg = (row?: any) => {
    optDlgMapRow.value = row;
    optDlgIsShow.value = true;
};
const updateOpt = (formValue) => {
    const foundIndex = tableData.value.findIndex((item) => item.user_id === formValue.user_id);
    if (foundIndex > -1) {
        tableData.value[foundIndex] = {
            ...tableData.value[foundIndex],
            ...formValue,
        };
    }
};
const insertOpt = (newData) => {
    tableData.value.push({ ...newData });
};
//#endregion
const deleteCurrentRow = (row: any) => {
    ElMessageBox.confirm(`确定删除用户:【${row.user_name}】?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }).then(async () => {
        const res = await userApi.deleteUserInfoByPost({
            user_id: row.user_id,
        });
        const foundIndex = tableData.value.findIndex((item) => item === row);
        foundIndex > -1 && tableData.value.splice(foundIndex, 1);
        ElMessage.success('删除用户成功');
    });
};
//#region ====================== ä¿®æ”¹å¯†ç æ“ä½œ ======================
const optPasswordDlgIsShow = ref(false);
const optPasswordDlgMapRow = ref(null);
const openOptPasswordDlg = (row?: any) => {
    optPasswordDlgMapRow.value = row;
    optPasswordDlgIsShow.value = true;
};
const updatePasswordOpt = (formValue) => {
    const foundIndex = tableData.value.findIndex((item) => item.user_id === formValue.user_id);
    if (foundIndex > -1) {
        tableData.value[foundIndex] = {
            ...tableData.value[foundIndex],
            ...formValue,
        };
    }
};
//#endregion
//#region ====================== ä¿®æ”¹è§’色操作 ======================
const optRoleDlgIsShow = ref(false);
const optRoleDlgMapRow = ref(null);
const openOptRoleDlg = (row?: any) => {
    optRoleDlgMapRow.value = row;
    optRoleDlgIsShow.value = true;
};
const updateRoleOpt = (formValue) => {
    const foundIndex = tableData.value.findIndex((item) => item.user_id === formValue.user_id);
    if (foundIndex > -1) {
        tableData.value[foundIndex] = {
            ...tableData.value[foundIndex],
            ...formValue,
        };
    }
};
//#endregion
const roleList = ref([]);
const roleMap = computed(() => getItemMap(roleList.value, 'id'));
const getRoleList = async () => {
    const res = await getRoleInfoListByPost();
    roleList.value = res?.values ?? [];
};
onMounted(async () => {
    nextTick(() => {
        handleQueryTable();
    });
});
</script>
<style scoped lang="scss"></style>
src/views/project/yw/systemManage/roleMgr/RoleMgr.vue
@@ -1,6 +1,211 @@
<template>
    <div>RoleMgr</div>
    <HMContainer type="card">
        <template #header>
            <el-form ref="queryFormRef" :inline="true" :model="queryParams">
                <el-form-item label="名称" prop="title">
                    <el-input v-model="queryParams.title" style="width: 226.4px" placeholder="名称" clearable @input="debounceQueryTable" />
                </el-form-item>
                <!-- <el-form-item>
                    <el-button icon="ele-Plus" @click="openOptDlg()" type="primary"> æ·»åŠ  </el-button>
                </el-form-item> -->
            </el-form>
        </template>
        <template #main>
            <div class="h-full" ref="chatDragContainerRef">
                <el-table
                    v-loading="tableLoading"
                    ref="draggableTableRef"
                    class="h100"
                    border
                    :row-class-name="isDragStatus ? 'cursor-move' : 'cursor-pointer'"
                    :data="displayTableData"
                    highlight-current-row
                >
                    <el-table-column prop="title" label="名称" fixed="left" show-overflow-tooltip> </el-table-column>
                    <!-- <el-table-column label="角色编码" prop="value" width="90" show-overflow-tooltip> </el-table-column> -->
                    <!-- <el-table-column label="操作" width="180" fixed="right" show-overflow-tooltip>
                        <template #default="scope">
                            <div class="space-x-3 items-center flex">
                                <el-tooltip effect="dark" content="编辑" placement="top">
                                    <i class="ywifont ywicon-bianji !text-[15px] text-blue-400 cursor-pointer" @click="openOptDlg(scope.row)"></i>
                                </el-tooltip>
                                <el-tooltip effect="dark" content="修改密码" placement="top">
                                    <i
                                        class="ywifont ywicon-mima !text-[15px] text-blue-400 cursor-pointer font-bold"
                                        @click="openOptPasswordDlg(scope.row)"
                                    ></i>
                                </el-tooltip>
                                <el-tooltip effect="dark" content="修改角色" placement="top">
                                    <i
                                        class="ywifont ywicon-jiaose !text-[15px] text-blue-400 cursor-pointer font-bold"
                                        @click="openOptRoleDlg(scope.row)"
                                    ></i>
                                </el-tooltip>
                                <el-tooltip effect="dark" content="删除" placement="top">
                                    <i class="ywifont ywicon-shanchu !text-[17px] text-red-400 cursor-pointer" @click="deleteCurrentRow(scope.row)"></i>
                                </el-tooltip>
                            </div>
                        </template>
                    </el-table-column> -->
                </el-table>
            </div>
        </template>
        <!-- <OptDlg v-model="optDlgIsShow" :item="optDlgMapRow" @insert="insertOpt" @update="updateOpt" :roleList="roleList"></OptDlg>
        <OptPasswordDlg
            v-model="optPasswordDlgIsShow"
            :item="optPasswordDlgMapRow"
            @update="updatePasswordOpt"
            :roleList="roleList"
        ></OptPasswordDlg>
        <OptRoleDlg v-model="optRoleDlgIsShow" :item="optRoleDlgMapRow" @update="updateRoleOpt" :roleList="roleList"></OptRoleDlg> -->
        <!-- <MetricPrompt v-model="infoDlgIsShow" :metricItem="infoDlgMapRow"></MetricPrompt>
        <MetricName v-model="metricNameIsShow" :metricItem="metricNameMapRow"></MetricName> -->
    </HMContainer>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { debounce, getItemMap } from '/@/utils/util';
import { onMounted, ref } from 'vue';
import { usePageDisplay } from '/@/hooks/usePageDisplay';
import { useQueryTable } from '/@/hooks/useQueryTable';
// import { useTableSort } from '/@/hooks/useTableSort';
// import { useValidateUniqueness } from '/@/hooks/useValidateUniqueness';
import OptDlg from './optDlg/OptDlg.vue';
import OptPasswordDlg from './optDlg/OptPasswordDlg.vue';
import OptRoleDlg from './optDlg/OptRoleDlg.vue';
import * as userApi from '/@/api/auth/user';
import { getRoleInfoListByPost } from '/@/api/auth/role';
import HMContainer from '/@/components/layout/HMContainer.vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { computed } from 'vue';
//#region ====================== è¡¨æ ¼æ•°æ®ï¼Œtable init ======================
const tableLoading = ref(false);
const tableData = ref([]);
const isDragStatus = ref(false);
const getTableData = async () => {
    const res = await getRoleInfoListByPost();
    tableData.value = res?.values ?? [];
};
//#endregion
//#region ====================== è¡¨æ ¼æŸ¥è¯¢ã€æŽ’序,search form init ======================
const queryParams = ref({
    title: '',
});
const { resetQuery, handleQueryTable, displayTableData } = useQueryTable(tableData, queryParams, () => {
    displayTableData.value = tableData.value;
});
const debounceQueryTable = debounce(handleQueryTable, 400);
//#endregion
//#region ====================== æŸ¥è¯¢å¿«æ·é”® ======================
const queryFormRef = ref(null);
const pressEnterSearch = (ev: KeyboardEvent) => {
    if (ev.key === 'Enter') {
        handleQueryTable();
    }
};
usePageDisplay(
    () => {
        queryFormRef.value?.$el?.addEventListener('keypress', pressEnterSearch);
    },
    () => {
        queryFormRef.value?.$el?.removeEventListener('keypress', pressEnterSearch);
    }
);
//#endregion
//#region ====================== æ·»åŠ ä¿®æ”¹æ“ä½œ ======================
const optDlgIsShow = ref(false);
const optDlgMapRow = ref(null);
const openOptDlg = (row?: any) => {
    optDlgMapRow.value = row;
    optDlgIsShow.value = true;
};
const updateOpt = (formValue) => {
    const foundIndex = tableData.value.findIndex((item) => item.user_id === formValue.user_id);
    if (foundIndex > -1) {
        tableData.value[foundIndex] = {
            ...tableData.value[foundIndex],
            ...formValue,
        };
    }
};
const insertOpt = (newData) => {
    tableData.value.push({ ...newData });
};
//#endregion
const deleteCurrentRow = (row: any) => {
    ElMessageBox.confirm(`确定删除用户:【${row.user_name}】?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }).then(async () => {
        const res = await userApi.deleteUserInfoByPost({
            user_id: row.user_id,
        });
        const foundIndex = tableData.value.findIndex((item) => item === row);
        foundIndex > -1 && tableData.value.splice(foundIndex, 1);
        ElMessage.success('删除用户成功');
    });
};
//#region ====================== ä¿®æ”¹å¯†ç æ“ä½œ ======================
const optPasswordDlgIsShow = ref(false);
const optPasswordDlgMapRow = ref(null);
const openOptPasswordDlg = (row?: any) => {
    optPasswordDlgMapRow.value = row;
    optPasswordDlgIsShow.value = true;
};
const updatePasswordOpt = (formValue) => {
    const foundIndex = tableData.value.findIndex((item) => item.user_id === formValue.user_id);
    if (foundIndex > -1) {
        tableData.value[foundIndex] = {
            ...tableData.value[foundIndex],
            ...formValue,
        };
    }
};
//#endregion
//#region ====================== ä¿®æ”¹è§’色操作 ======================
const optRoleDlgIsShow = ref(false);
const optRoleDlgMapRow = ref(null);
const openOptRoleDlg = (row?: any) => {
    optRoleDlgMapRow.value = row;
    optRoleDlgIsShow.value = true;
};
const updateRoleOpt = (formValue) => {
    const foundIndex = tableData.value.findIndex((item) => item.user_id === formValue.user_id);
    if (foundIndex > -1) {
        tableData.value[foundIndex] = {
            ...tableData.value[foundIndex],
            ...formValue,
        };
    }
};
//#endregion
onMounted(async () => {
    getTableData();
});
</script>
<style scoped lang="scss"></style>
src/views/project/yw/systemManage/userMgr/UserMgr.vue
@@ -7,8 +7,7 @@
                </el-form-item>
                <el-form-item>
                    <el-button icon="ele-Refresh" @click="resetQuery">重置 </el-button>
                    <el-button icon="ele-Plus" @click="openOptDlg()"> æ·»åŠ  </el-button>
                    <el-button icon="ele-Plus" @click="openOptDlg()" type="primary"> æ·»åŠ  </el-button>
                </el-form-item>
            </el-form>
        </template>
@@ -228,38 +227,6 @@
//#endregion
//#region ====================== æ”¹å˜å‘布状态 ======================
// const publishStatusChange = async (published: SupervisorPublished, id, index) => {
//     const res = await updatePublishStatus(
//         {
//             id: id,
//             publish: published,
//         },
//         {
//             loading: false,
//         }
//     );
//     const origin = published === SupervisorPublished.Y ? SupervisorPublished.N : SupervisorPublished.Y;
//     const final = res.publish ?? origin;
//     if (final === origin) {
//         ElMessage.warning('操作失败' + (res.fail_msg ? `:${res.fail_msg}` : ''));
//         return;
//     }
//     tableData.value[index].published = final;
//     published === SupervisorPublished.Y ? ElMessage.success('发布成功') : ElMessage.info('已取消发布');
// };
//#endregion
//#region ====================== æ›´æ–°å‘布状态 ======================
// useUpdateData({
//     event: 'supervisor.publish',
//     updateFun({ id, published }) {
//         updatePublishedById(id, published);
//     },
// });
//#endregion
const roleList = ref([]);
const roleMap = computed(() => getItemMap(roleList.value, 'id'));
vite.config.ts
@@ -39,7 +39,7 @@
            host: '0.0.0.0',
            port: env.VITE_PORT as unknown as number,
            open: JSON.parse(env.VITE_OPEN),
            hmr: true,
            hmr: false,
            proxy: {
                '/gitee': {
                    target: 'https://gitee.com',