feat: 添加用户下拉框

master
luoer 2023-09-27 17:40:39 +08:00
parent 9ce121af3f
commit 2f49f3814c
10 changed files with 196 additions and 77 deletions

View File

@ -6,21 +6,33 @@ on:
- master
paths-ignore:
- .gitignore
- README.md
- .eslintrc.json
- .prettierrc.json
- .vscode/**
- README.md
tags:
- v*
env:
docker_host: ${{ secrets.DOCKER_REGISTRY }}
docker_user: ${{ secrets.DOCKER_USERNAME }}
docker_pass: ${{ secrets.DOCKER_PASSWORD }}
docker_name: ${{ secrets.DOCKER_REGISTRY }}/${{ gitea.repository }}
deploy_host: ${{ secrets.DEPLOY_HOSTNAME }}
# docker 镜像仓库地址,例如: git.dev.juetan.cn
docker_host: ${{ secrets.DOCKER_HOST }}
# docker 镜像仓库用户名
docker_user: ${{ secrets.DOCKER_USER }}
# docker 镜像仓库密码
docker_pass: ${{ secrets.DOCKER_PASS }}
# docker 镜像仓库名称,例如: git.dev.juetan.cn/xxx/xxx
docker_name: ${{ secrets.DOCKER_HOST }}/${{ gitea.repository }}
# 部署服务器IP或域名, 例如: 1.1.1.1
deploy_host: ${{ secrets.DEPLOY_HOST }}
# 部署服务器端口, 例如: 22
deploy_port: ${{ secrets.DEPLOY_PORT }}
deploy_user: ${{ secrets.DEPLOY_USERNAME }}
deploy_pass: ${{ secrets.DEPLOY_PASSWORD }}
deploy_name: demo_web
# 部署服务器用户名, 例如: root
deploy_user: ${{ secrets.DEPLOY_USER }}
# 部署服务器密码, 例如: 123456
deploy_pass: ${{ secrets.DEPLOY_PASS }}
# 要更新的 docker 服务名称, 例如: demo_web
deploy_name: ${{ secrets.DEPLOY_NAME }}
jobs:
build:
@ -74,4 +86,4 @@ jobs:
password: ${{ env.deploy_pass }}
script: |
docker service ls | grep -q ${{ env.deploy_name }} || exit 0
docker service update --image ${{ env.docker_name }}:latest ${{ env.deploy_name }}
docker service update --image ${{ env.docker_name }}:latest ${{ env.deploy_name }}

5
Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM nginx:alpine
COPY ./dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@ -0,0 +1,58 @@
<template>
<a-dropdown position="br">
<span class="inline-flex items-center cursor-pointer rounded hover:bg-gray-100 px-2 py-1.5">
<a-avatar :size="20">
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
</a-avatar>
<span class="mx-2">
{{ userStore.nickname }}
</span>
<i class="icon-park-outline-down"></i>
</span>
<template #content>
<a-doption>
<div class="w-[160px] leading-4 my-1">
{{ userStore.nickname }}
<div class="text-xs text-gray-500">@{{ userStore.username }}</div>
</div>
</a-doption>
<a-divider :margin="4"></a-divider>
<a-doption>
<template #icon>
<i class="icon-park-outline-lock"></i>
</template>
修改密码
</a-doption>
<a-doption @click="router.push('/my')">
<template #icon>
<i class="icon-park-outline-config"></i>
</template>
个人设置
</a-doption>
<a-divider :margin="4"></a-divider>
<a-doption @click="logout">
<template #icon>
<i class="icon-park-outline-logout"></i>
</template>
退出
</a-doption>
</template>
</a-dropdown>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store";
import { Message } from "@arco-design/web-vue";
const userStore = useUserStore();
const route = useRoute();
const router = useRouter();
const logout = async () => {
userStore.clearUser();
Message.success("提示:已退出登陆!");
router.push({ path: "/login", query: { redirect: route.path } });
};
</script>
<style scoped></style>

View File

@ -1,10 +1,10 @@
<template>
<a-layout class="layout">
<a-layout-header
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
>
<div class="h-13 flex items-center border-b border-slate-200 dark:border-slate-800">
<router-link to="/" class="ml-1 flex items-center gap-2 text-slate-700">
<router-link to="/" class="px-2 py-1 rounded flex items-center gap-2 text-slate-700 hover:bg-slate-100">
<img src="/favicon.ico" alt="" width="22" height="22" class="" />
<h1 class="relative text-lg font-semibold leading-[19px] dark:text-white m-0 p-0">
{{ appStore.title }}
@ -17,43 +17,18 @@
</h1>
</router-link>
</div>
<div class="flex items-center gap-4">
<a-dropdown v-if="isDev" trigger="hover">
<a-button shape="round">
<template #icon>
<i class="icon-park-outline-api"></i>
</template>
</a-button>
<template #content>
<a-doption>接口文档</a-doption>
</template>
</a-dropdown>
<div class="flex items-center gap-2">
<div>
<a-input-search placeholder="搜索菜单/页面" :allow-clear="true"></a-input-search>
</div>
<a-tooltip v-for="btn in buttons" :key="btn.icon" :content="btn.tooltip">
<a-button shape="round" @click="btn.onClick">
<a-button @click="btn.onClick" class="!bg-transparent !hover:bg-gray-100">
<template #icon>
<i :class="btn.icon"></i>
<i :class="btn.icon" class="text-base"></i>
</template>
</a-button>
</a-tooltip>
<a-dropdown>
<span class="cursor-pointer">
<a-avatar :size="28">
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
</a-avatar>
<span class="mx-2">
{{ userStore.nickname }}
</span>
<i class="icon-park-outline-down"></i>
</span>
<template #content>
<a-doption v-for="item in userButtons" :key="item.text" @click="item.onClick">
<template #icon>
<i :class="item.icon"></i>
</template>
{{ item.text }}
</a-doption>
</template>
</a-dropdown>
<user-dropdown></user-dropdown>
<a-drawer v-model:visible="themeConfig.visible" title="主题设置" :width="280"></a-drawer>
</div>
</a-layout-header>
@ -74,8 +49,27 @@
</a-layout-sider>
<a-layout class="layout-content flex-1">
<a-layout-header class="h-8 bg-white border-b border-slate-200 dark:bg-slate-800 dark:border-slate-700">
<div class="h-full flex items-center gap-2 px-4">
<a-tag class="cursor-pointer">首页</a-tag>
<div class="h-full flex items-center justify-between gap-2 px-4">
<div class="space-x-2">
<a-tag
v-for="item in tagItems"
:key="item.text"
:color="item.active ? 'rgb(var(--primary-6))' : ''"
:closable="item.showClose"
class="cursor-pointer"
@mouseenter="item.showClose = true"
@mouseleave="item.showClose = false"
>
{{ item.text }}
</a-tag>
</div>
<div>
<a-tooltip v-for="btn in tabButtons" :key="btn.icon" :content="btn.text" position="bottom">
<span class="px-1.5 text-gray-600 py-0.5 hover:bg-slate-100 rounded cursor-pointer">
<i :class="btn.icon"></i>
</span>
</a-tooltip>
</div>
</div>
</a-layout-header>
<a-layout-content class="overflow-x-auto">
@ -96,8 +90,9 @@
<script lang="ts" setup>
import { useAppStore, useUserStore } from "@/store";
import { Message } from "@arco-design/web-vue";
import Menu from "./components/menu.vue";
import { IconSync } from "@arco-design/web-vue/es/icon";
import Menu from "./components/menu.vue";
import userDropdown from "./components/userDropdown.vue";
const appStore = useAppStore();
const userStore = useUserStore();
@ -121,36 +116,52 @@ const buttons = [
},
{
icon: "icon-park-outline-moon",
tooltip: "切换主题",
tooltip: "主题",
onClick: () => {
appStore.toggleDark();
},
},
{
icon: "icon-park-outline-config",
tooltip: "打开设置",
tooltip: "设置",
onClick: () => {
themeConfig.value.visible = true;
},
},
];
const userButtons = [
{
icon: "icon-park-outline-config",
text: "个人设置",
icon: "icon-park-outline-github",
tooltip: "仓库",
onClick: () => {
router.push("/my");
window.open("https://github.com/appnify/starter-vue", "_blank");
},
},
];
const tabButtons = [
{
icon: "icon-park-outline-logout",
text: "退出登录",
onClick: async () => {
userStore.clearUser();
Message.success("提示:已退出登陆!");
router.push({ path: "/login", query: { redirect: route.path } });
},
icon: "icon-park-outline-refresh",
text: "刷新页面",
},
{
icon: "icon-park-outline-full-screen",
text: "全屏显示",
},
{
icon: "icon-park-outline-more",
text: "更多",
},
];
const tagItems = [
{
active: true,
text: "首页",
showClose: false,
},
{
active: false,
text: "评论管理",
showClose: true,
},
];
</script>

View File

@ -15,9 +15,9 @@
<div
class="login-box w-[960px] h-[560px] relative mx-4 grid md:grid-cols-2 rounded overflow-hidden border border-blue-100"
>
<div class="login-left relative hidden md:block w-full h-full overflow-hidden bg-[rgb(var(--primary-6))] px-4">
<!-- <img src="./image-br.svg" :alt="appStore.title" class="w-full h-full select-none" /> -->
</div>
<div
class="login-left relative hidden md:block w-full h-full overflow-hidden bg-[rgb(var(--primary-6))] px-4"
></div>
<div class="relative p-20 px-8 md:px-14 bg-white shadow-sm">
<div class="text-2xl">欢迎登陆</div>
<div class="text-base text-gray-500 mt-2">{{ meridiem }}欢迎登陆{{ appStore.title }}!</div>

View File

@ -4,6 +4,10 @@
<section class="my-page m-5 py-4 pr-4 h-full bg-white">
<a-tabs direction="vertical">
<a-tab-pane key="1" title="基本设置">
<template #title>
<i class="icon-park-outline-config"></i>
基本设置
</template>
<a-form :model="user" layout="vertical">
<a-form-item label="个人头像">
<a-avatar :size="64">
@ -37,6 +41,10 @@
</a-form>
</a-tab-pane>
<a-tab-pane key="5" title="消息推送">
<template #title>
<i class="icon-park-outline-message"></i>
消息通知
</template>
<a-form :model="user" layout="vertical">
<a-form-item label="消息推送">
<div>
@ -56,6 +64,10 @@
</a-form>
</a-tab-pane>
<a-tab-pane key="2" title="主题偏好">
<template #title>
<i class="icon-park-outline-theme"></i>
主题设置
</template>
<div class="flex-1">
<a-form :model="user" layout="vertical">
<a-form-item label="主题">
@ -76,6 +88,10 @@
</div>
</a-tab-pane>
<a-tab-pane key="3" title="额外功能">
<template #title>
<i class="icon-park-outline-shield"></i>
基本设置
</template>
<div class="flex-1 grid">
<div class="mb-3">功能列表</div>
<div v-for="i in 3" class="border-t py-4 flex justify-between items-center gap-4">
@ -122,7 +138,7 @@
</div>
<div>
<div class="text-gray-900">支付功能</div>
<div class="text-gray-400 mt-1">通知管理员由企业互联的管理员来设置拥有通知业务的最大权限</div>
<div class="text-gray-400 mt-2">通知管理员由企业互联的管理员来设置拥有通知业务的最大权限</div>
</div>
</div>
<div>

View File

@ -2,10 +2,10 @@
<BreadPage>
<template #content>
<div class="p-4">
<a-alert :closable="true">
<a-alert :closable="true" class="mb-2">
仅展示近 90 天内的数据如需查看更多数据请联系管理员
</a-alert>
<div class="bg-white p-4 mt-2">
<div class="bg-white p-4">
<Table v-bind="table"></Table>
</div>
</div>

View File

@ -1,11 +1,6 @@
<template>
<BreadPage>
<a-radio-group type="button" v-model="type">
<a-radio value="all">全部</a-radio>
<a-radio value="all1">已激活</a-radio>
<a-radio value="all2">未激活</a-radio>
</a-radio-group>
<Table v-bind="table" class="pt-4">
<Table v-bind="table">
<template #action>
<a-button status="danger" type="outline" :disabled="true">
<template #icon>
@ -33,7 +28,7 @@ const table = useTable({
{
title: "用户昵称",
dataIndex: "username",
width: 180,
width: 240,
render: ({ record }) => (
<div class="flex items-center">
<a-avatar size={40}>
@ -41,7 +36,7 @@ const table = useTable({
</a-avatar>
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
<span>{record.nickname}</span>
<span class="text-gray-400 text-xs truncate">ID: {record.username}</span>
<span class="text-gray-400 text-xs truncate">@{record.username}</span>
</span>
</div>
),

View File

@ -1,8 +1,15 @@
@import url("@arco-design/web-vue/es/index.less");
@arcoblue-6:#08f;
@arcoblue-6: #08f;
body {
li.arco-dropdown-option {
line-height: 28px;
width: calc(100% - 8px);
margin-left: 4px;
margin-right: 4px;
border-radius: 4px;
}
.arco-layout-sider {
box-shadow: none;
}
@ -23,11 +30,25 @@ body {
}
.arco-menu {
&.arco-menu-vertical .arco-menu-item {
line-height: 36px;
margin-top: 2px;
}
&.arco-menu-vertical .arco-menu-group-title {
line-height: 28px;
margin-top: 8px;
}
[class^="icon-"] {
vertical-align: -2px;
}
.arco-menu-item {
margin: 0 4px;
&:hover {
background-color: var(--color-neutral-2);
}
&.arco-menu-selected {
// color: @arcoblue-6;
// background-color: @arcoblue-1;
color: #fff;
background-color: @arcoblue-6;
.arco-menu-icon {

View File

@ -17,6 +17,7 @@ declare module '@vue/runtime-core' {
ACheckboxGroup: typeof import('@arco-design/web-vue')['CheckboxGroup']
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
ADatePicker: typeof import('@arco-design/web-vue')['DatePicker']
ADivider: typeof import('@arco-design/web-vue')['Divider']
ADoption: typeof import('@arco-design/web-vue')['Doption']
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']