Browse Source

菜单管理

ZaiZai 1 year ago
parent
commit
333b9bf865

+ 74 - 0
src/api/modules/system/app.js

@@ -0,0 +1,74 @@
+import { HcApi } from '../../request/index'
+
+export default {
+    async page(form) {
+        return HcApi({
+            url: '/api/blade-manager/appVersion/page',
+            method: 'get',
+            params: form,
+        }, false)
+    },
+    async detail(id) {
+        return HcApi({
+            url: '/api/blade-system/tenant/detail',
+            method: 'get',
+            params: {
+                id,
+            },
+        }, false)
+    },
+    async add(form) {
+        return HcApi({
+            url: '/api/blade-manager/appVersion/add',
+            method: 'post',
+            data: form,
+        }, false)
+    },
+    async update(form) {
+        return HcApi({
+            url: '/api/blade-manager/appVersion/update',
+            method: 'post',
+            data: form,
+        }, false)
+    },
+    async del(id) {
+        return HcApi({
+            url: '/api/blade-manager/appVersion/delete',
+            method: 'post',
+            params: {
+                id,
+            },
+        }, false)
+    },
+    //升级版本
+    async getDetailList(form) {
+        return HcApi({
+            url: '/api/blade-manager/appVersionDetail/page',
+            method: 'get',
+            params: form,
+        }, false)
+    },
+    async updateDetail(form) {
+        return HcApi({
+            url: '/api/blade-manager/appVersionDetail/update',
+            method: 'post',
+            data: form,
+        }, false)
+    },
+    async addDetail(form) {
+        return HcApi({
+            url: '/api/blade-manager/appVersionDetail/add',
+            method: 'post',
+            data: form,
+        }, false)
+    },
+    async removeDetail(id) {
+        return HcApi({
+            url: '/api/blade-manager/appVersionDetail/delete',
+            method: 'get',
+            params: {
+                id,
+            },
+        }, false)
+    },
+}

+ 37 - 0
src/api/modules/system/role.js

@@ -0,0 +1,37 @@
+import { HcApi } from '../../request/index'
+
+export default {
+    async page(form) {
+        return HcApi({
+            url: '/api/blade-system/param/list',
+            method: 'get',
+            params: form,
+        }, false)
+    },
+    //菜单详情
+    async detail(id) {
+        return HcApi({
+            url: '/api/blade-system/param/detail',
+            method: 'get',
+            params: {
+                id,
+            },
+        }, false)
+    },
+    async submit(form) {
+        return HcApi({
+            url: '/api/blade-system/param/submit',
+            method: 'post',
+            data: form,
+        }, false)
+    },
+    async del(ids) {
+        return HcApi({
+            url: '/api/blade-system/param/remove',
+            method: 'post',
+            params: {
+                ids,
+            },
+        }, false)
+    },
+}

+ 37 - 0
src/api/modules/system/user.js

@@ -0,0 +1,37 @@
+import { HcApi } from '../../request/index'
+
+export default {
+    async page(form) {
+        return HcApi({
+            url: '/api/blade-system/param/list',
+            method: 'get',
+            params: form,
+        }, false)
+    },
+    //菜单详情
+    async detail(id) {
+        return HcApi({
+            url: '/api/blade-system/param/detail',
+            method: 'get',
+            params: {
+                id,
+            },
+        }, false)
+    },
+    async submit(form) {
+        return HcApi({
+            url: '/api/blade-system/param/submit',
+            method: 'post',
+            data: form,
+        }, false)
+    },
+    async del(ids) {
+        return HcApi({
+            url: '/api/blade-system/param/remove',
+            method: 'post',
+            params: {
+                ids,
+            },
+        }, false)
+    },
+}

+ 12 - 0
src/router/modules/base.js

@@ -58,6 +58,18 @@ export default [
                 meta: { title: '菜单管理' },
                 component: () => import('~src/views/system/menu.vue'),
             },
