自存19-48

19-菜单管理添加弹窗显示

javascript 复制代码
<template>
    <button @click="dialogFormVisable = true ">打开</button>
    <el-dialog
        v-model="dialogFormVisable"
        :before-close="beforeClose"
        title="添加权限"
        width="500"
    >
        <el-form
            ref="formRef"
            label-width="100px"
            label-position="left"
            :model="form"
        >
            <el-form-item label="名称" prop="name">
                <el-input v-model="form.name" placeholder="请填写权限名称"/>
            </el-form-item>
             <el-form-item label="权限" prop="permissions">
                <el-tree
                    ref="treeRef"
                    style="max-width: 600px;"
                    :data="permissionData"
                    node-key="id"
                    show-checkbox
                    :default-checked-keys="defaultKeys"
                />
            </el-form-item>
        </el-form>
    </el-dialog>
</template>
<script setup>
    import { ref , reactive , onMounted } from 'vue'
    import { userGetMenu } from '../../../api'
    
    onMounted(() => {
        //菜单数据
        userGetMenu().then(({ data })=>{
            console.log(data)
            permissionData.value = data.data
        })
    })
    //form的数据
    const form = reactive({
        name:'',
        permissions:''
    })
    //树形菜单权限数据
    const permissionData = ref([])
    //弹窗的显示隐藏
    const dialogFormVisable = ref(false)
    //关闭弹窗的回调
    const beforeClose = () => {
        dialogFormVisable.value = false
    }
    //选中权限
    const defaultKeys = [4,5]
    const treeRef = ref()
</script>
<style lang="less" scoped>
</style>
javascript 复制代码
import request from '../utils/request'
//发送验证码
export const getCode = (data) => {
    return request.post('/get/code',data)
}

//注册用户
export const userAuthentication = (data) =>{
    return request.post('/user/authentication',data)
}

//登录
export const login = (data) =>{
    return request.post('/login',data)
} 

//权限管理列表
export const authAdmin = (params) => {
    return request.get('/auth/admin', { params })
}

//菜单权限数据
export const userGetMenu = (params) => {
    return request.get('/user/getmenu', { params })
}

新添加的部分:

20-菜单管理添加接口联调

javascript 复制代码
<template>
    <button @click="dialogFormVisable = true ">打开</button>
    <el-dialog
        v-model="dialogFormVisable"
        :before-close="beforeClose"
        title="添加权限"
        width="500"
    >
        <el-form
            ref="formRef"
            label-width="100px"
            label-position="left"
            :model="form"
            :rules="rules"
        >
             <el-form-item v-show="false" prop="id">
                <el-input v-model="form.id"/>
             </el-form-item>
            <el-form-item label="名称" prop="name">
                <el-input v-model="form.name" placeholder="请填写权限名称"/>
            </el-form-item>
             <el-form-item label="权限" prop="permissions">
                <el-tree
                    ref="treeRef"
                    style="max-width: 600px;"
                    :data="permissionData"
                    node-key="id"
                    show-checkbox
                    :default-checked-keys="defaultKeys"
                    :default-expanded-keys="[2]"
                />
            </el-form-item>
        </el-form>
        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary"  @click="confirm(formRef)">确认</el-button>
            </div>
        </template>
    </el-dialog>
</template>
<script setup>
    import { ref, reactive, onMounted } from 'vue'
    import { userGetMenu, userSetMenu, menuList} from '../../../api'


    onMounted(() => {
        //菜单数据
        userGetMenu().then(({ data })=>{
            console.log(data)
            permissionData.value = data.data
        })
        getListData()
    })
    const paginationData = reactive({
        pageNum: 1,
        pageSize: 10,
    })

    //请求列表数据
    const getListData = () =>{
        menuList(paginationData).then(( data ) => {

        })
    }

    const formRef = ref()

    //form的数据
    const form = reactive({
        id:'',
        name:'',
        permissions:''
    })
    //树形菜单权限数据
    const permissionData = ref([])
    //弹窗的显示隐藏
    const dialogFormVisable = ref(false)
    //关闭弹窗的回调
    const beforeClose = () => {
        dialogFormVisable.value = false
    }
    //选中权限
    const defaultKeys = [4,5]
    const treeRef = ref()

    const rules = reactive({
        name:[{ required: true, trigger:'blur',message:'请输入权限名称' }]
    })
    //表单提交
    const confirm = async(formEl) => {
        if (!formEl) return
        await formEl.validate((valid,fields) => {
            if(valid){
                //获取到选择的checkbox数据
                const permissions = JSON.stringify( treeRef.value.getCheckedKeys())
                userSetMenu({ name: form.name, permissions, id: form.id}).then(({ data }) => {
                    console.log(data)
                })
            }else{
                console.log('error submit!' , fields )
            }
        })
    }
