Merge branch 'master' of https://gitea.zianxin.com/zax/biz-mobile-react-cloud
# Conflicts: # index.html
This commit is contained in:
commit
d2b68998b2
17 files changed
+655
-427
No files matched your search
@@ -20,15 +20,15 @@ VITE_OAUTH2_APP_CLIENT='mini:mini'
|
||||
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.174:9999 # 邓-本地
|
||||
VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
|
||||
#VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
|
||||
VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
|
||||
; VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
|
||||
|
||||
# --------------------------- 开发环境 图片访问基础地址 ---------------------------
|
||||
# VITE_IMAGE_DEV_PATH = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_IMAGE_DEV_PATH = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_IMAGE_DEV_PATH = http://192.168.101.174:9999 # 邓-本地
|
||||
VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
|
||||
#VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
|
||||
VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
|
||||
; VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
|
||||
|
||||
# --------------------------- 生产环境 api地址 ----------------------------------
|
||||
VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
|
||||
|
||||
+4
-4
@@ -21,9 +21,9 @@
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<script>
|
||||
// var vConsole = new VConsole()
|
||||
// console.log("console:", vConsole)
|
||||
</script>
|
||||
<!-- <script>
|
||||
var vConsole = new VConsole()
|
||||
console.log("console:", vConsole)
|
||||
</script> -->
|
||||
</body>
|
||||
</html>
|
||||
+235
-235
@@ -1,235 +1,235 @@
|
||||
<script lang="ts">
|
||||
import { getLaunchParam } from "@/sheep/utils/app"
|
||||
import { getAppInfo } from "@@/utils/app"
|
||||
import { APPENV } from "./sheep/constant"
|
||||
|
||||
interface TabbarItem {
|
||||
pagePath: string
|
||||
text: string
|
||||
iconPath: string
|
||||
selectedIconPath: string
|
||||
launchParam: string[]
|
||||
auth: string[]
|
||||
}
|
||||
|
||||
const tabbar: TabbarItem[] = [
|
||||
{
|
||||
pagePath: "pages/tabbar/index",
|
||||
text: "导航",
|
||||
iconPath: "",
|
||||
selectedIconPath: "",
|
||||
launchParam: [],
|
||||
auth: [],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/canteen",
|
||||
text: "食堂",
|
||||
iconPath: "/static/tabbar/canteen.png",
|
||||
selectedIconPath: "/static/tabbar/canteen-select.png",
|
||||
launchParam: ["canteen"],
|
||||
auth: [],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/canteenAnalyse",
|
||||
text: "喜好分析",
|
||||
iconPath: "/static/tabbar/canteen-analyse.png",
|
||||
selectedIconPath: "/static/tabbar/canteen-analyse-select.png",
|
||||
launchParam: ["canteen"],
|
||||
auth: [],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/selfMerchant",
|
||||
text: "自营商家",
|
||||
iconPath: "/static/tabbar/selfMerchant.png",
|
||||
selectedIconPath: "/static/tabbar/selfMerchant-select.png",
|
||||
launchParam: ["selfMerchant"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/coopMerchant",
|
||||
text: "合作商家",
|
||||
iconPath: "/static/tabbar/coopMerchant.png",
|
||||
selectedIconPath: "/static/tabbar/coopMerchant-select.png",
|
||||
launchParam: ["coopMerchant"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/onlineShop",
|
||||
text: "在线商城",
|
||||
iconPath: "/static/tabbar/online-shop.png",
|
||||
selectedIconPath: "/static/tabbar/online-shop-select.png",
|
||||
launchParam: ["onlineShop"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/prosperityShop",
|
||||
text: "共富商城",
|
||||
iconPath: "/static/tabbar/prosperity-shop.png",
|
||||
selectedIconPath: "/static/tabbar/prosperity-shop-select.png",
|
||||
launchParam: ["prosperityShop"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/cabinet",
|
||||
text: "智能柜",
|
||||
iconPath: "/static/tabbar/cabinet.png",
|
||||
selectedIconPath: "/static/tabbar/cabinet-select.png",
|
||||
launchParam: [],
|
||||
auth: ["doorAdmin"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/order",
|
||||
text: "订单",
|
||||
iconPath: "/static/tabbar/order.png",
|
||||
selectedIconPath: "/static/tabbar/order-select.png",
|
||||
launchParam: ["canteen", "selfMerchant", "onlineShop", "coopMerchant"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/flowStatistics",
|
||||
text: "流水统计",
|
||||
iconPath: "/static/tabbar/order.png",
|
||||
selectedIconPath: "/static/tabbar/order-select.png",
|
||||
launchParam: [],
|
||||
auth: ["merchant"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/individualOrder",
|
||||
text: "订单",
|
||||
iconPath: "/static/tabbar/order.png",
|
||||
selectedIconPath: "/static/tabbar/order-select.png",
|
||||
launchParam: [],
|
||||
auth: ["merchant"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/integrated",
|
||||
text: "综合服务",
|
||||
iconPath: "/static/tabbar/integrated.png",
|
||||
selectedIconPath: "/static/tabbar/integrated-select.png",
|
||||
launchParam: ["integrated"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/my",
|
||||
text: "我的",
|
||||
iconPath: "/static/tabbar/my.png",
|
||||
selectedIconPath: "/static/tabbar/my-select.png",
|
||||
launchParam: ["canteen", "selfMerchant", "onlineShop", "coopMerchant", "integrated", "prosperityShop"],
|
||||
auth: ["user", "merchant", "doorAdmin"],
|
||||
},
|
||||
]
|
||||
|
||||
// 设置tabbar
|
||||
const setTabbarItem = (index: number, item: TabbarItem, visible: boolean) => {
|
||||
uni.setTabBarItem({
|
||||
index,
|
||||
pagePath: item.pagePath,
|
||||
text: item.text,
|
||||
iconPath: item.iconPath,
|
||||
selectedIconPath: item.selectedIconPath,
|
||||
visible,
|
||||
})
|
||||
}
|
||||
|
||||
// 根据启动参数和用户角色设置tabbar
|
||||
const setTabbar = (launchParam?: string, auth?: string) => {
|
||||
if (launchParam && !auth) {
|
||||
tabbar.forEach((item, index) => {
|
||||
const visible = item.launchParam.includes(launchParam)
|
||||
setTabbarItem(index, item, visible)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!launchParam && auth) {
|
||||
tabbar.forEach((item, index) => {
|
||||
const visible = item.auth.includes(auth)
|
||||
setTabbarItem(index, item, visible)
|
||||
})
|
||||
}
|
||||
if (launchParam && auth) {
|
||||
tabbar.forEach((item, index) => {
|
||||
const visible = item.launchParam.includes(launchParam) && item.auth.includes(auth)
|
||||
setTabbarItem(index, item, visible)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async _initTabbar() {
|
||||
const launchParam = getLaunchParam()
|
||||
const appInfo = await getAppInfo()
|
||||
|
||||
// 浙政钉环境
|
||||
if (appInfo == APPENV.ZZD) {
|
||||
if (!launchParam) return uni.hideTabBar()
|
||||
|
||||
setTabbar(launchParam)
|
||||
uni.showTabBar()
|
||||
return
|
||||
}
|
||||
|
||||
// 诗画环境
|
||||
if (appInfo == APPENV.SH) {
|
||||
if (!launchParam) return uni.hideTabBar()
|
||||
|
||||
const userRole = uni.getStorageSync("userRole")
|
||||
switch (userRole) {
|
||||
case "user":
|
||||
setTabbar(launchParam, "user")
|
||||
uni.showTabBar()
|
||||
break
|
||||
case "merchant":
|
||||
setTabbar(undefined, "merchant")
|
||||
uni.showTabBar()
|
||||
break
|
||||
case "doorAdmin":
|
||||
setTabbar(undefined, "doorAdmin")
|
||||
uni.showTabBar()
|
||||
break
|
||||
default:
|
||||
uni.hideTabBar()
|
||||
uni.removeStorageSync("userRole")
|
||||
uni.showToast({ title: "用户身份未确认", icon: "none" })
|
||||
uni.reLaunch({ url: "/pages/user/userRole" })
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/sheep/scss/global.scss";
|
||||
@import url(@/uni_modules/tm-ui/css/remixicon.min.css);
|
||||
|
||||
$theme-green: #06be36;
|
||||
$theme-blue: #0094ff;
|
||||
$theme-gray: #999;
|
||||
|
||||
.botder_btn {
|
||||
border: 1px solid #999;
|
||||
color: #999;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
border-radius: 10rpx;
|
||||
padding: 8rpx 15rpx;
|
||||
}
|
||||
|
||||
.prefix_title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 8rpx;
|
||||
height: 24rpx;
|
||||
background: $theme-blue;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script lang="ts">
|
||||
import { getLaunchParam } from "@/sheep/utils/app"
|
||||
import { getAppInfo } from "@@/utils/app"
|
||||
import { APPENV } from "./sheep/constant"
|
||||
|
||||
interface TabbarItem {
|
||||
pagePath: string
|
||||
text: string
|
||||
iconPath: string
|
||||
selectedIconPath: string
|
||||
launchParam: string[]
|
||||
auth: string[]
|
||||
}
|
||||
|
||||
const tabbar: TabbarItem[] = [
|
||||
{
|
||||
pagePath: "pages/tabbar/index",
|
||||
text: "导航",
|
||||
iconPath: "",
|
||||
selectedIconPath: "",
|
||||
launchParam: [],
|
||||
auth: [],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/canteen",
|
||||
text: "食堂",
|
||||
iconPath: "/static/tabbar/canteen.png",
|
||||
selectedIconPath: "/static/tabbar/canteen-select.png",
|
||||
launchParam: ["canteen"],
|
||||
auth: [],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/canteenAnalyse",
|
||||
text: "喜好分析",
|
||||
iconPath: "/static/tabbar/canteen-analyse.png",
|
||||
selectedIconPath: "/static/tabbar/canteen-analyse-select.png",
|
||||
launchParam: ["canteen"],
|
||||
auth: [],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/selfMerchant",
|
||||
text: "自营商家",
|
||||
iconPath: "/static/tabbar/selfMerchant.png",
|
||||
selectedIconPath: "/static/tabbar/selfMerchant-select.png",
|
||||
launchParam: ["selfMerchant"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/coopMerchant",
|
||||
text: "合作商家",
|
||||
iconPath: "/static/tabbar/coopMerchant.png",
|
||||
selectedIconPath: "/static/tabbar/coopMerchant-select.png",
|
||||
launchParam: ["coopMerchant"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/onlineShop",
|
||||
text: "在线商城",
|
||||
iconPath: "/static/tabbar/online-shop.png",
|
||||
selectedIconPath: "/static/tabbar/online-shop-select.png",
|
||||
launchParam: ["onlineShop"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/prosperityShop",
|
||||
text: "共富商城",
|
||||
iconPath: "/static/tabbar/prosperity-shop.png",
|
||||
selectedIconPath: "/static/tabbar/prosperity-shop-select.png",
|
||||
launchParam: ["prosperityShop"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/cabinet",
|
||||
text: "智能柜",
|
||||
iconPath: "/static/tabbar/cabinet.png",
|
||||
selectedIconPath: "/static/tabbar/cabinet-select.png",
|
||||
launchParam: [],
|
||||
auth: ["doorAdmin"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/order",
|
||||
text: "订单",
|
||||
iconPath: "/static/tabbar/order.png",
|
||||
selectedIconPath: "/static/tabbar/order-select.png",
|
||||
launchParam: ["canteen", "selfMerchant", "onlineShop", "coopMerchant"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/flowStatistics",
|
||||
text: "流水统计",
|
||||
iconPath: "/static/tabbar/order.png",
|
||||
selectedIconPath: "/static/tabbar/order-select.png",
|
||||
launchParam: [],
|
||||
auth: ["merchant"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/individualOrder",
|
||||
text: "订单",
|
||||
iconPath: "/static/tabbar/order.png",
|
||||
selectedIconPath: "/static/tabbar/order-select.png",
|
||||
launchParam: [],
|
||||
auth: ["merchant"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/integrated",
|
||||
text: "综合服务",
|
||||
iconPath: "/static/tabbar/integrated.png",
|
||||
selectedIconPath: "/static/tabbar/integrated-select.png",
|
||||
launchParam: ["integrated"],
|
||||
auth: ["user"],
|
||||
},
|
||||
{
|
||||
pagePath: "pages/tabbar/my",
|
||||
text: "我的",
|
||||
iconPath: "/static/tabbar/my.png",
|
||||
selectedIconPath: "/static/tabbar/my-select.png",
|
||||
launchParam: ["canteen", "selfMerchant", "onlineShop", "coopMerchant", "integrated", "prosperityShop"],
|
||||
auth: ["user", "merchant", "doorAdmin"],
|
||||
},
|
||||
]
|
||||
|
||||
// 设置tabbar
|
||||
const setTabbarItem = (index: number, item: TabbarItem, visible: boolean) => {
|
||||
uni.setTabBarItem({
|
||||
index,
|
||||
pagePath: item.pagePath,
|
||||
text: item.text,
|
||||
iconPath: item.iconPath,
|
||||
selectedIconPath: item.selectedIconPath,
|
||||
visible,
|
||||
})
|
||||
}
|
||||
|
||||
// 根据启动参数和用户角色设置tabbar
|
||||
const setTabbar = (launchParam?: string, auth?: string) => {
|
||||
if (launchParam && !auth) {
|
||||
tabbar.forEach((item, index) => {
|
||||
const visible = item.launchParam.includes(launchParam)
|
||||
setTabbarItem(index, item, visible)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!launchParam && auth) {
|
||||
tabbar.forEach((item, index) => {
|
||||
const visible = item.auth.includes(auth)
|
||||
setTabbarItem(index, item, visible)
|
||||
})
|
||||
}
|
||||
if (launchParam && auth) {
|
||||
tabbar.forEach((item, index) => {
|
||||
const visible = item.launchParam.includes(launchParam) && item.auth.includes(auth)
|
||||
setTabbarItem(index, item, visible)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async _initTabbar() {
|
||||
const launchParam = getLaunchParam()
|
||||
const appInfo = await getAppInfo()
|
||||
|
||||
// 浙政钉环境
|
||||
if (appInfo == APPENV.ZZD) {
|
||||
if (!launchParam) return uni.hideTabBar()
|
||||
|
||||
setTabbar(launchParam)
|
||||
uni.showTabBar()
|
||||
return
|
||||
}
|
||||
|
||||
// 诗画环境
|
||||
if (appInfo == APPENV.SH) {
|
||||
if (!launchParam) return uni.hideTabBar()
|
||||
|
||||
const userRole = uni.getStorageSync("userRole")
|
||||
switch (userRole) {
|
||||
case "user":
|
||||
setTabbar(launchParam, "user")
|
||||
uni.showTabBar()
|
||||
break
|
||||
case "merchant":
|
||||
setTabbar(undefined, "merchant")
|
||||
uni.showTabBar()
|
||||
break
|
||||
case "doorAdmin":
|
||||
setTabbar(undefined, "doorAdmin")
|
||||
uni.showTabBar()
|
||||
break
|
||||
default:
|
||||
uni.hideTabBar()
|
||||
uni.removeStorageSync("userRole")
|
||||
uni.showToast({ title: "用户身份未确认", icon: "none" })
|
||||
uni.reLaunch({ url: "/pages/user/userRole" })
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/sheep/scss/global.scss";
|
||||
@import "@/uni_modules/tm-ui/css/remixicon.min.css";
|
||||
|
||||
$theme-green: #06be36;
|
||||
$theme-blue: #0094ff;
|
||||
$theme-gray: #999;
|
||||
|
||||
.botder_btn {
|
||||
border: 1px solid #999;
|
||||
color: #999;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
border-radius: 10rpx;
|
||||
padding: 8rpx 15rpx;
|
||||
}
|
||||
|
||||
.prefix_title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 8rpx;
|
||||
height: 24rpx;
|
||||
background: $theme-blue;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -14,9 +14,11 @@
|
||||
<image
|
||||
v-for="(img, idx) in imageList"
|
||||
:key="idx"
|
||||
:src="img.startsWith('http') ? img : filePath(img)"
|
||||
:src="img.startsWith('http') || img.startsWith('https') ? img : filePath(img)"
|
||||
class="feedback-img"
|
||||
mode="aspectFill"
|
||||
@error="handleImageError(img)"
|
||||
@load="handleImageLoad(img)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
@@ -40,36 +42,26 @@ const typeOptionsLoaded = ref(false)
|
||||
async function loadTypeOptions() {
|
||||
try {
|
||||
const res: any = await feedbackApi.getFeedbackType()
|
||||
console.log('反馈类型API响应:', res)
|
||||
if (res.code === 0 && res.data && Array.isArray(res.data)) {
|
||||
typeOptions.value = res.data.map(item => ({
|
||||
value: item.id,
|
||||
label: item.label
|
||||
}))
|
||||
console.log('处理后的反馈类型选项:', typeOptions.value)
|
||||
typeOptionsLoaded.value = true
|
||||
} else {
|
||||
console.error('获取反馈类型失败:', res.msg)
|
||||
typeOptionsLoaded.value = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取反馈类型异常:', e)
|
||||
typeOptionsLoaded.value = true
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeLabel(type) {
|
||||
console.log('获取类型标签 - 输入类型:', type, '类型:', typeof type)
|
||||
console.log('获取类型标签 - 类型选项:', typeOptions.value)
|
||||
if (!typeOptions.value.length || !type) {
|
||||
console.log('获取类型标签 - 无选项或无类型,返回:', type || '')
|
||||
return type || ''
|
||||
}
|
||||
const option = typeOptions.value.find(item => String(item.value) === String(type))
|
||||
console.log('获取类型标签 - 找到的选项:', option)
|
||||
const result = option ? option.label : type
|
||||
console.log('获取类型标签 - 最终结果:', result)
|
||||
return result
|
||||
return option ? option.label : type
|
||||
}
|
||||
|
||||
function getTypeClass(type: string) {
|
||||
@@ -108,6 +100,14 @@ function formatTime(time: string) {
|
||||
return new Date(time).toLocaleString()
|
||||
}
|
||||
|
||||
function handleImageError(img: string) {
|
||||
// 图片加载失败处理
|
||||
}
|
||||
|
||||
function handleImageLoad(img: string) {
|
||||
// 图片加载成功处理
|
||||
}
|
||||
|
||||
// 计算图片数组
|
||||
const imageList = computed(() => {
|
||||
if (!detail.value.picUrl) return []
|
||||
@@ -116,7 +116,6 @@ const imageList = computed(() => {
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
const id = options.id
|
||||
console.log('页面参数:', options)
|
||||
if (!id) {
|
||||
uni.showToast({ title: '缺少反馈ID', icon: 'none' })
|
||||
return
|
||||
@@ -127,7 +126,6 @@ onLoad(async (options: any) => {
|
||||
|
||||
// 先获取反馈详情
|
||||
const response: any = await feedbackApi.getFeedbackDetail(id)
|
||||
console.log('反馈详情响应:', response)
|
||||
|
||||
if (response.code === 0) {
|
||||
// 处理不同的数据结构
|
||||
@@ -136,11 +134,9 @@ onLoad(async (options: any) => {
|
||||
} else if (response.data && typeof response.data === 'object') {
|
||||
detail.value = response.data
|
||||
} else {
|
||||
console.error('数据结构异常:', response.data)
|
||||
uni.showToast({ title: '数据格式错误', icon: 'none' })
|
||||
return
|
||||
}
|
||||
console.log('反馈详情数据:', detail.value)
|
||||
} else {
|
||||
uni.showToast({ title: response.msg || '获取详情失败', icon: 'none' })
|
||||
return
|
||||
@@ -151,7 +147,6 @@ onLoad(async (options: any) => {
|
||||
|
||||
uni.hideLoading()
|
||||
} catch (error) {
|
||||
console.error('获取详情失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '获取详情失败', icon: 'none' })
|
||||
}
|
||||
|
||||
@@ -119,21 +119,17 @@ const canSubmit = computed(() => {
|
||||
async function loadTypeOptions() {
|
||||
try {
|
||||
const res: any = await feedbackApi.getFeedbackType()
|
||||
console.log('反馈类型API响应:', res)
|
||||
if (res.code === 0 && res.data && Array.isArray(res.data)) {
|
||||
typeOptions.value = res.data.map(item => ({
|
||||
value: item.id,
|
||||
label: item.label
|
||||
}))
|
||||
console.log('处理后的反馈类型选项:', typeOptions.value)
|
||||
typeOptionsLoaded.value = true
|
||||
} else {
|
||||
console.error('获取反馈类型失败:', res.msg)
|
||||
uni.showToast({ title: res.msg || '获取反馈类型失败', icon: 'none' })
|
||||
typeOptionsLoaded.value = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取反馈类型异常:', e)
|
||||
uni.showToast({ title: '获取反馈类型失败', icon: 'none' })
|
||||
typeOptionsLoaded.value = true
|
||||
}
|
||||
@@ -144,17 +140,11 @@ function onTypeChange(e: any) {
|
||||
}
|
||||
|
||||
function getTypeLabel(type: string) {
|
||||
console.log('列表页获取类型标签 - 输入类型:', type, '类型:', typeof type)
|
||||
console.log('列表页获取类型标签 - 类型选项:', typeOptions.value)
|
||||
if (!typeOptions.value.length || !type) {
|
||||
console.log('列表页获取类型标签 - 无选项或无类型,返回:', type || '')
|
||||
return type || ''
|
||||
}
|
||||
const option = typeOptions.value.find(item => String(item.value) === String(type))
|
||||
console.log('列表页获取类型标签 - 找到的选项:', option)
|
||||
const result = option ? option.label : type
|
||||
console.log('列表页获取类型标签 - 最终结果:', result)
|
||||
return result
|
||||
return option ? option.label : type
|
||||
}
|
||||
|
||||
function getTypeClass(type: string) {
|
||||
@@ -220,6 +210,8 @@ async function submitFeedback() {
|
||||
description.value = ''
|
||||
contact.value = ''
|
||||
typeIndex.value = 0
|
||||
// 使用 nextTick 确保在下一个 DOM 更新周期清空上传列表
|
||||
await nextTick()
|
||||
uploadList.value = []
|
||||
// 刷新列表
|
||||
loadFeedbackList()
|
||||
|
||||
@@ -1,42 +1,75 @@
|
||||
<template>
|
||||
<view class="booking-detail">
|
||||
<view class="room-info">
|
||||
<view class="room-name">{{ detail.roomName }}</view>
|
||||
<!-- 会议室信息卡片 -->
|
||||
<view class="room-card">
|
||||
<view class="room-header">
|
||||
<view class="room-name">{{ detail.roomName }}</view>
|
||||
<view class="status-badge" :class="getStatusClass(detail.checkStatus)">
|
||||
{{ detail.checkStatusText }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="room-meta">
|
||||
<text>容量:{{ detail.roomCapacity }}人</text>
|
||||
<text>位置:{{ detail.roomLocation || '未设置' }}</text>
|
||||
<view class="meta-item">
|
||||
<text class="icon">👥</text>
|
||||
<text>{{ detail.roomCapacity }}人</text>
|
||||
</view>
|
||||
<view class="meta-item">
|
||||
<text class="icon">📍</text>
|
||||
<text>{{ detail.roomLocation || '未设置' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="detail.roomEquipment" class="room-equip">
|
||||
设备:{{ detail.roomEquipment }}
|
||||
</view>
|
||||
<view v-if="detail.roomStatusText" class="room-status">
|
||||
状态:{{ detail.roomStatusText }}
|
||||
<text class="icon">🔧</text>
|
||||
<text>{{ detail.roomEquipment }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">预约信息</view>
|
||||
<view class="info-row"><text class="label">预约人:</text>{{ detail.applicantName }}</view>
|
||||
<view class="info-row"><text class="label">预约日期:</text>{{ detail.bookingDate }}</view>
|
||||
<view class="info-row"><text class="label">预约时间:</text>{{ detail.startTime }} ~ {{ detail.endTime }}</view>
|
||||
<view class="info-row"><text class="label">会议时长:</text>{{ detail.duration }}分钟</view>
|
||||
<view class="info-row"><text class="label">预约状态:</text>{{ detail.checkStatusText }}</view>
|
||||
<view class="info-row" v-if="detail.checkReason"><text class="label">审核意见:</text>{{ detail.checkReason }}</view>
|
||||
<!-- 预约信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">
|
||||
<text class="title-icon">📅</text>
|
||||
<text>预约信息</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">预约人</text>
|
||||
<text class="value">{{ detail.applicantName }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">预约日期</text>
|
||||
<text class="value">{{ detail.bookingDate }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">会议时间</text>
|
||||
<text class="value primary">{{ detail.startTime }} ~ {{ detail.endTime }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">会议时长</text>
|
||||
<text class="value">{{ detail.duration }}分钟</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="detail.checkReason">
|
||||
<text class="label">审核意见</text>
|
||||
<text class="value">{{ detail.checkReason }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">会议配置</view>
|
||||
<view class="info-row"><text class="label">会务服务:</text>{{ detail.needServiceText }}</view>
|
||||
<view class="info-row" v-if="detail.deskLayoutText"><text class="label">桌子摆放:</text>{{ detail.deskLayoutText }}</view>
|
||||
<view class="info-row" v-if="detail.description"><text class="label">备注说明:</text>{{ detail.description }}</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">系统信息</view>
|
||||
<view class="info-row"><text class="label">创建人:</text>{{ detail.createBy }}</view>
|
||||
<view class="info-row"><text class="label">创建时间:</text>{{ detail.createTime }}</view>
|
||||
<view class="info-row" v-if="detail.updateBy"><text class="label">更新人:</text>{{ detail.updateBy }}</view>
|
||||
<view class="info-row" v-if="detail.updateTime"><text class="label">更新时间:</text>{{ detail.updateTime }}</view>
|
||||
<!-- 会议配置卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">
|
||||
<text class="title-icon">⚙️</text>
|
||||
<text>会议配置</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">会务服务</text>
|
||||
<text class="value">{{ detail.needServiceText }}</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="detail.deskLayoutText">
|
||||
<text class="label">桌子摆放</text>
|
||||
<text class="value">{{ detail.deskLayoutText }}</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="detail.description">
|
||||
<text class="label">备注说明</text>
|
||||
<text class="value remark">{{ detail.description }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -48,6 +81,18 @@ import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
|
||||
const detail = ref<any>({})
|
||||
|
||||
// 获取状态样式类
|
||||
function getStatusClass(status: string) {
|
||||
const classMap: Record<string, string> = {
|
||||
'1': 'status-pending',
|
||||
'2': 'status-approved',
|
||||
'3': 'status-rejected',
|
||||
'4': 'status-cancelled',
|
||||
'5': 'status-completed'
|
||||
}
|
||||
return classMap[status] || 'status-pending'
|
||||
}
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
const id = options.id
|
||||
if (!id) return
|
||||
@@ -60,51 +105,154 @@ onLoad(async (options: any) => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.booking-detail {
|
||||
min-height: 100vh;
|
||||
background: #f5f6fa;
|
||||
padding: 24rpx;
|
||||
padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
// 会议室信息卡片
|
||||
.room-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 20rpx;
|
||||
padding: 32rpx;
|
||||
.room-info {
|
||||
background: #f7f8fa;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.25);
|
||||
|
||||
.room-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.room-name {
|
||||
font-size: 36rpx;
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 12rpx;
|
||||
color: #fff;
|
||||
flex: 1;
|
||||
}
|
||||
.room-meta {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 8rpx;
|
||||
text {
|
||||
margin-right: 32rpx;
|
||||
|
||||
.status-badge {
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
|
||||
&.status-pending {
|
||||
background: rgba(255, 193, 7, 0.9);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.status-approved {
|
||||
background: rgba(76, 175, 80, 0.9);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.status-rejected {
|
||||
background: rgba(244, 67, 54, 0.9);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.status-cancelled {
|
||||
background: rgba(158, 158, 158, 0.9);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.status-completed {
|
||||
background: rgba(33, 150, 243, 0.9);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.room-equip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.room-status {
|
||||
font-size: 24rpx;
|
||||
color: #ff6b35;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.room-meta {
|
||||
display: flex;
|
||||
gap: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.meta-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
|
||||
.icon {
|
||||
margin-right: 8rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.section {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
.info-row {
|
||||
|
||||
.room-equip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
|
||||
.icon {
|
||||
margin-right: 8rpx;
|
||||
font-size: 26rpx;
|
||||
margin-bottom: 14rpx;
|
||||
.label {
|
||||
color: #888;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 信息卡片
|
||||
.info-card {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 16rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
|
||||
.title-icon {
|
||||
margin-right: 12rpx;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 16rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
min-width: 160rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
|
||||
&.primary {
|
||||
color: #1777FF;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.remark {
|
||||
text-align: left;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<text class="modal-close" @tap="hideModal">×</text>
|
||||
</view>
|
||||
|
||||
<view class="modal-body">
|
||||
<scroll-view class="modal-body" scroll-y>
|
||||
<!-- 会务服务选择 -->
|
||||
<view class="form-item">
|
||||
<text class="form-label">是否需要会务服务</text>
|
||||
@@ -94,7 +94,7 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn cancel-btn" @tap="hideModal" :class="{ disabled: isBooking }">取消</view>
|
||||
@@ -197,10 +197,20 @@ const handleDateChange = async (index: number) => {
|
||||
await fetchTimeSlots(date)
|
||||
}
|
||||
|
||||
// 判断时间段是否已过期
|
||||
const isTimeSlotExpired = (slot: TimeSlotItem, date: string): boolean => {
|
||||
try {
|
||||
const now = new Date()
|
||||
const slotDateTime = new Date(`${date} ${slot.startTime}`)
|
||||
return slotDateTime < now
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取时间段数据
|
||||
const fetchTimeSlots = async (date: string) => {
|
||||
if (!roomId.value) {
|
||||
console.log('No roomId available for API request')
|
||||
uni.showToast({
|
||||
title: '会议室ID不存在',
|
||||
icon: 'none'
|
||||
@@ -208,26 +218,25 @@ const fetchTimeSlots = async (date: string) => {
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Making API request with roomId:', roomId.value)
|
||||
try {
|
||||
const res = await meetingRoomApi.getTimeSlots(roomId.value, date)
|
||||
console.log('Raw API response:', res)
|
||||
|
||||
const response = res as unknown as ApiResponse<TimeSlotItem[]>
|
||||
console.log('Parsed response:', response)
|
||||
|
||||
if (response.code === 0 && response.data) {
|
||||
console.log('Time slots data:', response.data)
|
||||
timeSlots.value = response.data
|
||||
// 处理时间段数据,将已过期的时间段标记为不可用
|
||||
timeSlots.value = response.data.map(slot => {
|
||||
if (isTimeSlotExpired(slot, date) && slot.status === 'free') {
|
||||
return { ...slot, status: 'disabled' as 'disabled' }
|
||||
}
|
||||
return slot
|
||||
})
|
||||
} else {
|
||||
console.error('Invalid response:', response)
|
||||
uni.showToast({
|
||||
title: response.msg || '获取时间段失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('API request failed:', error)
|
||||
uni.showToast({
|
||||
title: '获取时间段失败',
|
||||
icon: 'none'
|
||||
@@ -239,18 +248,12 @@ const fetchTimeSlots = async (date: string) => {
|
||||
const fetchDeskLayouts = async () => {
|
||||
try {
|
||||
const res = await meetingRoomApi.getMeetingDeskLayout('')
|
||||
console.log('Desk layouts response:', res)
|
||||
|
||||
const response = res as unknown as ApiResponse<any[]>
|
||||
if (response.code === 0 && response.data) {
|
||||
deskLayouts.value = response.data
|
||||
console.log('Desk layouts data:', deskLayouts.value)
|
||||
console.log('First layout item structure:', deskLayouts.value[0])
|
||||
} else {
|
||||
console.error('Failed to fetch desk layouts:', response)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('API request failed:', error)
|
||||
// 获取桌子摆放形态失败
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,29 +306,20 @@ function selectService(value: string) {
|
||||
|
||||
// 选择桌子摆放形态
|
||||
function selectLayout(layoutId: string) {
|
||||
console.log('selectLayout called with layoutId:', layoutId)
|
||||
selectedLayout.value = layoutId
|
||||
console.log('selectedLayout.value set to:', selectedLayout.value)
|
||||
}
|
||||
|
||||
// 获取选中的桌子摆放形态名称
|
||||
const getSelectedLayoutName = () => {
|
||||
console.log('getSelectedLayoutName - selectedLayout.value:', selectedLayout.value)
|
||||
console.log('getSelectedLayoutName - deskLayouts.value:', deskLayouts.value)
|
||||
|
||||
if (!selectedLayout.value) {
|
||||
console.log('No layout selected, returning 未选择')
|
||||
return '未选择'
|
||||
}
|
||||
|
||||
const selectedLayoutItem = deskLayouts.value.find(layout => layout.id === selectedLayout.value)
|
||||
console.log('Found selected layout item:', selectedLayoutItem)
|
||||
|
||||
if (selectedLayoutItem) {
|
||||
console.log('Returning layout name:', selectedLayoutItem.layoutName)
|
||||
return selectedLayoutItem.layoutName
|
||||
} else {
|
||||
console.log('Layout item not found, returning 未选择')
|
||||
return '未选择'
|
||||
}
|
||||
}
|
||||
@@ -357,8 +351,6 @@ async function confirmReserve() {
|
||||
const endSlot = timeSlots.value[selectedTime.value[selectedTime.value.length - 1]]
|
||||
|
||||
const deskLayoutName = getSelectedLayoutName()
|
||||
console.log('选中的桌子摆放形态ID:', selectedLayout.value)
|
||||
console.log('桌子摆放形态名称:', deskLayoutName)
|
||||
|
||||
const res = await meetingRoomApi.bookMeetingRoom(roomId.value, {
|
||||
date,
|
||||
@@ -370,19 +362,12 @@ async function confirmReserve() {
|
||||
need_service: needService.value,
|
||||
deskLayout: deskLayoutName
|
||||
})
|
||||
|
||||
console.log('预约接口响应:', res)
|
||||
console.log('响应类型:', typeof res)
|
||||
console.log('响应内容:', JSON.stringify(res))
|
||||
|
||||
// 处理响应数据
|
||||
const responseData = res as any
|
||||
|
||||
// 检查业务错误(HTTP 200 但 code !== 0)
|
||||
if (responseData && responseData.code !== undefined) {
|
||||
console.log('检测到响应码:', responseData.code)
|
||||
console.log('检测到响应消息:', responseData.msg)
|
||||
|
||||
if (responseData.code === 0) {
|
||||
// 成功:隐藏loading,显示成功提示
|
||||
uni.hideLoading()
|
||||
@@ -396,7 +381,6 @@ async function confirmReserve() {
|
||||
// 失败:隐藏loading,关闭弹窗,显示错误信息
|
||||
uni.hideLoading()
|
||||
isBooking.value = false
|
||||
console.log('预约失败,错误信息:', responseData.msg)
|
||||
|
||||
// 先关闭弹窗,再显示错误信息
|
||||
hideModal()
|
||||
@@ -414,7 +398,6 @@ async function confirmReserve() {
|
||||
// 响应格式异常:隐藏loading,显示错误信息
|
||||
uni.hideLoading()
|
||||
isBooking.value = false
|
||||
console.log('响应格式异常:', responseData)
|
||||
uni.showToast({
|
||||
title: '预约失败,响应格式异常',
|
||||
icon: 'none',
|
||||
@@ -425,12 +408,10 @@ async function confirmReserve() {
|
||||
// 确保在异常情况下也隐藏loading
|
||||
uni.hideLoading()
|
||||
isBooking.value = false
|
||||
console.error('预约失败:', error)
|
||||
|
||||
// 处理HTTP错误(如500错误)
|
||||
const errorData = error as any
|
||||
if (errorData?.data?.msg) {
|
||||
console.log('HTTP错误信息:', errorData.data.msg)
|
||||
uni.showToast({
|
||||
title: errorData.data.msg,
|
||||
icon: 'none',
|
||||
@@ -448,15 +429,9 @@ async function confirmReserve() {
|
||||
|
||||
// 初始化数据
|
||||
onMounted(() => {
|
||||
console.log('Detail page mounted, props:', props)
|
||||
console.log('roomId from props:', props.roomId)
|
||||
|
||||
// 从props获取roomId
|
||||
if (props.roomId) {
|
||||
roomId.value = props.roomId
|
||||
console.log('roomId set to:', roomId.value)
|
||||
} else {
|
||||
console.log('No roomId found in props')
|
||||
}
|
||||
|
||||
// 接收列表页传递的会议室信息
|
||||
@@ -464,20 +439,17 @@ onMounted(() => {
|
||||
const eventChannel = currentPage ? (currentPage as any).getOpenerEventChannel() : undefined
|
||||
if (eventChannel) {
|
||||
eventChannel.on('acceptRoomInfo', (data: any) => {
|
||||
console.log('detail.vue: Received raw room info from eventChannel:', data)
|
||||
// 字段映射
|
||||
room.value.name = data.roomName || '未知会议室'
|
||||
room.value.capacity = data.capacity || 0
|
||||
room.value.address = data.location || '未知地址'
|
||||
room.value.img = data.picUrl || '/static/meeting/default.jpg'
|
||||
room.value.tags = data.equipmentNames ? data.equipmentNames.map((eq: { name: string, quantity?: number }) => eq.quantity ? `${eq.name} x${eq.quantity}` : eq.name) : []
|
||||
console.log('detail.vue: Room.value after mapping:', room.value)
|
||||
})
|
||||
}
|
||||
|
||||
// 获取当天的时间段
|
||||
const today = getDateString(0)
|
||||
console.log('Fetching time slots for date:', today)
|
||||
fetchTimeSlots(today)
|
||||
|
||||
// 获取桌子摆放形态数据
|
||||
@@ -493,12 +465,10 @@ onMounted(() => {
|
||||
if (userInfoData.data.sysUser.userId) {
|
||||
currentUser.value.id = userInfoData.data.sysUser.userId.toString()
|
||||
}
|
||||
console.log('detail.vue: Current user name set from localStorage:', currentUser.value.name)
|
||||
console.log('detail.vue: Current user ID set from localStorage:', currentUser.value.id)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('detail.vue: Failed to parse user_info from localStorage:', e)
|
||||
// 解析用户信息失败
|
||||
}
|
||||
})
|
||||
|
||||
@@ -736,7 +706,9 @@ const goBack = () => {
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
max-height: 800rpx;
|
||||
padding: 32rpx;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
|
||||
@@ -87,33 +87,25 @@ async function fetchMeetingRooms() {
|
||||
loading.value = true
|
||||
error.value = ""
|
||||
try {
|
||||
console.log('开始获取会议室列表...')
|
||||
const res: any = await meetingRoomApi.getMeetingRoomList({ current: 1, size: 10 })
|
||||
console.log('会议室列表API响应:', res)
|
||||
if (res.code === 0) {
|
||||
meetingRooms.value = res.data.records || []
|
||||
console.log('会议室列表数据:', meetingRooms.value)
|
||||
} else {
|
||||
error.value = res.msg || '获取会议室列表失败'
|
||||
console.error('获取会议室列表失败:', res.msg)
|
||||
}
|
||||
} catch (err) {
|
||||
error.value = '网络请求失败'
|
||||
console.error('获取会议室列表异常:', err)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function goDetail(room) {
|
||||
console.log("index.vue: Navigating to detail page with room:", room)
|
||||
console.log("index.vue: Room ID being passed:", room.id)
|
||||
uni.navigateTo({
|
||||
url: `/pages/integrated/meeting/detail?roomId=${room.id}`,
|
||||
success: function (res) {
|
||||
// 通过 eventChannel 传递 room 对象
|
||||
res.eventChannel.emit("acceptRoomInfo", room)
|
||||
console.log("index.vue: Room object emitted via eventChannel:", room)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
|
||||
<!-- 预约卡片列表 -->
|
||||
<view v-if="reservationList.length">
|
||||
<view v-for="item in reservationList" :key="item.id" class="card">
|
||||
<view v-for="item in reservationList" :key="item.id" class="card">
|
||||
<view class="card-header">
|
||||
<image src="/static/icons/meeting.png" class="card-icon" />
|
||||
<text class="card-title">{{ item.title }}</text>
|
||||
<text class="card-status" :class="statusMap[item.checkStatus]?.class">{{ statusMap[item.checkStatus]?.text }}</text>
|
||||
<text class="card-status" :class="statusMap[item.checkStatus]?.class">{{ statusMap[item.checkStatus]?.text }}</text>
|
||||
<text v-if="isEnded(item)" class="tag ended">已结束</text>
|
||||
<text v-else-if="isExpired(item)" class="tag expired">已过期</text>
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<view>预约日期:{{ item.bookingDate }}</view>
|
||||
@@ -28,7 +30,8 @@
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<view class="card-btn" @tap="viewDetail(item)">查看详情</view>
|
||||
<view v-if="item.checkStatus === 1 || item.checkStatus === 2" class="card-btn cancel" @tap="cancelBooking(item)">取消预约</view>
|
||||
<view v-if="Number(item.checkStatus) === 1" class="card-btn cancel" @tap="cancelBooking(item)">取消预约</view>
|
||||
<view v-if="Number(item.checkStatus) === 2 && !isEnded(item)" class="card-btn end" @tap="endMeeting(item)">结束会议</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -96,10 +99,73 @@ function cancelBooking(item: any) {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定要取消该预约吗?",
|
||||
success: (res) => {
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
// TODO: 调用取消预约接口
|
||||
uni.showToast({ title: "已取消(待接入接口)", icon: "none" })
|
||||
try {
|
||||
uni.showLoading({ title: "处理中..." })
|
||||
const response: any = await meetingRoomApi.cancelBooking(item.id)
|
||||
uni.hideLoading()
|
||||
|
||||
if (response.code === 0) {
|
||||
uni.showToast({ title: "预约已取消", icon: "success" })
|
||||
// 刷新列表
|
||||
fetchReservations()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: response.msg || "操作失败",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "操作失败,请重试", icon: "none" })
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 是否已结束
|
||||
function isEnded(item: any) {
|
||||
return Number(item.isConfirmEnd) === 1
|
||||
}
|
||||
|
||||
// 是否已过期(当前日期大于预约日期,且未结束)
|
||||
function isExpired(item: any) {
|
||||
try {
|
||||
if (!item.bookingDate) return false
|
||||
const todayStr = new Date().toISOString().split('T')[0]
|
||||
return todayStr > item.bookingDate && !isEnded(item)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function endMeeting(item: any) {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定要结束该会议吗?",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
uni.showLoading({ title: "处理中..." })
|
||||
const response: any = await meetingRoomApi.confirmEndMeeting(item.id)
|
||||
uni.hideLoading()
|
||||
|
||||
if (response.code === 0) {
|
||||
uni.showToast({ title: "会议已结束", icon: "success" })
|
||||
// 刷新列表
|
||||
fetchReservations()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: response.msg || "操作失败",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "操作失败,请重试", icon: "none" })
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -194,6 +260,20 @@ function viewDetail(item: any) {
|
||||
.card-status.cancel {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.tag {
|
||||
margin-left: 8rpx;
|
||||
font-size: 22rpx;
|
||||
padding: 2rpx 10rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
.tag.ended {
|
||||
background: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
.tag.expired {
|
||||
background: #fff1f0;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.card-info {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
@@ -215,6 +295,10 @@ function viewDetail(item: any) {
|
||||
background: #ffeaea;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.card-btn.end {
|
||||
background: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -71,7 +71,6 @@ const urgencyOptions = [
|
||||
async function loadTypeOptions() {
|
||||
try {
|
||||
const response: any = await maintenanceApi.getFeedbackType()
|
||||
console.log('维修类型响应:', response)
|
||||
if (response.code === 0 && response.data) {
|
||||
// 处理API返回的数据格式
|
||||
if (Array.isArray(response.data)) {
|
||||
@@ -86,10 +85,8 @@ async function loadTypeOptions() {
|
||||
label: value
|
||||
}))
|
||||
}
|
||||
console.log('处理后的维修类型选项:', typeOptions.value)
|
||||
typeOptionsLoaded.value = true
|
||||
} else {
|
||||
console.error('获取维修类型失败:', response.msg)
|
||||
// 使用默认选项作为后备
|
||||
typeOptions.value = [
|
||||
{ value: '1', label: '电气设备' },
|
||||
@@ -101,7 +98,6 @@ async function loadTypeOptions() {
|
||||
typeOptionsLoaded.value = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取维修类型失败:', error)
|
||||
// 使用默认选项作为后备
|
||||
typeOptions.value = [
|
||||
{ value: '1', label: '电气设备' },
|
||||
@@ -157,7 +153,6 @@ const imageList = computed(() => {
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
const id = options.id
|
||||
console.log('维修详情页面参数:', options)
|
||||
if (!id) {
|
||||
uni.showToast({ title: '缺少维修ID', icon: 'none' })
|
||||
return
|
||||
@@ -171,18 +166,15 @@ onLoad(async (options: any) => {
|
||||
|
||||
// 再加载维修详情
|
||||
const response: any = await maintenanceApi.getRepairDetail(id)
|
||||
console.log('维修详情响应:', response)
|
||||
|
||||
if (response.code === 0 && response.data) {
|
||||
detail.value = response.data
|
||||
console.log('维修详情数据:', detail.value)
|
||||
} else {
|
||||
uni.showToast({ title: response.msg || '获取详情失败', icon: 'none' })
|
||||
}
|
||||
|
||||
uni.hideLoading()
|
||||
} catch (error) {
|
||||
console.error('获取维修详情失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '获取详情失败', icon: 'none' })
|
||||
}
|
||||
|
||||
@@ -156,7 +156,6 @@ function beforeComplete(uploadFile: any) {
|
||||
async function loadTypeOptions() {
|
||||
try {
|
||||
const response: any = await maintenanceApi.getFeedbackType()
|
||||
console.log('维修类型响应:', response)
|
||||
if (response.code === 0 && response.data) {
|
||||
// 处理API返回的数据格式
|
||||
if (Array.isArray(response.data)) {
|
||||
@@ -171,10 +170,8 @@ async function loadTypeOptions() {
|
||||
label: value
|
||||
}))
|
||||
}
|
||||
console.log('处理后的维修类型选项:', typeOptions.value)
|
||||
typeOptionsLoaded.value = true
|
||||
} else {
|
||||
console.error('获取维修类型失败:', response.msg)
|
||||
// 使用默认选项作为后备
|
||||
typeOptions.value = [
|
||||
{ value: 1, label: '电气设备' },
|
||||
@@ -186,7 +183,6 @@ async function loadTypeOptions() {
|
||||
typeOptionsLoaded.value = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取维修类型失败:', error)
|
||||
// 使用默认选项作为后备
|
||||
typeOptions.value = [
|
||||
{ value: 1, label: '电气设备' },
|
||||
@@ -270,9 +266,7 @@ async function submitRepair() {
|
||||
urgency: String(urgencyOptions[urgencyIndex.value].value),
|
||||
maintainType: typeOptions.value[typeIndex.value].value
|
||||
}
|
||||
console.log('提交的维修数据:', data)
|
||||
const response: any = await maintenanceApi.submitRepair(data)
|
||||
console.log('维修提交响应:', response)
|
||||
uni.hideLoading()
|
||||
if (response.code === 0) {
|
||||
uni.showToast({ title: '提交成功', icon: 'success' })
|
||||
@@ -281,9 +275,11 @@ async function submitRepair() {
|
||||
location.value = ''
|
||||
description.value = ''
|
||||
dateFound.value = ''
|
||||
uploadFileUrl.value = []
|
||||
typeIndex.value = -1
|
||||
urgencyIndex.value = 0
|
||||
// 使用 nextTick 确保在下一个 DOM 更新周期清空上传列表
|
||||
await nextTick()
|
||||
uploadFileUrl.value = []
|
||||
// 刷新列表
|
||||
if (activeTab.value === 1) {
|
||||
loadRepairList()
|
||||
@@ -292,7 +288,6 @@ async function submitRepair() {
|
||||
uni.showToast({ title: response.msg || '提交失败', icon: 'none' })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('维修提交失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '提交失败', icon: 'none' })
|
||||
}
|
||||
|
||||
@@ -163,8 +163,8 @@ const query = (page: number, pagesize: number) => {
|
||||
pageHook.startPage(page, pagesize, false, state.params)
|
||||
}
|
||||
|
||||
const onTabChange = (e: number) => {
|
||||
state.params.type = e
|
||||
const onTabChange = (index: number, value: number) => {
|
||||
state.params.type = value
|
||||
pageRef.value.reload(true)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ onLoad(async () => {
|
||||
app._initTabbar()
|
||||
|
||||
try {
|
||||
const res: any = await merchantApi.selectCatgory({})
|
||||
const res: any = await merchantApi.selectCatgory({ current: 1, size: 99999 })
|
||||
if (res.code == 0) {
|
||||
state.tabs = state.tabs.concat(res.data)
|
||||
} else {
|
||||
|
||||
@@ -86,6 +86,10 @@ const jumpByParam = async () => {
|
||||
uni.setStorageSync("launchParam", launchParam)
|
||||
uni.switchTab({ url: "/pages/tabbar/integrated" })
|
||||
break
|
||||
case "prosperityShop": // 共富商城
|
||||
uni.setStorageSync("launchParam", launchParam)
|
||||
uni.switchTab({ url: "/pages/tabbar/prosperityShop" })
|
||||
break
|
||||
default:
|
||||
uni.hideTabBar()
|
||||
break
|
||||
|
||||
@@ -95,6 +95,16 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
function goPage(item) {
|
||||
// 访客邀约功能正在开发中
|
||||
// if (item.name === "visitor") {
|
||||
// uni.showToast({
|
||||
// title: "访客邀约功能正在开发中",
|
||||
// icon: "none",
|
||||
// duration: 2000,
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
if (item.url) {
|
||||
uni.navigateTo({ url: item.url })
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export default {
|
||||
description: string;
|
||||
attendees: string[];
|
||||
need_service?: string;
|
||||
desk_layout?: string;
|
||||
deskLayout?: string;
|
||||
}) =>
|
||||
request({
|
||||
url: `/integrated/meetingRoom/${roomId}/book`,
|
||||
@@ -69,6 +69,24 @@ export default {
|
||||
method: 'GET',
|
||||
}),
|
||||
|
||||
/**
|
||||
* 确认结束会议
|
||||
*/
|
||||
confirmEndMeeting: (bookingId: string) =>
|
||||
request({
|
||||
url: `/integrated/meetingBooking/app/confirm-end-meeting/${bookingId}`,
|
||||
method: 'POST',
|
||||
}),
|
||||
|
||||
/**
|
||||
* 取消预约
|
||||
*/
|
||||
cancelBooking: (bookingId: string) =>
|
||||
request({
|
||||
url: `/integrated/meetingRoom/app/cancel-booking/${bookingId}`,
|
||||
method: 'POST',
|
||||
}),
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
<tm-button
|
||||
class="day-time-button"
|
||||
size="m"
|
||||
:color="selectedTimePointIndex == index ? '' : 'info'"
|
||||
v-for="(item, index) in dayTimePointList"
|
||||
:key="index"
|
||||
@click="selectTimePoint(item, index)"
|
||||
:color="selectedTimePointIndex == item.index ? '' : 'info'"
|
||||
:disabled="item.disabled"
|
||||
v-for="item in availableTimePoints"
|
||||
:key="item.index"
|
||||
@click="selectTimePoint(item.time, item.index)"
|
||||
>
|
||||
{{ item.slice(0, 5) }}
|
||||
{{ item.time.slice(0, 5) }}
|
||||
</tm-button>
|
||||
</view>
|
||||
<view class="px-20rpx py-2 flex justify-between">
|
||||
@@ -56,6 +57,17 @@ const getLast7DaysWeek = (): { week: string; date: string; fullDate: string }[]
|
||||
return result
|
||||
}
|
||||
|
||||
// 判断时间是否已过期
|
||||
const isTimePast = (dateStr: string, timeStr: string): boolean => {
|
||||
try {
|
||||
const now = new Date()
|
||||
const selectedDateTime = new Date(`${dateStr} ${timeStr}`)
|
||||
return selectedDateTime < now
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 生成时间点列表(8:00-18:00,每半小时一个时间点)
|
||||
const dayTimePointList = computed(() => {
|
||||
const times: string[] = []
|
||||
@@ -67,6 +79,15 @@ const dayTimePointList = computed(() => {
|
||||
return times
|
||||
})
|
||||
|
||||
// 过滤出可用的时间点(未过期的)
|
||||
const availableTimePoints = computed(() => {
|
||||
return dayTimePointList.value.map((time, index) => ({
|
||||
time,
|
||||
index,
|
||||
disabled: isTimePast(selectedDateValue.value.fullDate, time)
|
||||
}))
|
||||
})
|
||||
|
||||
const selectedDateIndex = ref(0)
|
||||
const selectedDateValue = ref<{ week: string; date: string; fullDate: string }>(getLast7DaysWeek()[0])
|
||||
const selectedTimePointIndex = ref(0)
|
||||
@@ -80,6 +101,11 @@ const selectDate = (value: { week: string; date: string; fullDate: string }, ind
|
||||
|
||||
// 选择时间点
|
||||
const selectTimePoint = (value: string, index: number) => {
|
||||
// 检查是否已过期
|
||||
if (isTimePast(selectedDateValue.value.fullDate, value)) {
|
||||
uni.showToast({ title: '不能选择过去的时间', icon: 'none' })
|
||||
return
|
||||
}
|
||||
selectedTimePointValue.value = value
|
||||
selectedTimePointIndex.value = index
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user