+            {
+                path: '/system/app',
+                name: 'app',
+                meta: { title: 'App管理' },
+                component: () => import('~src/views/system/app.vue'),
+            },
+            {
+                path: '/system/user',
+                name: 'user',
+                meta: { title: '用户管理' },
+                component: () => import('~src/views/system/user.vue'),
+            },
         ],
     },
     {

+ 476 - 0
src/views/system/app.vue

@@ -0,0 +1,476 @@
+<template>
+    <hc-new-card>
+        <template #header>
+            <div class="w-60">
+                <hc-search-input v-model="searchForm.name" placeholder="请输入名称关键词" @search="searchClick" />
+            </div>
+        </template>
+        <template #extra>
+            <el-button hc-btn type="primary" @click="addClick">新增</el-button>
+        </template>
+        <hc-table :column="tableColumn" :datas="tableData" :loading="tableLoading" is-new :index-style="{ width: 60 }">
+            <template #action="{ row }">
+                <el-link type="warning" @click="editRowClick(row)">修改</el-link>
+                <el-link type="primary" @click="updateRowClick(row)">升级</el-link>
+                <el-link type="danger" @click="delRowClick(row)">删除</el-link>
+            </template>
+        </hc-table>
+        <template #action>
+            <hc-pages :pages="searchForm" @change="pageChange" />
+        </template>
+
+        <!-- 新增/修改 -->
+        <hc-new-dialog v-model="isDialogShow" widths="400px" is-footer-center :title="dialogTitle" @close="dialogClose">
+            <el-form ref="formRef" :model="formModel" :rules="formRules" label-position="top" label-width="auto">
+                <el-form-item label="应用平台:" prop="platform">
+                    <el-input v-model="formModel.platform" clearable placeholder="请输入应用平台" />
+                </el-form-item>
+                <el-form-item label="应用名称:" prop="name">
+                    <el-input v-model="formModel.name" clearable placeholder="请输入应用名称" />
+                </el-form-item>
+                <el-form-item label="当前版本:" prop="currentVersion">
+                    <el-input v-model="formModel.currentVersion" clearable placeholder="请输入当前版本号" />
+                </el-form-item>
+                <el-form-item label="应用说明:">
+                    <el-input v-model="formModel.appExplain" :autosize="{ minRows: 4, maxRows: 8 }" type="textarea" placeholder="请输入应用说明" />
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                <el-button hc-btn @click="dialogClose">取消</el-button>
+                <el-button hc-btn type="primary" :loading="submitLoading" @click="dialogSubmit">提交</el-button>
+            </template>
+        </hc-new-dialog>
+
+        <!-- APP升级列表 -->
+        <hc-new-dialog v-model="isUpdateDialog" ui="hc-app-update-dialog" widths="700px" is-table @close="updateDialogClose">
+            <template #header>
+                <el-button hc-btn type="primary" @click="addUpdateClick">新增版本</el-button>
+                <div class="hc-update-dialog-title">{{ updateDialogTitle }}</div>
+            </template>
+            <hc-table :column="tableUpdateColumn" :datas="tableUpdateData" :loading="tableUpdateLoading" is-new :index-style="{ width: 60 }">
+                <template #softwareType="{ row }">
+                    {{ row.softwareType === 1 ? '安卓' : 'IOS' }}
+                </template>
+                <template #fileType="{ row }">
+                    {{ row.fileType === 0 ? '完整' : 'wgt' }}
+                </template>
+                <template #constraintUpdate="{ row }">
+                    {{ row.fileType === 1 ? '是' : '否' }}
+                </template>
+                <template #action="{ row }">
+                    <el-link type="warning" @click="editUpdateRow(row)">修改</el-link>
+                    <el-link type="danger" @click="delUpdateRow(row)">删除</el-link>
+                </template>
+            </hc-table>
+            <template #footer>
+                <hc-pages :pages="searchUpdateForm" @change="pageUpdateChange" />
+            </template>
+        </hc-new-dialog>
+
+        <!-- 新增/修改 APP升级 -->
+        <hc-new-dialog v-model="isUpdateFormDialog" widths="550px" is-footer-center :title="updateFormTitle" @close="updateFormDialogClose">
+            <el-form ref="formUpdateRef" :model="formUpdateModel" :rules="formUpdateRules" label-position="left" label-width="auto">
+                <el-form-item label="当前版本:" prop="versionNumber">
+                    <el-input v-model="formUpdateModel.versionNumber" clearable placeholder="请输入当前版本号" />
+                </el-form-item>
+                <el-form-item label="软件类型:" prop="softwareType">
+                    <el-radio-group v-model="formUpdateModel.softwareType">
+                        <el-radio :label="1">安卓</el-radio>
+                        <el-radio :label="2">ios</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item label="文件类型:" prop="fileType">
+                    <el-radio-group v-model="formUpdateModel.fileType">
+                        <el-radio :label="0">完整安装包</el-radio>
+                        <el-radio :label="1">wgt热更新包</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item label="更新内容:" prop="updateContent">
+                    <el-input v-model="formUpdateModel.updateContent" :autosize="{ minRows: 4, maxRows: 8 }" type="textarea" placeholder="请输入更新内容" />
+                </el-form-item>
+                <el-form-item label="文件地址:" prop="fileUrl">
+                    <el-input v-model="formUpdateModel.fileUrl" clearable>
+                        <template #append>
+                            <el-button @click="uploadFile">上传文件</el-button>
+                        </template>
+                    </el-input>
+                </el-form-item>
+                <el-form-item label="强制更新:" prop="constraintUpdate">
+                    <el-radio-group v-model="formUpdateModel.constraintUpdate">
+                        <el-radio :label="1">是</el-radio>
+                        <el-radio :label="0">否</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                <el-button hc-btn @click="updateFormDialogClose">取消</el-button>
+                <el-button hc-btn type="primary" :loading="submitUpdateLoading" @click="dialogUpdateSubmit">提交</el-button>
+            </template>
+        </hc-new-dialog>
+
+        <!-- 上传文件 -->
+        <hc-upload-file ref="uploadRef" :options="uploadOptions" @success="uploadSuccess" />
+    </hc-new-card>
+</template>
+
+<script setup>
+import { nextTick, onActivated, ref } from 'vue'
+import { formValidate, getArrValue } from 'js-fast-way'
+import { delMessage } from '~uti/tools'
+import mainApi from '~api/system/app'
+import { getHeader } from 'hc-vue3-ui'
+
+//激活
+onActivated(() => {
+    searchForm.value.current = 1
+    getTableData()
+})
+
+//搜索表单
+const searchForm = ref({ current: 1, size: 30, total: 0 })
+
+//搜索
+const searchClick = () => {
+    searchForm.value.current = 1
+    getTableData()
+}
+
+//分页
+const pageChange = ({ current, size }) => {
+    searchForm.value.current = current
+    searchForm.value.size = size
+    getTableData()
+}
+
+//表格数据
+const tableColumn = ref([
+    { key: 'platform', name: '应用平台' },
+    { key: 'name', name: '应用名称' },
+    { key: 'currentVersion', name: '当前版本' },
+    { key: 'updateTime', name: '更新时间' },
+    { key: 'action', name: '操作', width: 120, align: 'center' },
+])
+
+//获取表格数据
+const tableLoading = ref(false)
+const tableData = ref([{}])
+const getTableData = async () => {
+    tableData.value = []
+    tableLoading.value = true
+    const { error, code, data } = await mainApi.page({
+        ...searchForm.value,
+        total: null,
+    })
+    tableLoading.value = false
+    if (!error && code === 200) {
+        tableData.value = getArrValue(data['records'])
+        searchForm.value.total = data['total']
+    } else {
+        tableData.value = []
+        searchForm.value.total = 0
+    }
+}
+
+//新增/修改 弹窗
+const isDialogShow = ref(false)
+const dialogTitle = ref('')
+
+//菜单表单
+const formRef = ref(null)
+const formModel = ref({})
+const formRules = {
+    platform: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入应用平台',
+    },
+    name: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入应用名称',
+    },
+    currentVersion: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入当前版本号',
+    },
+}
+
+//新增
+const addClick = () => {
+    dialogTitle.value = '新增APP'
+    formModel.value = {}
+    //显示表单弹窗
+    nextTick(() => {
+        isDialogShow.value = true
+    })
+}
+
+//修改
+const editRowClick = (row) => {
+    formModel.value = {}
+    dialogTitle.value = '修改APP'
+    formModel.value = { ...row }
+    //显示表单弹窗
+    nextTick(() => {
+        isDialogShow.value = true
+    })
+}
+
+//删除
+const delRowClick = (row) => {
+    delMessage(async () => {
+        const { code, msg } = await mainApi.del(row.id)
+        if (code === 200) {
+            window.$message.success('删除成功')
+            dialogClose()
+            getTableData().then()
+        } else {
+            window.$message.error(msg ?? '删除失败')
+        }
+    })
+}
+
+//提交表单
+const submitLoading = ref(false)
+const dialogSubmit = async () => {
+    const formRes = await formValidate(formRef.value)
+    if (!formRes) return false
+    submitLoading.value = true
+    //发起请求
+    let res = {}
+    if (formModel.value.id) {
+        res = await mainApi.update(formModel.value)
+    } else {
+        res = await mainApi.add(formModel.value)
+    }
+    //处理结果
+    const { error, code, msg } = res
+    if (!error && code === 200) {
+        submitLoading.value = false
+        window?.$message?.success('操作成功')
+        dialogClose()
+        getTableData().then()
+    } else {
+        window?.$message?.error(msg ?? '操作失败')
+    }
+}
+
+//关闭弹窗
+const dialogClose = () => {
+    isDialogShow.value = false
+    submitLoading.value = false
+    formModel.value = {}
+}
+
+//升级APP
+const isUpdateDialog = ref(false)
+const updateDialogTitle = ref('')
+const appRowInfo = ref({})
+
+//显示升级弹窗
+const updateRowClick = (row) => {
+    updateDialogTitle.value = `升级 - ${row.name}`
+    appRowInfo.value = { ...row }
+    searchUpdateForm.value.current = 1
+    searchUpdateForm.value.versionId = row.id
+    nextTick(() => {
+        isUpdateDialog.value = true
+        getUpdateTableData()
+    })
+}
+
+//搜索表单
+const searchUpdateForm = ref({
+    current: 1, size: 30, total: 0,
+})
+
+//分页
+const pageUpdateChange = ({ current, size }) => {
+    searchUpdateForm.value.current = current
+    searchUpdateForm.value.size = size
+    getUpdateTableData()
+}
+
+//表格数据
+const tableUpdateColumn = ref([
+    { key: 'softwareType', name: '软件类型', width: 80 },
+    { key: 'versionNumber', name: '当前版本', width: 100 },
+    { key: 'fileType', name: '文件类型', width: 80 },
+    { key: 'constraintUpdate', name: '强制更新', width: 80 },
+    { key: 'updateDate', name: '更新时间' },
+    { key: 'action', name: '操作', width: 100, align: 'center' },
+])
+
+//获取表格数据
+const tableUpdateLoading = ref(false)
+const tableUpdateData = ref([{}])
+const getUpdateTableData = async () => {
+    tableUpdateData.value = []
+    tableUpdateLoading.value = true
+    const { error, code, data } = await mainApi.getDetailList({
+        ...searchUpdateForm.value,
+        total: null,
+    })
+    tableUpdateLoading.value = false
+    if (!error && code === 200) {
+        tableUpdateData.value = getArrValue(data['records'])
+        searchUpdateForm.value.total = data['total']
+    } else {
+        tableUpdateData.value = []
+        searchUpdateForm.value.total = 0
+    }
+}
+
+
+//新增/修改 弹窗
+const isUpdateFormDialog = ref(false)
+const updateFormTitle = ref('')
+
+//菜单表单
+const formUpdateRef = ref(null)
+const formUpdateModel = ref({})
+const formUpdateRules = {
+    versionNumber: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入当前版本号',
+    },
+    softwareType: {
+        required: true,
+        trigger: 'blur',
+        message: '请选择软件类型',
+    },
+    fileType: {
+        required: true,
+        trigger: 'blur',
+        message: '请选择文件类型',
+    },
+    updateContent: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入更新内容',
+    },
+    fileUrl: {
+        required: true,
+        trigger: 'blur',
+        message: '请上传文件',
+    },
+    constraintUpdate: {
+        required: true,
+        trigger: 'blur',
+        message: '请选择强制更新',
+    },
+}
+
+//新增
+const addUpdateClick = () => {
+    updateFormTitle.value = '新增 - ' + updateDialogTitle.value
+    formUpdateModel.value = {}
+    //显示表单弹窗
+    nextTick(() => {
+        isUpdateFormDialog.value = true
+    })
+}
+
+//修改
+const editUpdateRow = (row) => {
+    formUpdateModel.value = {}
+    updateFormTitle.value = '修改 - ' + updateDialogTitle.value
+    formUpdateModel.value = { ...row }
+    //显示表单弹窗
+    nextTick(() => {
+        isUpdateFormDialog.value = true
+    })
+}
+
+//删除
+const delUpdateRow = (row) => {
+    delMessage(async () => {
+        const { code, msg } = await mainApi.removeDetail(row.id)
+        if (code === 200) {
+            window.$message.success('删除成功')
+            updateDialogClose()
+            getUpdateTableData().then()
+        } else {
+            window.$message.error(msg ?? '删除失败')
+        }
+    })
+}
+
+//关闭升级弹窗
+const updateDialogClose = () => {
+    isUpdateDialog.value = false
+    tableUpdateLoading.value = false
+    tableUpdateData.value = []
+    getTableData()
+}
+
+//上传文件
+const uploadRef = ref(null)
+const uploadOptions = ref({
+    url: '/api/blade-resource/oss/endpoint/put-file2',
+    accept: '.apk,.wgt',
+    accept_tip: '只能上传apk或wgt文件',
+    headers: getHeader(),
+    multiple: false,
+})
+
+//上传文件
+const uploadFile = () => {
+    uploadRef.value?.selectFile()
+}
+
+// 文件上传成功的回调
+const uploadSuccess = ({ resData }) => {
+    formUpdateModel.value.fileUrl = resData
+    uploadRef.value?.setModalShow(false)
+}
+
+//提交APP升级表单
+const submitUpdateLoading = ref(false)
+const dialogUpdateSubmit = async () => {
+    const formRes = await formValidate(formUpdateRef.value)
+    if (!formRes) return false
+    submitUpdateLoading.value = true
+    //发起请求
+    let res = {}
+    if (formUpdateModel.value.id) {
+        res = await mainApi.updateDetail(formUpdateModel.value)
+    } else {
+        res = await mainApi.addDetail(formUpdateModel.value)
+    }
+    //处理结果
+    const { error, code, msg } = res
+    if (!error && code === 200) {
+        submitUpdateLoading.value = false
+        window?.$message?.success('操作成功')
+        updateFormDialogClose()
+        getUpdateTableData().then()
+    } else {
+        window?.$message?.error(msg ?? '操作失败')
+    }
+}
+
+//关闭升级表单弹窗
+const updateFormDialogClose = () => {
+    isUpdateFormDialog.value = false
+    submitUpdateLoading.value = false
+    formUpdateModel.value = {}
+}
+</script>
+
+<style lang="scss">
+.hc-app-update-dialog .el-dialog__headerbtn {
+    top: 0;
+    width: 48px;
+    height: 48px;
+}
+.hc-update-dialog-title {
+    position: absolute;
+    top: 15px;
+    left: 200px;
+    right: 200px;
+    text-align: center;
+}
+</style>