</script>
<style lang="less" scoped>
</style>
javascript 复制代码
import request from '../utils/request'
//发送验证码
export const getCode = (data) => {
    return request.post('/get/code',data)
}

//注册用户
export const userAuthentication = (data) =>{
    return request.post('/user/authentication',data)
}

//登录
export const login = (data) =>{
    return request.post('/login',data)
} 

//权限管理列表
export const authAdmin = (params) => {
    return request.get('/auth/admin', { params })
}

//菜单权限数据
export const userGetMenu = (params) => {
    return request.get('/user/getmenu', { params })
}

//菜单权限修改
export const userSetMenu = (data) => {
     return request.post('/user/setmenu',data)
}

//菜单权限列表
export const menuList = (params) => {
    return request.get('/menu/list', { params })
}

21-菜单管理列表和编辑逻辑

javascript 复制代码
<template>
    <button @click="open(null)">打开 </button>
    <el-table :data="tableData.list" style="width: 100%">
        <el-table-column prop="id" label="id" />
        <el-table-column prop="name" label="昵称" />
        <el-table-column prop="permissionName" label="菜单权限" width="500px"/>
        <el-table-column label="操作">
            <template #default="scope">
               <el-button type="primary" @click="open(scope.row)">编辑</el-button>
            </template>
        </el-table-column>
    </el-table>
    <el-dialog
        v-model="dialogFormVisable"
        :before-close="beforeClose"
        title="添加权限"
        width="500"
    >
        <el-form
            ref="formRef"
            label-width="100px"
            label-position="left"
            :model="form"
            :rules="rules"
        >
             <el-form-item v-show="false" prop="id">
                <el-input v-model="form.id"/>
             </el-form-item>
            <el-form-item label="名称" prop="name">
                <el-input v-model="form.name" placeholder="请填写权限名称"/>
            </el-form-item>
             <el-form-item label="权限" prop="permissions">
                <el-tree
                    ref="treeRef"
                    style="max-width: 600px;"
                    :data="permissionData"
                    node-key="id"
                    show-checkbox
                    :default-checked-keys="defaultKeys"
                    :default-expanded-keys="[2]"
                />
            </el-form-item>
        </el-form>
        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary"  @click="confirm(formRef)">确认</el-button>
            </div>
        </template>
    </el-dialog>
