ref 组件配置微调

This commit is contained in:
bootx
2024-07-02 22:01:39 +08:00
parent 4835eb66c7
commit 0427a8f88a
15 changed files with 280 additions and 112 deletions

View File

@@ -0,0 +1,83 @@
<template>
<a-form class="page-query" layout="inline">
<a-row :gutter="gutter">
<query-item
:key="i"
v-show="i < defaultItemCount || toggleSearchStatus"
v-for="(field, i) in fields"
:field="field"
:md="defaultItemMd"
:query-params="queryParams"
@enter-query="query"
/>
<a-col :md="defaultItemMd" :sm="24">
<a-space>
<a-button type="primary" :disabled="disabledQuery" @click="query">查询</a-button>
<a-button @click="reset">重置</a-button>
</a-space>
<a
v-show="fields.length > defaultItemCount"
@click="handleToggleSearch"
style="margin-left: 8px"
>
{{ toggleSearchStatus ? '收起' : '展开' }}
<up-outlined v-if="toggleSearchStatus" />
<down-outlined v-else />
</a>
</a-col>
</a-row>
</a-form>
</template>
<script lang="ts" setup>
import QueryItem from './QueryItem.vue'
import { ref } from 'vue'
import { DownOutlined, UpOutlined } from '@ant-design/icons-vue'
import { QueryField } from './Query'
// 切换搜索条件展开状态
let toggleSearchStatus = ref(false)
withDefaults(
defineProps<{
// 字段
fields: QueryField[]
// 查询条件
queryParams: object
// 默认展示几个
defaultItemCount?: number
// 所占栅格宽度
defaultItemMd?: number
// 禁用查询
disabledQuery?: boolean
// gutter
gutter?: number
}>(),
{
defaultItemCount: 2,
defaultItemMd: 6,
disabledQuery: false,
gutter: 10,
},
)
const emits = defineEmits(['update:modelValue', 'query', 'reset'])
/**
* 查询
*/
function query() {
emits('query')
}
/**
* 重置
*/
function reset() {
emits('reset')
}
/**
* 切换搜索条件展开状态
*/
function handleToggleSearch() {
toggleSearchStatus.value = !toggleSearchStatus.value
}
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,74 @@
import { LabeledValue } from 'ant-design-vue/lib/select'
// 数字
export const NUMBER = 'number'
// 字符串
export const STRING = 'string'
// 布尔
export const BOOLEAN = 'boolean'
// 日期
export const DATE = 'date'
// 时间
export const TIME = 'time'
// 日期时间
export const DATE_TIME = 'date_time'
// 列表
export const LIST = 'list'
/**
* 查询属性
*/
export interface QueryField {
//类型
type?: 'number' | 'string' | 'boolean' | 'date' | 'time' | 'date_time' | 'list'
// 提示
placeholder?: string
// 字段名称
field?: string
// 栅格宽度
md?: number
// 显示名称
name?: string
// 精度
precision?: number
// 查询列表
selectList?: LabeledValue[] | null
// 时间格式化
format?: string | null
// 默认值 未启用
defaultValue?: number | string
}
/**
* 查询参数
*/
export interface QueryParam {
// antd select 组件限制原因导致不能使用bool
or?: 'true' | 'false'
// 参数名称
paramName?: string
// 格式化 主要用于时间格式化
format?: string
// 精度
precision?: number
// 比较类型
compareType?:
| 'eq'
| 'ne'
| 'like'
| 'like_left'
| 'like_right'
| 'not_like'
| 'gt'
| 'ge'
| 'lt'
| 'le'
| 'is_null'
| 'not_null'
// 参数类型
paramType?: string
// 参数值
paramValue?: object
// 嵌套查询
nestedParams?: QueryParam[]
}

View File

