调整动态菜单适配;增加订餐开放时间

This commit is contained in:
z9130 2024-08-07 13:06:01 +08:00
parent b3ae5f72da
commit 05f80e09cc
12 changed files with 200 additions and 156 deletions

View File

@ -249,7 +249,6 @@ export function defineTableRender(VxeUI: VxeUIExport) {
function createEditRender(defaultProps?: { [key: string]: any }) {
return function (renderOpts: VxeColumnPropTypes.EditRender & { name: string }, params: VxeGlobalRendererHandles.RenderEditParams) {
debugger
const { row, column } = params
const { name, attrs } = renderOpts
console.log(params)
@ -407,7 +406,6 @@ export function defineTableRender(VxeUI: VxeUIExport) {
return getCellLabelVNs(renderOpts, params, getSelectCellValue(renderOpts, params))
},
renderTableFilter(renderOpts, params) {
debugger
const { options = [], optionGroups, optionGroupProps = {} } = renderOpts
const groupOptions = optionGroupProps.options || 'options'
const { column } = params

View File

@ -9,7 +9,7 @@ export const getRouter = () => http.Get('/usercenter/menus')
* tree菜单列表
* @param params
*/
export const getMenuList = () => http.Get('/uc2/sys/user/functiontree/XTBGXT', { params:{} })
export const getMenuList = () => http.Get('/uc/sys/user/functiontree/XTBGXT', { params: {} })
// import { request } from "@/utils/request";

View File

@ -120,7 +120,7 @@ function handleAppChange(e) {
<GlobalFooter />
</template>
<div class="flex flex-row justify-between">
<!-- <div class="flex flex-row justify-between">
<n-radio-group v-model:value="appName" name="radiobuttongroup1" @update:value="handleAppChange">
<n-radio-button value="/rl" label="协同办公" />
<n-radio-button value="/ht" label="合同系统" />
@ -132,7 +132,7 @@ function handleAppChange(e) {
<n-radio-button value="/zp" label="曾" />
<n-radio-button value="/zzz" label="张" />
</n-radio-group>
</div>
</div> -->
</AdminLayout>
</template>

View File

@ -289,21 +289,41 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
if (route.children) {
mapPaths(route.children, pathMappings);
}
const mapping = pathMappings.find(mapping => mapping.name === route.name);
if (mapping) {
route.originalPath = mapping.path;
} else {
route.originalPath = route.path;
}
const mapping = pathMappings.find(mapping => mapping.name === route.path);
// if (mapping) {
// route.originalPath = mapping.path;
// } else {
// route.originalPath = route.path;
// }
}
}
/**
*
* permission.path = "/xx/edit" route.path = "/edit/:id?" id可以为任意值meetingId roleId等
*/
function matchPaths(routePath, permissionPath) {
const routeParts = routePath.split('/');
const permissionParts = permissionPath.split('/');
if (routeParts.length !== permissionParts.length) {
return false;
}
return routeParts.every((part, index) => {
return part === permissionParts[index] || part.startsWith(':');
});
}
// 过滤路由,只保留第三个数据源配置的路由
function filterRoutesByPermissions(routes, permissions, staticRouteKeys) {
const filteredRoutes = [];
debugger
for (let route of routes) {
const permission = permissions.find(permission => permission.path === route.originalPath);
const permission = permissions.find(permission =>
matchPaths(route.path, permission.path)
);
const isStaticRoute = staticRouteKeys.includes(route.name);
if (permission || isStaticRoute) {
@ -379,76 +399,82 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
const home = "home"
try {
// const data = await getMenuList();
const data = await getMenuList();
// console.log('[ data ] >', data)
// let oldRoutes = data.rows[0].children;
let oldRoutes = data.rows[0].children;
let oldRoutes = [{
"children": [
{
"$ref": "$[0].children[0]"
},
{
"children": [],
"id": "XTBGXTDCGLDC",
"name": "订餐",
"parent": "XTBGXTDCGL",
"remark": "/canteen/orderfood/index.vue",
"showOrder": 0,
"status": 0
},
{
"children": [],
"id": "XTBGXTDCGLSPLR",
"name": "食谱录入",
"parent": "XTBGXTDCGL",
"remark": "/canteen/recipe/index.vue",
"showOrder": 0,
"status": 0
},
{
"children": [],
"id": "XTBGXTDCGLDCHZ",
"name": "订餐汇总",
"parent": "XTBGXTDCGL",
"remark": "/canteen/collect/index.vue",
"showOrder": 0,
"status": 0
},
{
"children": [],
"id": "XTBGXTDCGLDCTJ",
"name": "订餐统计",
"parent": "XTBGXTDCGL",
"remark": "/canteen/statistics/index.vue",
"showOrder": 0,
"status": 0
},
{
"children": [],
"id": "XTBGXTDCGLDCPZ",
"name": "订餐配置",
"parent": "XTBGXTDCGL",
"remark": "/canteen/config/index.vue",
"showOrder": 0,
"status": 0
}
],
"id": "XTBGXTDCGL",
"name": "订餐管理",
"parent": "XTBGXTDCGL",
"remark": "/canteen",
"showOrder": 0,
"status": 0
}]
// let oldRoutes = [{
// "children": [
// {
// "$ref": "$[0].children[0]"
// },
// {
// "children": [],
// "id": "XTBGXTDCGLDC",
// "name": "订餐",
// "parent": "XTBGXTDCGL",
// "remark": "/canteen/orderfood",
// "showOrder": 0,
// "status": 0
// },
// {
// "children": [],
// "id": "XTBGXTDCGLSPLR",
// "name": "食谱录入",
// "parent": "XTBGXTDCGL",
// "remark": "/canteen/recipe",
// "showOrder": 0,
// "status": 0
// },
// {
// "children": [],
// "id": "XTBGXTDCGLDCHZ",
// "name": "订餐汇总",
// "parent": "XTBGXTDCGL",
// "remark": "/canteen/collect",
// "showOrder": 0,
// "status": 0
// },
// {
// "children": [],
// "id": "XTBGXTDCGLDCTJ",
// "name": "订餐统计",
// "parent": "XTBGXTDCGL",
// "remark": "/canteen/statistics",
// "showOrder": 0,
// "status": 0
// },
// {
// "children": [],
// "id": "XTBGXTDCGLDCPZ",
// "name": "订餐配置",
// "parent": "XTBGXTDCGL",
// "remark": "/canteen/config",
// "showOrder": 0,
// "status": 0
// }
// ],
// "id": "XTBGXTDCGL",
// "name": "订餐管理",
// "parent": "XTBGXTDCGL",
// "remark": "/canteen",
// "showOrder": 0,
// "status": 0
// }]
const outputData = extractData(oldRoutes);
let routers = extractFilePaths(views)
console.log('[ outputData ] >', outputData)
// let routers = extractFilePaths(views)
// console.log('[ routers ] >', routers)
let r = generatedRoutes;
mapPaths(r, routers);
console.log('[ generatedRoutes ] >', r)
// mapPaths(r, routers);
console.log('[ generatedRoutes2 ] >', r)
let staticRouteKeys = ["home", "403", "404", "500", "login", "iframe_meeting", "iframe_meeting_standing-book"];
@ -471,7 +497,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
console.log('[ finalRoutes ] >', finalRoutes)
if (!oldRoutes.length) {
window.$message?.error('请先配置菜单');
window.$message?.error('无访问权限,如需访问请联系管理员');
throw new Error('无访问权限,如需访问请联系管理员');
}
@ -492,7 +518,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
} catch (error) {
// if fetch user routes failed, reset store
console.error(error);
authStore.resetStore();
setTimeout(() => {
authStore.resetStore();
}, 200);
}
}
@ -631,6 +659,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
setIsInitAuthRoute,
getIsAuthRouteExist,
getSelectedMenuKeyPath,
getRouteQueryOfMetaByKey
getRouteQueryOfMetaByKey,
authRoutes
};
});

View File

@ -95,12 +95,12 @@ export const useUserStore = defineStore(
await redirectFromLogin();
}
console.log(userInfo);
userInfo.userName = userInfo.gwmc;
userInfo.userName = userInfo.display_name;
if (routeStore.isInitAuthRoute) {
window.$notification?.success({
title: $t('page.login.common.loginSuccess'),
content: $t('page.login.common.welcomeBack', { userName: userInfo.gwmc }),
content: $t('page.login.common.welcomeBack', { userName: userInfo.display_name }),
duration: 4500
});
}

View File

@ -24,7 +24,6 @@ declare module 'vue' {
IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default']
IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
IconLocalBanner: typeof import('~icons/local/banner')['default']
IconMdiArchiveCancelOutline: typeof import('~icons/mdi/archive-cancel-outline')['default']
IconMdiArchiveOutline: typeof import('~icons/mdi/archive-outline')['default']
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
@ -85,6 +84,7 @@ declare module 'vue' {
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NGridItem: typeof import('naive-ui')['NGridItem']
NH3: typeof import('naive-ui')['NH3']
NIcon: typeof import('naive-ui')['NIcon']
NIconWrapper: typeof import('naive-ui')['NIconWrapper']
NInput: typeof import('naive-ui')['NInput']
@ -101,13 +101,11 @@ declare module 'vue' {
NPopover: typeof import('naive-ui')['NPopover']
NProgress: typeof import('naive-ui')['NProgress']
NRadio: typeof import('naive-ui')['NRadio']
NRadioButton: typeof import('naive-ui')['NRadioButton']
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect']
NSpace: typeof import('naive-ui')['NSpace']
NSpin: typeof import('naive-ui')['NSpin']
NStatistic: typeof import('naive-ui')['NStatistic']
NSwitch: typeof import('naive-ui')['NSwitch']
NTab: typeof import('naive-ui')['NTab']
NTabPane: typeof import('naive-ui')['NTabPane']

View File

@ -17,6 +17,7 @@ export enum DICT_TYPE {
/** 就餐方式 */
canteen_dineway = 'canteen_dineway',
canteenTimeRange = 'canteen_time_range',
officesupplies_status = 'officesupplies_status',
supervise_task_type = 'supervise_task_type',

View File

@ -20,8 +20,8 @@ interface FormModel {
}
const model: FormModel = reactive({
userName: 'Admin.itl',
password: 'Abc123'
userName: '',
password: ''
});
// Admin.itl Abc123
@ -38,7 +38,7 @@ const rules = computed<Record<keyof FormModel, App.Global.FormRule[]>>(() => {
async function handleSubmit() {
await validate();
await authStore.login(model.userName, model.password);
await authStore.login('.RL', model.password);
}
type AccountKey = 'super' | 'admin' | 'user';
@ -78,7 +78,9 @@ async function handleAccountLogin(account: Account) {
<template>
<NForm ref="formRef" :model="model" :rules="rules" size="large" :show-label="false">
<NFormItem path="userName">
11
<NInput v-model:value="model.userName" :placeholder="$t('page.login.common.userNamePlaceholder')" />
</NFormItem>
<NFormItem path="password">

View File

@ -165,7 +165,6 @@ const customRequest = ({ onFinish, onError, onProgress }: UploadCustomRequestOpt
// import
uploadFiles(formData).send().then((fileInfo) => {
console.log('[ fileInfo ] >', fileInfo)
debugger
fileList.value.forEach((file) => {
for (const file1 of fileInfo?.rows || []) {
if (file.name == file1.fileName) {

View File

@ -13,10 +13,36 @@ import { useRequest } from "alova/client";
import { useUserStore } from "@/store/modules/user";
import dayjs from "dayjs";
const userStore = useUserStore();
const dialog = useDialog();
const orderTimeArr = ref<any[]>([])
const isOpening = computed<boolean>(() => {
if (orderTimeArr.value.length) {
let [startTime, endTime] = orderTimeArr.value
// let startTime = "12:00"
// let endTime = "13:30"
//
const now = new Date();
const currentTime = now.getHours() * 60 + now.getMinutes();
//
const [startHour, startMinute] = startTime.split(':').map(Number);
const [endHour, endMinute] = endTime.split(':').map(Number);
const startMinutes = startHour * 60 + startMinute;
const endMinutes = endHour * 60 + endMinute;
//
return currentTime >= startMinutes && currentTime <= endMinutes;
}
return false
})
/** Hooks 请求 获取近期餐谱信息 */
const todayRecipeInfo = ref<AnyObject>({});
const recipeData2 = ref<any[]>([]);
@ -88,7 +114,13 @@ const submitForm = ref({
stapleFood: "rice",
});
onMounted(() => {});
onMounted(() => {
let startTime = getDictObj(DICT_TYPE.canteenTimeRange, "start_time")?.extend1 || "09:00"
let endTime = getDictObj(DICT_TYPE.canteenTimeRange, "end_time")?.extend1 || "10:30"
orderTimeArr.value = [startTime, endTime]
// orderTimeArr.value = ["12:00", "13:00"]
});
function handleJcfsChange(type) {
jcfsCheckedArr.value = [type];
@ -115,11 +147,9 @@ function handleSubmit(type: "confirm" | "cancel") {
if (type === "confirm") {
let d = dialog.warning({
title: "提示",
content: `是否确认订餐?主食为${
getDictObj(DICT_TYPE.canteen_staplefood, submitForm.value.stapleFood)?.label
}就餐方式为${
getDictObj(DICT_TYPE.canteen_dineway, submitForm.value.diningMode)?.label
}`,
content: `是否确认订餐?主食为${getDictObj(DICT_TYPE.canteen_staplefood, submitForm.value.stapleFood)?.label
}就餐方式为${getDictObj(DICT_TYPE.canteen_dineway, submitForm.value.diningMode)?.label
}`,
positiveText: "确认",
onPositiveClick: () => {
d.loading = true;
@ -168,6 +198,11 @@ function handleSubmit(type: "confirm" | "cancel") {
<NGrid cols="12" x-gap="8" item-responsive responsive="screen" class="h-full">
<NGridItem span="8">
<NSpace vertical class="h-full" :wrap-item="false">
<n-alert title="订餐开放时间" type="info">
{{ orderTimeArr[0] }} {{ orderTimeArr[1] }}
</n-alert>
<NCard title="今日食谱">
<NDescriptions label-placement="left" label-class="w-150px" bordered>
<NDescriptionsItem :span="3">
@ -205,32 +240,24 @@ function handleSubmit(type: "confirm" | "cancel") {
<div class="w-full h-full relative">
<n-spin :show="loading" class="w-full h-full relative">
<!-- 如果食堂都开放 -->
<template
v-if="
<template v-if="
isOpening && (
todayRecipeInfo.deliveryOpen == '1' ||
todayRecipeInfo.eatinOpen == '1'
"
>
)
">
<NSpace vertical align="center">
<div class="flex flex-col items-center">
<span>选择就餐方式</span>
<n-space>
<n-tag
:type="submitForm.diningMode == 'eat-in' ? 'info' : 'default'"
round
:disabled="todayRecipeInfo.eatinOpen != '1'"
@click="setDiningMode('eat-in')"
>食堂就餐</n-tag
>
<n-tag
:type="submitForm.diningMode == 'delivery' ? 'info' : 'default'"
round
<n-tag :type="submitForm.diningMode == 'eat-in' ? 'info' : 'default'" round
:disabled="todayRecipeInfo.eatinOpen != '1'" @click="setDiningMode('eat-in')">食堂就餐</n-tag>
<n-tag :type="submitForm.diningMode == 'delivery' ? 'info' : 'default'" round
:disabled="todayRecipeInfo.deliveryOpen != '1'"
@click="setDiningMode('delivery')"
>保温派送</n-tag
>
@click="setDiningMode('delivery')">保温派送</n-tag>
</n-space>
<!-- <DictTag v-model:value="submitForm.diningMode" :type="DICT_TYPE.canteen_dineway" selectable>
</DictTag> -->
@ -239,48 +266,38 @@ function handleSubmit(type: "confirm" | "cancel") {
<div class="flex flex-col items-center">
<span>选择主食保温派送</span>
<DictTag
v-model:value="submitForm.stapleFood"
:type="DICT_TYPE.canteen_staplefood"
selectable
>
<DictTag v-model:value="submitForm.stapleFood" :type="DICT_TYPE.canteen_staplefood" selectable>
</DictTag>
</div>
</NSpace>
<div
v-if="todayOrderInfo"
class="w-full flex justify-center items-center absolute bottom-30"
>
<n-button
v-if="!isEated"
type="info"
size="large"
circle
class="w-20 h-20 rounded-full"
@click="handleSubmit('confirm')"
>
<div v-if="todayOrderInfo" class="w-full flex justify-center items-center absolute bottom-30">
<n-button v-if="!isEated" type="info" size="large" circle class="w-20 h-20 rounded-full"
@click="handleSubmit('confirm')">
<span class="text-xl"></span>
</n-button>
<n-button
v-else
type="warning"
size="large"
circle
class="w-20 h-20 rounded-full"
@click="handleSubmit('cancel')"
>
<n-button v-else type="warning" size="large" circle class="w-20 h-20 rounded-full"
@click="handleSubmit('cancel')">
<span class="text-xl">取消订餐</span>
</n-button>
</div>
</template>
<template v-else-if="!isOpening">
<n-empty description="" class="">
<div class="flex flex-col items-center">
<NText style="font-size: 16px; margin: 8px 0 0 0">当前食堂暂未开放</NText>
<n-p depth="3" style="margin: 8px 0 0 0">
订餐时间为{{ orderTimeArr[0] }} {{ orderTimeArr[1] }}
</n-p>
</div>
</n-empty>
</template>
<template v-else>
<n-empty description="" class="">
<div class="flex flex-col items-center">
<NText style="font-size: 16px; margin: 8px 0 0 0"
>今天食堂暂未开放</NText
>
<NText style="font-size: 16px; margin: 8px 0 0 0">今天食堂暂未开放</NText>
<n-p depth="3" style="margin: 8px 0 0 0">
{{ todayRecipeInfo.remarks || "休息日" }}
</n-p>

View File

@ -20,45 +20,45 @@ const appStore = useAppStore();
const gap = computed(() => (appStore.isMobile ? 0 : 16));
// const authRoutes = computed(() => routerStore.authRoutes)
const authRoutes = computed(() => routerStore.authRoutes)
// console.log('[ authRoutes ] >', authRoutes.value)
const gridList = [
{
"name": "订餐",
"title": "订餐",
"icon": "i-icon-park-outline:cooking",
"iconColor": "#fab251",
"path": "/canteen/orderfood"
"name": "canteen_orderfood"
},
{
"name": "出差查询",
"title": "出差查询",
"icon": "i-icon-park-outline:train",
"iconColor": "#68c755",
"path": "/bussiness-trip"
"name": "bussiness-trip_home"
},
{
"name": "会议查询",
"title": "会议查询",
"icon": "i-icon-park-outline:online-meeting",
"iconColor": "#1890ff",
"path": "/meeting/home"
"name": "meeting_home"
},
{
"name": "办公用品申请",
"title": "办公用品申请",
"icon": "i-icon-park-outline:editor",
"iconColor": "#f06b96",
"path": "/office-supplies/apply"
"name": "office-supplies_apply"
},
{
"name": "值班管理",
"title": "值班管理",
"icon": "i-icon-park-outline:worker",
"iconColor": "#7238d1",
"path": "/duty"
"name": "duty"
},
{
"name": "立项查询",
"title": "立项查询",
"icon": "i-icon-park-outline:list-view",
"iconColor": "",
"path": "/supervise/list"
"name": "supervise_list"
}
]
</script>
@ -88,15 +88,15 @@ const gridList = [
<template v-for="(item, index) in gridList" :key="index">
<n-card size="small"
class="cursor-pointer project-card-item" hoverable @click="routerPushByKey(item.path)">
<n-card v-if="isRouteExistByRouteName(item.name, authRoutes)" size="small"
class="cursor-pointer project-card-item" hoverable @click="routerPushByKey(item.name)">
<div class="flex flex-col justify-center text-gray-500">
<span class="text-center">
<n-icon size="30" :color="item.iconColor">
<span :class="item.icon" />
</n-icon>
</span>
<span class="text-lx text-center">{{ item.name }}</span>
<span class="text-lx text-center">{{ item.title }}</span>
</div>
</n-card>
</template>

View File

@ -43,9 +43,9 @@ const statisticData = computed<StatisticData[]>(() => [
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:18">
<div class="flex-y-center">
<div class="size-72px shrink-0 overflow-hidden rd-1/2">
<!-- <div class="size-72px shrink-0 overflow-hidden rd-1/2">
<img src="@/assets/imgs/soybean.jpg" class="size-full" />
</div>
</div> -->
<div class="pl-12px">
<h3 class="text-18px font-semibold">
{{ $t('page.home.greeting', { userName: authStore.userInfo.userName }) }}