</template>
<script setup>
    import { ref, reactive, onMounted, nextTick } from 'vue'
    import { userGetMenu, userSetMenu, menuList} from '../../../api'


    onMounted(() => {
        //菜单数据
        userGetMenu().then(({ data })=>{
            console.log(data)
            permissionData.value = data.data
        })
        getListData()
    })

    //列表数据
    const tableData = reactive({
        list: [],
        total: 0
    })
    //打开弹窗
    const open = (rowData = {}) =>{
        dialogFormVisable.value = true
        // 弹窗打开form生成是异步的
        nextTick(() => {
            if(rowData){
                Object.assign(form, { id:rowData.id , name: rowData.name  })
                treeRef.value.setCheckedKeys(rowData.permission)
            }
        })
    }

    const paginationData = reactive({
        pageNum: 1,
        pageSize: 10,
    })

    //请求列表数据
    const getListData = () =>{
        menuList(paginationData).then(({ data }) => {
            const { list, total } = data.data
            tableData.list = list
            tableData.total = total
        })
    }

    const formRef = ref()

    //form的数据
    const form = reactive({
        id:'',
        name:'',
        permissions:''
    })
    //树形菜单权限数据
    const permissionData = ref([])
    //弹窗的显示隐藏
    const dialogFormVisable = ref(false)
    //关闭弹窗的回调
    const beforeClose = () => {
        dialogFormVisable.value = false
        //重置表单
        formRef.value.resetFields()
        //tree选择重置
        treeRef.value.setCheckedKeys(defaultKeys)
    }
    //选中权限
    const defaultKeys = [4,5]
    const treeRef = ref()

    const rules = reactive({
        name:[{ required: true, trigger:'blur',message:'请输入权限名称' }]
    })
    //表单提交
    const confirm = async(formEl) => {
        if (!formEl) return
        await formEl.validate((valid,fields) => {
            if(valid){
                //获取到选择的checkbox数据
                const permissions = JSON.stringify( treeRef.value.getCheckedKeys())
                userSetMenu({ name: form.name, permissions, id: form.id}).then(({ data }) => {
                    console.log(data)
                })
            }else{
                console.log('error submit!' , fields )
            }
        })
    }
</script>
<style lang="less" scoped>
</style>

22-菜单管理剩余问题处理

javascript 复制代码
<template>
    <panel-head/>
    <div class="btns">
        <el-button  :icon="Plus" type="primary" @click="open(null)" size="small">新增</el-button>
    </div>
    <el-table :data="tableData.list" style="width: 100%">
        <el-table-column prop="id" label="id" />
        <el-table-column prop="name" label="昵称" />
        <el-table-column prop="permissionName" label="菜单权限" width="500px"/>
        <el-table-column label="操作">
            <template #default="scope">
               <el-button type="primary" @click="open(scope.row)">编辑</el-button>
            </template>
        </el-table-column>
    </el-table>
    <div class="pagination-info">
        <el-pagination
            v-model:current-page="paginationData.pageNum"
            :page-size="paginationData.pageSize"
            :background="false"
            size="small"
            layout="total, prev, pager, next"
            :total="tableData.total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            />
    </div>
    <el-dialog
        v-model="dialogFormVisable"
        :before-close="beforeClose"
        title="添加权限"
        width="500"
    >
        <el-form
            ref="formRef"
            label-width="100px"
            label-position="left"
            :model="form"
            :rules="rules"
        >
             <el-form-item v-show="false" prop="id">
                <el-input v-model="form.id"/>
             </el-form-item>
            <el-form-item label="名称" prop="name">
                <el-input v-model="form.name" placeholder="请填写权限名称"/>
            </el-form-item>
             <el-form-item label="权限" prop="permissions">
                <el-tree
                    ref="treeRef"
                    style="max-width: 600px;"
                    :data="permissionData"
                    node-key="id"
                    show-checkbox
                    :default-checked-keys="defaultKeys"
                    :default-expanded-keys="[2]"
                />
            </el-form-item>
        </el-form>
        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary"  @click="confirm(formRef)">确认</el-button>
            </div>
        </template>
    </el-dialog>