@@ -0,0 +1,96 @@
<template>
<a-col :md="field.md || md" :sm="24">
<a-form-item :label="field.name">
<!-- 文本输入 -->
<a-input
@keyup.enter="query"
allowClear
v-if="field.type === STRING"
:placeholder="field.placeholder ? field.placeholder : '请输入查询值'"
v-model:value="queryParams[field.field]"
/>
<!-- 数字输入 -->
<a-input-number
allowClear
style="width: 100%"
v-else-if="field.type === NUMBER"
:placeholder="field.placeholder ? field.placeholder : '请输入查询值'"
:precision="field.precision ? field.precision : 0"
v-model:value="queryParams[field.field]"
/>
<!-- 布尔 -->
<a-radio-group v-else-if="field.type === BOOLEAN" v-model:value="queryParams[field.field]">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
<!-- 列表 -->
<a-select
allowClear
v-else-if="field.type === LIST"
:placeholder="field.placeholder ? field.placeholder : '请选择查询值'"
v-model:value="queryParams[field.field]"
:options="field.selectList"
/>
<!-- 日期 -->
<a-date-picker
allowClear
v-else-if="field.type === DATE"
style="width: 100%"
:placeholder="field.placeholder ? field.placeholder : '请选择日期'"
:valueFormat="field.format ? field.format : 'YYYY-MM-DD'"
v-model:value="queryParams[field.field]"
/>
<!-- 时间 -->
<a-time-picker
allowClear
v-else-if="field.type === TIME"
style="width: 100%"
:placeholder="field.placeholder ? field.placeholder : '请选择时间'"
:valueFormat="field.format ? field.format : 'HH:mm:ss'"
v-model:value="queryParams[field.field]"
/>
<!-- 日期时间 -->
<a-date-picker
allowClear
showTime
v-else-if="field.type === DATE_TIME"
style="width: 100%"
:placeholder="field.placeholder ? field.placeholder : '请选择日期时间'"
:valueFormat="field.format ? field.format : 'YYYY-MM-DD HH:mm:ss'"
v-model:value="queryParams[field.field]"
/>
<!-- 默认文本输入 -->
<a-input
allowClear
v-else
:placeholder="field.placeholder ? field.placeholder : '请输入查询值'"
v-model:value="queryParams[field.field]"
/>
</a-form-item>
</a-col>
</template>
<script lang="ts" setup>
import { BOOLEAN, DATE, DATE_TIME, LIST, NUMBER, QueryField, STRING, TIME } from './Query'
const emits = defineEmits(['enterQuery'])
withDefaults(
defineProps<{
// 查询字段属性
field: QueryField
// 查询条件
queryParams: object
// md 栅格占位
md: number
}>(),
{
md: 6,
},
)
function query() {
emits('enterQuery')
}
</script>
<style scoped></style>

View File