+ 170 - 0
src/views/system/user.vue

@@ -0,0 +1,170 @@
+<template>
+    <div>user</div>
+</template>
+
+<script setup>
+import { nextTick, onActivated, ref } from 'vue'
+import { arrToId, formValidate, getArrValue } from 'js-fast-way'
+import { delMessage, reloadPage } from '~uti/tools'
+import roleApi from '~api/system/role'
+import mainApi from '~api/system/user'
+
+//激活
+onActivated(() => {
+    getTableData()
+})
+
+//搜索表单
+const searchForm = ref({ current: 1, size: 30, total: 0 })
+
+//搜索
+const searchClick = () => {
+    searchForm.value.current = 1
+    getTableData()
+}
+
+//分页
+const pageChange = ({ current, size }) => {
+    searchForm.value.current = current
+    searchForm.value.size = size
+    getTableData()
+}
+
+//表格数据
+const tableRef = ref(null)
+const tableColumn = ref([
+    { key: 'paramName', name: '参数名称' },
+    { key: 'paramKey', name: '参数键名' },
+    { key: 'paramValue', name: '参数键值' },
+    { key: 'action', name: '操作', width: 100, align: 'center' },
+])
+
+//获取表格数据
+const tableLoading = ref(false)
+const tableData = ref([{}])
+const getTableData = async () => {
+    tableData.value = []
+    tableLoading.value = true
+    const { error, code, data } = await mainApi.page({
+        ...searchForm.value,
+        total: null,
+    })
+    tableLoading.value = false
+    if (!error && code === 200) {
+        tableData.value = getArrValue(data['records'])
+        searchForm.value.total = data['total']
+    } else {
+        tableData.value = []
+        searchForm.value.total = 0
+    }
+}
+
+//表格被选择
+const tableCheckKeys = ref([])
+const tableCheckChange = (rows) => {
+    tableCheckKeys.value = rows
+}
+
+//新增/修改 弹窗
+const isDialogShow = ref(false)
+const dialogTitle = ref('')
+
+//菜单表单
+const formRef = ref(null)
+const formModel = ref({})
+const formRules = {
+    paramName: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入参数名称',
+    },
+    paramKey: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入参数键名',
+    },
+    paramValue: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入参数键值',
+    },
+}
+
+//新增
+const addClick = () => {
+    dialogTitle.value = '新增参数'
+    formModel.value = {}
+    //显示表单弹窗
+    nextTick(() => {
+        isDialogShow.value = true
+    })
+}
+
+//修改菜单
+const editRowClick = (row) => {
+    formModel.value = {}
+    dialogTitle.value = '修改参数'
+    formModel.value = { ...row }
+    //显示表单弹窗
+    nextTick(() => {
+        isDialogShow.value = true
+    })
+}
+
+//删除菜单
+const delRowClick = (row) => {
+    delMessage(async () => {
+        const { code, msg } = await mainApi.del(row.id)
+        if (code === 200) {
+            window.$message.success('删除成功')
+            reloadPage()
+        } else {
+            window.$message.error(msg ?? '删除失败')
+        }
+    })
+}
+
+//批量删除菜单
+const delClick = () => {
+    const rows = tableCheckKeys.value
+    if (rows.length <= 0) {
+        window.$message.warning('请选择要删除的菜单')
+        return false
+    }
+    //确认删除菜单
+    delMessage(async () => {
+        const ids = arrToId(rows)
+        const { code, msg } = await mainApi.del(ids)
+        if (code === 200) {
+            window.$message.success('删除成功')
+            reloadPage()
+        } else {
+            window.$message.error(msg ?? '删除失败')
+        }
+    })
+}
+
+//提交表单
+const submitLoading = ref(false)
+const dialogSubmit = async () => {
+    const formRes = await formValidate(formRef.value)
+    if (!formRes) return false
+    submitLoading.value = true
+    //发起请求
+    const { error, code, msg } = await mainApi.submit(formModel.value)
+    if (!error && code === 200) {
+        submitLoading.value = false
+        window?.$message?.success('操作成功')
+        reloadPage()
+    } else {
+        window?.$message?.error(msg ?? '操作失败')
+    }
+}
+
+//关闭弹窗
+const dialogClose = () => {
+    isDialogShow.value = false
+    submitLoading.value = false
+    formModel.value = {}
+}
+</script>