</template>
<script setup>
    import { ref, reactive, onMounted, nextTick } from 'vue'
    import { userGetMenu, userSetMenu, menuList} from '../../../api'
    import { Plus } from '@element-plus/icons-vue'


    onMounted(() => {
        //菜单数据
        userGetMenu().then(({ data })=>{
            console.log(data)
            permissionData.value = data.data
        })
        getListData()
    })

    //列表数据
    const tableData = reactive({
        list: [],
        total: 0
    })
    //打开弹窗
    const open = (rowData = {}) =>{
        dialogFormVisable.value = true
        // 弹窗打开form生成是异步的
        nextTick(() => {
            if(rowData){
                Object.assign(form, { id:rowData.id , name: rowData.name  })
                treeRef.value.setCheckedKeys(rowData.permission)
            }
        })
    }

    const paginationData = reactive({
        pageNum: 1,
        pageSize: 10,
    })

    const handleSizeChange = (val) => {
        paginationData.pageSize = val
        getListData()
    }
    const handleCurrentChange = (val) => {
        paginationData.pageNum = val
        getListData()
    }
    //请求列表数据
    const getListData = () =>{
        menuList(paginationData).then(({ data }) => {
            const { list, total } = data.data
            tableData.list = list
            tableData.total = total
        })
    }

    const formRef = ref()

    //form的数据
    const form = reactive({
        id:'',
        name:'',
        permissions:''
    })
    //树形菜单权限数据
    const permissionData = ref([])
    //弹窗的显示隐藏
    const dialogFormVisable = ref(false)
    //关闭弹窗的回调
    const beforeClose = () => {
        dialogFormVisable.value = false
        //重置表单
        formRef.value.resetFields()
        //tree选择重置
        treeRef.value.setCheckedKeys(defaultKeys)
    }
    //选中权限
    const defaultKeys = [4,5]
    const treeRef = ref()

    const rules = reactive({
        name:[{ required: true, trigger:'blur',message:'请输入权限名称' }]
    })
    //表单提交
    const confirm = async(formEl) => {
        if (!formEl) return
        await formEl.validate((valid,fields) => {
            if(valid){
                //获取到选择的checkbox数据
                const permissions = JSON.stringify( treeRef.value.getCheckedKeys())
                userSetMenu({ name: form.name, permissions, id: form.id}).then(({ data }) => {
                    beforeClose()
                    getListData()
                })
            }else{
                console.log('error submit!' , fields )
            }
        })
    }
</script>
<style lang="less" scoped>
.btns{
    padding: 10px 0 10px 10px ;
    background-color: #fff;
}
</style>
javascript 复制代码
<template>
    <div class="panel-heading">
        <div class="panel-lead">
            <div class="title">菜单管理</div>
            <p class="description">菜单规则通常对应一个控制器的方法,同时菜单栏数据也从规则中获取</p>
        </div>
    </div>
</template>

<script setup>
</script>

<style lang="less" scoped>
.panel-heading {
    padding: 15px;
    background: #e8edf0;
    border-color: #e8edf0;
    position: relative;
    .panel-lead {
      font-size: 14px;
      .title {
        font-weight: bold;
        font-style: normal;
      }
      .description {
        margin-top: 5px;
      }
    }
  }
</style>
javascript 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import store from './store'
import PanelHead from './components/panelHead.vue'


router.beforeEach((to,from) =>{
  const token = localStorage.getItem('pz_token')
  //非登录页面token不存在
  if (!token && to.path !== '/login') {
    return '/login'
  }else if (token && to.path === '/login'){
    return '/'
  }else{
    return true
  }
})

// 如果您正在使用CDN引入,请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app.component('PanelHead',PanelHead)
//路由挂载
app.use(router)
//store挂载
app.use(store)
app.mount('#app')

23-账号管理列表

24-账号管理编辑分页功能完成

javascript 复制代码
<template>
    <panel-head/>
    <el-table :data="tableData.list" style="width: 100%">
        <el-table-column prop="id" label="id" />
        <el-table-column prop="name" label="昵称" />
        <el-table-column prop="permissions_id" label="所属组别" >
            <template #default="scope">
               {{ permissionName(scope.row.permissions_id) }}
            </template>
        </el-table-column>
         <el-table-column prop="mobile" label="手机号" />

         <el-table-column prop="active" label="状态" >
             <template #default="scope">
                <el-tag  :type="scope.row.active ? 'success' : 'danger' ">{{ scope.row.active ? '正常' : '失效'}}</el-tag>
            </template>
        </el-table-column>

        <el-table-column  label="创建时间" >
             <template #default="scope">
                <div class="flex-box">
                    <el-icon><Clock /></el-icon>
                    <span style="margin-left : 10px">{{ scope.row.create_time}}</span>
                </div>
            </template>
        </el-table-column>

        <el-table-column label="操作">
            <template #default="scope">
               <el-button type="primary" @click="open(scope.row)">编辑</el-button>
            </template>
        </el-table-column>
    </el-table>

    <div class="pagination-info">
        <el-pagination
            v-model:current-page="paginationData.pageNum"
            :page-size="paginationData.pageSize"
            :background="false"
            size="small"
            layout="total, prev, pager, next"
            :total="tableData.total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            />
    </div>
    <el-dialog
        v-model="dialogFormVisable"
        :before-close="beforeClose"
        title="添加权限"
        width="500"
    >
        <el-form
                ref="formRef"
                label-width="100px"
                label-position="left"
                :model="form"
                :rules="rules"
            >
                <el-form-item label="手机号" prop="mobile">
                    <el-input v-model="form.mobile" disabled/>
                </el-form-item>
                <el-form-item label="昵称" prop="name">
                    <el-input v-model="form.name" />
                </el-form-item>
                <el-form-item label="菜单权限" prop="permissions_id">
                    <el-select
                        v-model="form.permissions_id"
                        placeholder="请选择菜单权限"
                        style="width: 240px"
                    >
                        <el-option
                            v-for="item in options" 
                            :key="item.id"
                            :label="item.name"
                            :value="item.id"       
                            />
                    </el-select>
                </el-form-item>
        </el-form>
        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary"  @click="confirm(formRef)">确认</el-button>
            </div>
        </template>
    </el-dialog>