@@ -29,7 +29,7 @@
import { propTypes } from '@/utils/propTypes'
import { REDIRECT_NAME } from '@/router/constant'
import { useRouter } from 'vue-router'
import { isFunction, isHttpUrl } from '@/utils/is'
import { isFunction, isOutsideUrl } from '@/utils/is'
import { openWindow } from '@/utils'
import { useOpenKeys } from './useOpenKeys'
@@ -126,8 +126,10 @@
}
async function handleSelect(key: string) {
if (isHttpUrl(key)) {
openWindow(key)
// 判断是否需要通过外部打开
const path = isOutsideUrl(key)
if (path) {
openWindow(path)
return
}
const { beforeClickFn } = props

View File

@@ -30,11 +30,7 @@ export enum SessionTimeoutProcessingEnum {
*/
export enum PermissionModeEnum {
// 角色权限
ROLE = 'ROLE',
// 后端
BACK = 'BACK',
// 路由映射
ROUTE_MAPPING = 'ROUTE_MAPPING',
}
// Route switching animation

View File

@@ -5,52 +5,14 @@ import { usePermissionStore } from '@/store/modules/permission'
import { useTabs } from './useTabs'
import { router, resetRouter } from '@/router'
import projectSetting from '@/settings/projectSetting'
import { PermissionModeEnum } from '@/enums/appEnum'
import { RoleEnum } from '@/enums/roleEnum'
import { intersection } from 'lodash-es'
import { isArray } from '@/utils/is'
import { useMultipleTabStore } from '@/store/modules/multipleTab'
// User permissions related operations
export function usePermission() {
const appStore = useAppStore()
const permissionStore = usePermissionStore()
const { closeAll } = useTabs(router)
/**
* Change permission mode
*/
async function togglePermissionMode() {
appStore.setProjectConfig({
permissionMode:
projectSetting.permissionMode === PermissionModeEnum.BACK
? PermissionModeEnum.ROUTE_MAPPING
: PermissionModeEnum.BACK,
})
location.reload()
}
/**
* Reset and regain authority resource information
* 重置和重新获得权限资源信息
* @param id
*/
async function resume() {
console.log('重置和重新获得权限资源信息')
const tabStore = useMultipleTabStore()
tabStore.clearCacheTabs()
resetRouter()
const routes = await permissionStore.buildRoutesAction()
routes.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw)
})
permissionStore.setLastBuildMenuTime()
closeAll()
}
/**
* Determine whether there is permission
@@ -68,12 +30,5 @@ export function usePermission() {
return (intersection(value, allCodeList) as string[]).length > 0
}
/**
* refresh menu data
*/
async function refreshMenu() {
resume()
}
return { hasPermission, togglePermissionMode, refreshMenu }
return { hasPermission }
}

View File

@@ -55,7 +55,6 @@
userStore.confirmLoginOut()
}
// open doc
function openDoc() {
openWindow(DOC_URL)
}
@@ -116,5 +115,10 @@
color: @header-light-desc-color;
}
}
&-dropdown-overlay {
.ant-dropdown-menu-item {
min-width: 160px;
}
}
}
</style>

View File

@@ -1,8 +1,5 @@
import type { Router } from 'vue-router'
import { configureDynamicParamsMenu } from '../helper/menuHelper'
import { Menu } from '../types'
import { PermissionModeEnum } from '@/enums/appEnum'
import { useAppStoreWithOut } from '@/store/modules/app'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
@@ -21,27 +18,9 @@ export function createParamMenuGuard(router: Router) {
return
}
let menus: Menu[] = []
if (isBackMode()) {
menus = permissionStore.getBackMenuList
} else if (isRouteMappingMode()) {
menus = permissionStore.getFrontMenuList
}
const menus = permissionStore.getBackMenuList
menus.forEach((item) => configureDynamicParamsMenu(item, to.params))
next()
})
}
const getPermissionMode = () => {
const appStore = useAppStoreWithOut()
return appStore.getProjectConfig.permissionMode
}
// 后端模式
const isBackMode = () => {
return getPermissionMode() === PermissionModeEnum.BACK
}
// 路由映射
const isRouteMappingMode = () => {
return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING
}

View File

@@ -7,7 +7,7 @@ import { warn } from '@/utils/log'
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import XEUtils from 'xe-utils'
const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue')
const IFRAME = () => import('@/views/sys/iframe/FrameBlank.vue')
const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>()

View File