</template>
 
<script setup>
import { authAdmin, menuSelectList, updateUser } from'../../../api'
import { ref, reactive, onMounted } from 'vue'
import dayjs from 'dayjs'

const paginationData = reactive({
    pageNum: 1,
    pageSize: 10,
})

//列表数据
const tableData = reactive({
    list: [],
    total: 0
})

onMounted(() => {
    getListData()
    menuSelectList().then(({ data }) => {
        options.value = data.data
    })
})
//请求列表
const getListData = () => {
    authAdmin(paginationData).then(({data}) => {
        console.log(data, 'authAdmin')
        const { list, total } = data.data
        list.forEach(item => {
            item.create_time = dayjs(item.create_time).format('YYYY-MM-DD')
        })
        tableData.list = list
        tableData.total = total
    })
}

const handleSizeChange = (val) => {
    paginationData.pageSize = val
    getListData()
}
const handleCurrentChange = (val) => {
    paginationData.pageNum = val
    getListData()
}

//弹窗
const dialogFormVisable = ref(false)
const beforeClose = () => {

}

const rules = reactive({
    name:[{ required: true, trigger: 'blur' , message:'请填写昵称' }],
    permissions_id:[{ required: true, trigger: 'blur' , message:'请选择菜单权限' }],

})

//编辑表单
const formRef = ref()
const form = reactive({
    name:'',
    permissions_id:'',

})
//表单提交
const confirm = async (formEl) => {
    if (!formEl) return
    await formEl.validate((valid,fields) => {
        if(valid){
            const { name, permissions_id } = form
            updateUser({ name, permissions_id}).then(({ data }) => {
                if( data.code === 10000 ){
                    dialogFormVisable.value = false
                    getListData()
                }
            })
        }else{
            console.log('error submit!' , fields )
        }
    })
}

const options = ref([])
//根据权限id匹配权限名称
const permissionName = (id) => {
    const data = options.value.find(el => el.id === id)
    return data ? data.name : '超级管理员'
}
const open = ( rowData ) => {
    dialogFormVisable.value = true
    Object.assign(form, { mobile:rowData.mobile, name: rowData.name, permissions_id:rowData.permissions_id })
}
</script>

<style lang="less" scoped>
.flex-box{
    display: flex;
    align-items: center;
}
</style>
javascript 复制代码
import request from '../utils/request'
//发送验证码
export const getCode = (data) => {
    return request.post('/get/code',data)
}

//注册用户
export const userAuthentication = (data) =>{
    return request.post('/user/authentication',data)
}

//登录
export const login = (data) =>{
    return request.post('/login',data)
} 

//权限管理列表
export const authAdmin = (params) => {
    return request.get('/auth/admin', { params })
}

//菜单权限数据
export const userGetMenu = () => {
    return request.get('/user/getmenu')
}

//菜单权限修改
export const userSetMenu = (data) => {
     return request.post('/user/setmenu',data)
}

//菜单权限列表
export const menuList = (params) => {
    return request.get('/menu/list', { params })
}

//权限下拉列表
export const menuSelectList = () =>{
    return request.get('/menu/selectlist',)
}

//用户数据修改
export const updateUser = (data) => {
     return request.post('/update/user',data)
}

25-用户权限接口联调和动态路由数据组装

javascript 复制代码
<template>
    <div class="header-container">
        <div class="header-left flex-box" >
            <el-icon class="icon" size="20" @click="store.commit('collapseMenu')"><Fold /></el-icon>
            <ul class="flex-box">
                <li 
                    v-for="(item,index) in selectMenu" 
                    :key="item.path"
                    :class="{selected: route.path === item.path}"
                    class="tab flex-box">
                    <el-icon  size="12" ><component :is="item.icon" /></el-icon>
                    <router-link class="text flex-box" :to="{ path:item.path }">
                        {{item.name}}
                    </router-link>
                    <el-icon  size="12" class="close" @click="closeTab(item,index)"><Close /></el-icon>
                </li>
            </ul>
        </div>
        <div class="header-right">
            <el-dropdown @command="handleClick">
               <div class="el-dropdown-link flex-box">
                    <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"/>
                    <p class="user-name">admin</p>
               </div>
                <template #dropdown>
                    <el-dropdown-item command="cancel">退出</el-dropdown-item>
                </template>
            </el-dropdown>
        </div>
    </div>
</template>

<script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'
import { useRoute,useRouter } from 'vue-router'
//拿到store的实例
const store = useStore()
// 当前路由对象
const route = useRoute()
const router = useRouter()
const selectMenu = computed( ()=> store.state.menu.selectMenu)
//点击关闭tag
const closeTab = (item,index) =>{
    store.commit('closeMenu',item)
    //删除的非当前页tag
    if(route.path !== item.path){
        return
    }
    const selectMenuDate = selectMenu.value
    //删除的最后一项
    if( index === selectMenuData.length){
        //如果tag只有一个元素
        if(!selectMenuData.length) {
            router.push('/')
        }else{
            router.push({
                path:selectMenuData[index -1].path
            })
        }
    }else(//如果删除的是中间位置tag
        router.push({
            path:selectMenuData[index].path
        })
    )
}

const handleClick = (command) => {
    if(command === "cancel" ){
        localStorage.removeItem('pz_token')
        localStorage.removeItem('pz_userInfo')

        window.location.href = window.location.origin
    }
}
</script>

<style lang="less" scoped>
.flex-box{
    display: flex;
    align-items: center;
    height: 100%;
}
.header-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 100%;
    background-color: #fff;
    padding-right: 25px;
    .header-left{
        height: 100%;
        .icon{
            width: 45px;
            height: 100%;
        }
        .icon:hover{
            background-color: #f5f5f5;
            cursor: pointer;
        }
        .tab{
            padding: 0 10px;
            height: 100%;
            .text{
                margin: 0 5px;
            }
            .close{
                visibility: hidden;
            }
            &.selected{
                a{
                    color: #409eff;
                }
                i{
                    color: #409eff;
                }
                background-color: #f5f5f5;
            }
        }
        .tab:hover{
            background-color: #f5f5f5;
            .close{
                visibility: inherit;
                cursor: pointer;
                color: #000;
            }
        }
    }
    .header-right{
        .user-name{
            margin-left: 10px;
        }
    }
    a{ 
        height: 100%;
        color: #333;
        font-size: 15px;
    }
}
</style>
javascript 复制代码
<template>
        <el-row class="login-container" justify="center" :align="'middle'">
            <el-card style="max-width: 480px">
                <template #header>
                    <div class="card-header">
                        <img :src="imgUrl" alt="">
                    </div>
                </template>
                <div class="jump-link">
                    <el-link type="primary" @click="handleChange">{{ formType ? '返回登录' : '注册账号' }}</el-link>
                </div>
                 <el-form 
                 ref="loginFromRef"
                 :model="loginForm" 
                 style="max-width: 600px"
                 class="demo-ruleForm"
                 :rules="rules"
                 >
                    <el-form-item prop="userName">
                        <el-input v-model="loginForm.userName" :prefix-icon="UserFilled" placeholder="手机号"></el-input>
                    </el-form-item>
                    <el-form-item prop="passWord">
                        <el-input v-model="loginForm.passWord" type="password" :prefix-icon="Lock" placeholder="密码"></el-input>
                    </el-form-item>
                    <el-form-item v-if="formType" prop="validCode">
                        <el-input v-model="loginForm.validCode" :prefix-icon="Lock" placeholder="验证码">
                            <template #append>
                                <span @click="countdownChange">{{ countdown.validText }}</span>
                            </template>
                        </el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" :style="{width:'100%'}" @click="submitForm(loginFromRef)">
                            {{ formType ? '注册账号' : '登录'}}
                        </el-button>
                    </el-form-item>
                 </el-form>
            </el-card>
        </el-row>