@@ -1,13 +1,11 @@
import type { Menu, MenuModule } from '@/router/types'
import type { RouteRecordNormalized } from 'vue-router'
import { useAppStoreWithOut } from '@/store/modules/app'
import { usePermissionStore } from '@/store/modules/permission'
import { transformMenuModule, getAllParentPath } from '@/router/helper/menuHelper'
import { filter } from '@/utils/helper/treeHelper'
import { isHttpUrl } from '@/utils/is'
import { router } from '@/router'
import { PermissionModeEnum } from '@/enums/appEnum'
import { pathToRegexp } from 'path-to-regexp'
const modules = import.meta.glob('./modules/**/*.ts', { eager: true })
@@ -24,20 +22,8 @@ Object.keys(modules).forEach((key) => {
// ==========Helper===========
// ===========================
const getPermissionMode = () => {
const appStore = useAppStoreWithOut()
return appStore.getProjectConfig.permissionMode
}
const isBackMode = () => {
return getPermissionMode() === PermissionModeEnum.BACK
}
const isRouteMappingMode = () => {
return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING
}
const isRoleMode = () => {
return getPermissionMode() === PermissionModeEnum.ROLE
return false
}
const staticMenus: Menu[] = []

View File

@@ -16,15 +16,15 @@ export const INTERNAL: AppRouteModule = {
// {
// path: '/account/setting',
// name: 'AccountSettingPage',
// component: () => import('/@/views/account/setting/index.vue'),
// component: () => import('@/views/account/setting/index.vue'),
// meta: { title: '个人设置' },
// },
// {
// path: '/about/index',
// name: 'AboutPage',
// component: () => import('/@/views/sys/about/index.vue'),
// meta: { title: '关于' },
// },
{
path: '/about/index',
name: 'AboutPage',
component: () => import('@/views/sys/about/index.vue'),
meta: { title: '关于' },
},
],
}
@@ -39,7 +39,7 @@ export const OUTSIDE: AppRouteModule = {
// {
// path: '/cashier',
// name: 'cashier',
// component: () => import('/@/views/demo/cashier/Cashier.vue'),
// component: () => import('@/views/demo/cashier/Cashier.vue'),
// meta: { title: '收银台演示', ignoreAuth: true },
// },
],

View File

@@ -14,7 +14,7 @@ import { APP_PRESET_COLOR_LIST } from './designSetting'
// ! You need to clear the browser cache after the change
const setting: ProjectConfig = {
// 是否显示配置按钮
showSettingButton: true,
showSettingButton: false,
// 是否显示主题切换按钮
showDarkModeToggle: true,

View File

@@ -69,7 +69,7 @@
background-color: @dark-bg;
&::before {
background-image: url(/@/assets/svg/login-bg-dark.svg);
background-image: url(@/assets/svg/login-bg-dark.svg);
}
.ant-input,
@@ -115,7 +115,7 @@
width: 100%;
height: 100%;
margin-left: -48%;
background-image: url(/@/assets/svg/login-bg.svg);
background-image: url(@/assets/svg/login-bg.svg);
background-position: 100%;
background-repeat: no-repeat;
background-size: auto 100%;

View File

@@ -11,20 +11,13 @@
import { useDesign } from '@/hooks/web/useDesign'
import { useUserStore } from '@/store/modules/user'
import { usePermissionStore } from '@/store/modules/permission'
import { useAppStore } from '@/store/modules/app'
import { PermissionModeEnum } from '@/enums/appEnum'
import { type Nullable } from '@vben/types'
const { prefixCls } = useDesign('st-login')
const userStore = useUserStore()
const permissionStore = usePermissionStore()
const appStore = useAppStore()
const userId = ref<Nullable<number | string>>(0)
const isBackMode = () => {
return appStore.getProjectConfig.permissionMode === PermissionModeEnum.BACK
}
onMounted(() => {
// 记录当前的UserId
userId.value = userStore.getUserInfo?.userId
@@ -35,7 +28,7 @@
if (userId.value && userId.value !== userStore.getUserInfo.userId) {
// 登录的不是同一个用户,刷新整个页面以便丢弃之前用户的页面状态
document.location.reload()
} else if (isBackMode() && permissionStore.getLastBuildMenuTime === 0) {
} else if (permissionStore.getLastBuildMenuTime === 0) {
// 后台权限模式下没有成功加载过菜单就重新加载整个页面。这通常发生在会话过期后按F5刷新整个页面后载入了本模块这种场景
document.location.reload()
}

View File

@@ -35,7 +35,7 @@ declare module 'vue-router' {
currentActiveMenu?: string
// Never show in tab
hideTab?: boolean
// Never show in menu
// 隐藏菜单
hideMenu?: boolean
isLink?: boolean
// only build for Menu