</template>

<script setup>
import { ref, reactive, computed } from 'vue'
import { getCode, userAuthentication, login, menuPermissions  } from '../../api'
import { UserFilled, Lock } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router' 
import { useStore } from 'vuex'

const imgUrl = new URL('../../../public/login-head.png', import.meta.url).href

//表单数据
const loginForm = reactive({
    userName: '',
    passWord: '',
    validCode: '',
})
//切换表单(0登录 1注册)
const formType = ref(0)
//点击切换登录和注册
const handleChange = () => {
    formType.value = formType.value ? 0 : 1
}
//账号校验规则
const validateUser = (rule,value,callback) =>{
    //不能为空
    if(value === ''){
        callback(new Error('请输入账号'))
    }else{
        const phoneReg =  /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
        phoneReg.test(value) ? callback() : callback(Error('手机号格式不对,请输入正确手机号'))
    }
}
//密码校验
const validatePass = (rule,value,callback) =>{
    //不能为空
    if(value === ''){
        calllback(new Error('请输入密码'))
    }else{
        const reg = /^[a-zA-Z0-9_-]{4,16}$/
        reg.test(value) ? callback() : callback(Error('密码格式不对,需要4-16位字符,请确认格式'))
    }
}
//表单校验
const rules = reactive({
    userName : [{ validator: validateUser, trigger:'blur'}],
    passWord : [{ validator: validatePass, trigger:'blur'}]
})
//发送短信
const countdown = reactive({
    validText:'获取验证码',
    time:60
})
let flag = false
const countdownChange = () =>{
    //如果已发送不处理
    if(flag) return
    //判断手机号是否正确
    const phoneReg =  /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
    if (!loginForm.userName || !phoneReg.test(loginForm.userName)){
        return  ElMessage({
                message: '请检查手机号是否正确',
                type: 'warning',
        })
    }
    //倒计时
    const time = setInterval(()=>{
        if( countdown.time <= 0){
            countdown.time = 60
            countdown.validText = `获取验证码`
            flag = false
            clearInterval(time)
        }else{
            countdown.time -= 1
            countdown.validText = `剩余${countdown.time}s`
        }
    },1000)
    flag = true
    getCode({ tel: loginForm.userName}).then(({ data }) => {
        if(data.code === 10000){
            ElMessage.success('发送成功')
        }
    })
}

const router = useRouter()
const loginFromRef = ref()
const store = useStore()

const routerList =  computed(() => store.state.menu.routerList)
//表单提交
const submitForm = async (formEl) => { 
    if (!formEl) return
    //手动触发校验
    await formEl.validate((valid, fields) => {
        if (valid) {
            //注册页面
            if(formType.value){
                userAuthentication(loginForm).then(({ data }) => {
                    if (data.code === 10000) {
                        ElMessage.success('注册成功,请登录')
                        formType.value = 0
                    }
                })
            }else{
                //登录页面
                login(loginForm).then(({data}) => {
                     if (data.code === 10000) {
                        ElMessage.success('登录成功!')
                        console.log(data)
                        //将token和用户信息缓存到浏览器
                        localStorage.setItem('pz_token', data.data.token)
                        localStorage.setItem('pz_userInfo', JSON.stringify(data.data.userInfo))
                        menuPermissions().then(({ data }) => {
                            store.commit('dynamicMenu', data.data)
                            console.log(routerList, 'routerList')
                            // router.push('/')
                        })
                        
                    }
                })
            }
        } else {
        console.log('error submit!', fields)
        }
    })
}
</script>

<style lang="less" scoped>
:deep(.el-card__header) {
    padding: 0
}
  .login-container {
    height: 100%;
    .card-header{
      background-color: #899fe1;
      img {
        width: 430px;
      }
    }
    .jump-link {
      text-align: right;
      margin-bottom: 10px;
    }
  }
</style>
javascript 复制代码
const state = {
    isCollapse : false,
    selectMenu: [],
    routerList: []
}
const mutations = {
    collapseMenu(state){
        state.isCollapse = !state.isCollapse
    },
    addMenu(state,payload) {
        //对数据进行去重
        if(state.selectMenu.findIndex(item => item.path === payload.path) === -1){
            state.selectMenu.push(payload)

        }
    },
    closeMenu(state,payload){
        //找到点击数据的索引
        const index = state.selectMenu.findIndex(val => val.name === payload.name )
        //通过索引删除数组指定元素
        state.selectMenu.splice(index,1)
    },
    dynamicMenu( state, payload ) {
        //通过glob导入文件
        const modules =  import.meta.glob('../views/**/**/*.vue')
         console.log(modules)
         function routerSet(router){
            router.forEach(route => {
                //判断没有子菜单,拼接路由数据
                if ( !route.children ){
                    const url = `../views${route.meta.path}/index.vue`
                    //拿到获取的vue组件
                    route.component =  modules[url]
                }else{
                    routerSet(route.children)
                }
            })
         }
         routerSet(payload)
         //拿到完整的路由数据
         state.routerList =  payload
    }

}

export default{
    state,
    mutations
}

26-动态路由添加和vuex持久化实现

27-菜单高亮显示和用户信息显示问题解决

28-陪护管理新增陪护师弹窗

29-陪护新增表单校验和接口联调

30-陪护列表显示和接口联调

31-陪护师编辑和批量删除接口联调

32-【C端】项目创建引入router和vant UI

33-【C端】tabbar引入和layout组件实现

34-【C端】登录页面显示效果实现

35-【C端】axios二次封装和登录接口联调

36-【C端】首页页面效果实现

37-【C端】订单详情自定义头部和状态显示

38-【C端】订单详情选择医院功能

39-【C端】订单详情选择就诊时间功能

40-【C端】订单详情剩余表单显示

41-【C端】订单下单和支付功能实现

42-【C端】订单列表显示效果实现

43-【C端】订单详情显示效果(上)

44-【C端】订单详情显示效果(下)

45-【C端】我的页面显示效果

46-【C端】订单列表页面实现效果

47-【C端】订单列表服务状态扭转和问题解决

48-【完结】项目总结和回顾

相关推荐
Never_Satisfied4 小时前
在JavaScript / HTML中,`onclick`事件触发多个函数
开发语言·javascript·html
Misnice7 小时前
React渲染超大的字符串
前端·javascript·react.js
二十雨辰15 小时前
vite如何处理项目中的资源
开发语言·javascript
洛可可白16 小时前
把 Vue2 项目“黑盒”嵌进 Vue3:qiankun 微前端实战笔记
前端·vue.js·笔记
四月_h17 小时前
vue2动态实现多Y轴echarts图表,及节点点击事件
前端·javascript·vue.js·echarts
文心快码BaiduComate17 小时前
用Zulu轻松搭建国庆旅行4行诗网站
前端·javascript·后端
正义的大古18 小时前
OpenLayers地图交互 -- 章节十八:拖拽旋转和缩放交互详解
javascript·vue.js·openlayers
疯狂踩坑人20 小时前
【万字长文】让面试没有难撕的JS基础题
javascript·面试
极客小俊20 小时前
【浅谈javascript禁术】 eval函数暗藏玄机?
javascript