Compare commits
No commits in common. "dev" and "main" have entirely different histories.
|
|
@ -0,0 +1,14 @@
|
|||
import http from '@/http/api.js'
|
||||
|
||||
// 获取验证码
|
||||
const captcha = (data) => {
|
||||
return http.request({
|
||||
url: '/api/blade-auth/oauth/captcha',
|
||||
method: 'GET',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
captcha,
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import http from '@/http/api.js'
|
||||
|
||||
// 获取通知公告列表
|
||||
export const getList = (params) => {
|
||||
return http.request({
|
||||
url: '/api/blade-desk/notice/list',
|
||||
method: 'GET',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export const remove = (ids) => {
|
||||
return http.request({
|
||||
url: '/api/blade-desk/notice/remove',
|
||||
method: 'post',
|
||||
params: {
|
||||
ids,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const add = (row) => {
|
||||
return http.request({
|
||||
url: '/api/blade-desk/notice/submit',
|
||||
method: 'post',
|
||||
data: row
|
||||
})
|
||||
}
|
||||
|
||||
export const update = (row) => {
|
||||
return http.request({
|
||||
url: '/api/blade-desk/notice/submit',
|
||||
method: 'post',
|
||||
data: row
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
import http from '@/http/api.js'
|
||||
|
||||
/**
|
||||
* 获取部门列表
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const deptList = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-system/dept/list-page',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取事项列表
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const itemList = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-biz/item/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 预约须知
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const noticeData = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-noticeinfo/noticeInfo/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取可用日历
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const availableDate = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-bookingdate/bookingDate/available-week-dates',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询用户信息
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const getUserInfo = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-system/user/info',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 提交预约
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const submit = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-biz/booking/submit-booking',
|
||||
method: 'POST',
|
||||
data: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询我的预约
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const myReserve = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-biz/booking/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消预约
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const cancel = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-biz/booking/cancel',
|
||||
method: 'POST',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const getDetail = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-biz/booking/detail',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取是否无感取号成功
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const getIsSuccessTicket = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-onlineticket/onlineTicket/getByYyNo',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
253
api/ticket.js
|
|
@ -1,253 +0,0 @@
|
|||
import http from '@/http/api.js'
|
||||
|
||||
// ==================== 自助取号机接口 ====================
|
||||
|
||||
/**
|
||||
* 主题取号列表
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const getThemeList = params => {
|
||||
return http.request({
|
||||
url: 'api/blade-subject/subject/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 事项列表
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const getBusinessList = params => {
|
||||
return http.request({
|
||||
url: 'api/blade-item/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 历史取号列表
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export const getHistoryList = params => {
|
||||
return http.request({
|
||||
url: 'api/blade-queuerecord/queueRecord/history',
|
||||
method: 'GET',
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取号
|
||||
* @param {*} data { applicantName, applicantIdCard, itemId, windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const takeNumber = data => {
|
||||
return http.request({
|
||||
url: 'api/blade-queuerecord/queueRecord/take-number',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 事项详情
|
||||
* @param {*} params { id }
|
||||
* @returns
|
||||
*/
|
||||
export const getItemDetail = params => {
|
||||
return http.request({
|
||||
url: 'api/blade-item/detail',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
// ==================== 叫号机窗口端接口 ====================
|
||||
|
||||
/**
|
||||
* 获取可选窗口列表
|
||||
* @param {*} params { status, serviceStatus, current, size }
|
||||
* @returns
|
||||
*/
|
||||
export const getWindowList = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-windows/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
status: 1,
|
||||
serviceStatus: 1,
|
||||
current: 1,
|
||||
size: 100,
|
||||
...params
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 选择窗口
|
||||
* @param {*} data { windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const selectWindow = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-windows/select-window',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 窗口工作台(获取当前叫号和等候人数)
|
||||
* @param {*} params { windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const getWindowWorkbench = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/window-workbench',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 呼叫下一位
|
||||
* @param {*} data { windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const callNext = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/call-next',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 重呼
|
||||
* @param {*} data { recordId, windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const recall = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/recall',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 开始办理
|
||||
* @param {*} data { recordId, windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const startHandle = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/start-handle',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 完成办理
|
||||
* @param {*} data { recordId, windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const finishHandle = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/finish',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 过号
|
||||
* @param {*} data { recordId, windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const passRecord = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/pass',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 转移窗口
|
||||
* @param {*} data { recordId, windowId, targetWindowId }
|
||||
* @returns
|
||||
*/
|
||||
export const transferRecord = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/transfer',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 挂起窗口
|
||||
* @param {*} data { windowId, reason }
|
||||
* @returns
|
||||
*/
|
||||
export const suspendWindow = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-windows/suspend',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 恢复窗口
|
||||
* @param {*} data { windowId }
|
||||
* @returns
|
||||
*/
|
||||
export const resumeWindow = data => {
|
||||
return http.request({
|
||||
url: '/api/blade-windows/resume',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 窗口统计
|
||||
* @param {*} params { windowId, date }
|
||||
* @returns
|
||||
*/
|
||||
export const getWindowStat = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/window-stat',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
// ==================== 大屏展示接口 ====================
|
||||
|
||||
/**
|
||||
* 大屏展示(当前呼叫 + 等候队列)
|
||||
* @param {*} params { calledSize, waitingSize }
|
||||
* @returns
|
||||
*/
|
||||
export const getDisplayScreen = params => {
|
||||
return http.request({
|
||||
url: '/api/blade-queuerecord/queueRecord/display-screen',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 顶部标题栏 -->
|
||||
<view class="header">
|
||||
<text class="header-left">环江毛南族自治县政务服务中心</text>
|
||||
<text class="header-center">自助取号机</text>
|
||||
<view class="btn-group">
|
||||
<view class="btn" v-if="backBtn" @click="back">
|
||||
<img src="../../static/images/home/back_icon.png" alt="" />
|
||||
<text class="btn-text">返回</text>
|
||||
</view>
|
||||
<view class="btn" v-if="logoutBtn" @click="logout">
|
||||
<img src="../../static/images/home/logout_icon.png" alt="" />
|
||||
<text class="btn-text">退出</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 主体内容区 -->
|
||||
<view class="main">
|
||||
<slot name="main"></slot>
|
||||
</view>
|
||||
|
||||
<!-- 底部状态栏 -->
|
||||
<view class="footer">
|
||||
<text class="footer-left">本机编号: YJS0001</text>
|
||||
<text class="footer-right">{{ currentTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
backBtn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
logoutBtn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentTime: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updateTime()
|
||||
setInterval(() => {
|
||||
this.updateTime()
|
||||
}, 1000)
|
||||
// APP端强制横屏
|
||||
// #ifdef APP-PLUS
|
||||
plus.screen.lockOrientation('landscape-primary')
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
updateTime() {
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(now.getDate()).padStart(2, '0')
|
||||
const hours = String(now.getHours()).padStart(2, '0')
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0')
|
||||
this.currentTime = `${year}年${month}月${day}日 ${hours}:${minutes}:${seconds}`
|
||||
},
|
||||
back() {
|
||||
this.$emit('handleBack')
|
||||
},
|
||||
logout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出吗?',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
// 清空存储的身份证号
|
||||
uni.removeStorageSync('idcard')
|
||||
uni.reLaunch({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 全屏自适应容器 - viewport弹性布局 */
|
||||
.container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* 顶部标题栏 */
|
||||
.header {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 22vh;
|
||||
background: url('../../static/images/home/top_bg.png');
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
padding: 3vh 4% 0;
|
||||
border-radius: 0 0 2% 2%;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
color: #fff;
|
||||
font-size: 2.5vw;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-center {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 3.2vh;
|
||||
transform: translateX(-50%);
|
||||
color: #fff;
|
||||
font-size: 2.5vw;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
position: absolute;
|
||||
right: 4%;
|
||||
top: 3.2vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 1vw;
|
||||
width: 8.5vw;
|
||||
height: 5.5vh;
|
||||
border-radius: 3vh;
|
||||
background: #fff;
|
||||
font-size: 1.6vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
|
||||
img {
|
||||
margin-right: 0.8vw;
|
||||
width: 2vw;
|
||||
height: 2vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 主体内容区 - 自动占满剩余空间 */
|
||||
.main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: url('../../static/images/home/bg.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
/* 底部状态栏 */
|
||||
.footer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 7vh;
|
||||
background: url('../../static/images/home/footer_bg.png');
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 3%;
|
||||
border-radius: 2% 2% 0 0;
|
||||
}
|
||||
|
||||
.footer-left,
|
||||
.footer-right {
|
||||
color: #fff;
|
||||
font-size: 2vw;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "环江取号机",
|
||||
"name": "住房保障预约",
|
||||
"appid": "__UNI__8FD82FF",
|
||||
"description": "",
|
||||
"versionName": "2.0.0",
|
||||
|
|
@ -104,6 +104,11 @@
|
|||
},
|
||||
"h5": {
|
||||
"template": "template.h5.html",
|
||||
"publicPath": "/housingAssuranceBookingMobile/",
|
||||
"router": {
|
||||
"mode": "hash",
|
||||
"base": "/housingAssuranceBookingMobile"
|
||||
},
|
||||
"optimization": {
|
||||
"treeShaking": {
|
||||
"enable": true
|
||||
|
|
@ -112,12 +117,18 @@
|
|||
"devServer": {
|
||||
"proxy": {
|
||||
"/api": {
|
||||
"target": "http://192.168.3.130:8079",
|
||||
"target": "http://192.168.3.111:8181",
|
||||
// "target" : "http://192.168.3.100:2891",
|
||||
//"target" : "https://rider.bladex.vip/api",
|
||||
"pathRewrite": {
|
||||
"^/api": "/"
|
||||
}
|
||||
},
|
||||
"/epoint-web-cs": {
|
||||
"target": "https://gxqzzfbzzx.cn",
|
||||
"pathRewrite": {
|
||||
"^/epoint-web-cs": "/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": ""
|
||||
|
|
|
|||
47
pages.json
|
|
@ -5,9 +5,9 @@
|
|||
},
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/home/chooseMachine",
|
||||
"path": "pages/loading/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "选择机器类别",
|
||||
"navigationBarTitleText": "云预约",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
|
|
@ -15,76 +15,59 @@
|
|||
{
|
||||
"path": "pages/home/home",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自助取号机",
|
||||
"navigationBarTitleText": "云预约",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/ticket",
|
||||
"path": "pages/reserve/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自助取号机",
|
||||
"navigationBarTitleText": "网上预约",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/theme",
|
||||
"path": "pages/reserve/notice",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自助取号机",
|
||||
"navigationBarTitleText": "预约须知",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/dept",
|
||||
"path": "pages/reserve/timeSelect",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自助取号机",
|
||||
"navigationBarTitleText": "预约时间",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/businessList",
|
||||
"path": "pages/reserve/confirm",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自助取号机",
|
||||
"navigationBarTitleText": "预约确认",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/guide",
|
||||
"path": "pages/myReserve/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自助取号机",
|
||||
"navigationBarTitleText": "我的预约",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/callTicket/chooseWindow",
|
||||
"path": "pages/myReserve/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "选择叫号机窗口",
|
||||
"navigationBarTitleText": "预约详情",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/callTicket/callTicket",
|
||||
"style": {
|
||||
"navigationBarTitleText": "叫号机",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/screen/screen",
|
||||
"style": {
|
||||
"navigationBarTitleText": "公告屏",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,747 +0,0 @@
|
|||
<template>
|
||||
<!-- 外层容器,使用 vw/vh 自适应屏幕 -->
|
||||
<view class="wrap">
|
||||
<!-- 顶部蓝色头部 -->
|
||||
<view class="header-bar">
|
||||
<view class="header-left">
|
||||
<text class="win-no">窗口号:{{ windowName }}</text>
|
||||
<view class="user-dept">
|
||||
<text>{{ handlerUserName }}</text>
|
||||
<text>{{ handlerDeptName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="exit-btn" @click="handleExit">
|
||||
<image class="icon-exit" src="../../static/images/home/logout_icon.png" />
|
||||
<text>退出</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 中间内容区域 -->
|
||||
<view class="content-box">
|
||||
<view class="item-col">
|
||||
<text class="col-title">当前叫号</text>
|
||||
<text class="call-no">{{ currentCallNo }}</text>
|
||||
</view>
|
||||
<view class="item-col">
|
||||
<text class="col-title">当前等候</text>
|
||||
<text class="wait-num">{{ waitingCount }}人</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部功能按钮区 -->
|
||||
<view class="btn-group">
|
||||
<view class="btn-item green" @click="handleCall" :class="{ disabled: callDisabled }">
|
||||
<image class="btn-icon" src="../../static/images/takeTicket/hj_icon.png" mode="aspectFit" />
|
||||
<text>呼叫</text>
|
||||
</view>
|
||||
<view class="btn-item blue" @click="handleReCall" :class="{ disabled: recallDisabled }">
|
||||
<image class="btn-icon" src="../../static/images/takeTicket/ch_icon.png" mode="aspectFit" />
|
||||
<text>重呼</text>
|
||||
</view>
|
||||
<view class="btn-item sky" @click="handleTransfer" :class="{ disabled: transferDisabled }">
|
||||
<image class="btn-icon" src="../../static/images/takeTicket/zy_icon.png" mode="aspectFit" />
|
||||
<text>转移</text>
|
||||
</view>
|
||||
<view class="btn-item orange" @click="handlePass" :class="{ disabled: passDisabled }">
|
||||
<image class="btn-icon" src="../../static/images/takeTicket/gh_icon.png" mode="aspectFit" />
|
||||
<text>过号</text>
|
||||
</view>
|
||||
<view class="btn-item red" @click="handleSuspend" v-if="serviceStatus === 1">
|
||||
<image class="btn-icon" src="../../static/images/takeTicket/gq_icon.png" mode="aspectFit" />
|
||||
<text>挂起</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 挂起遮罩层 -->
|
||||
<view class="suspend-overlay" v-if="serviceStatus === 2">
|
||||
<text class="suspend-tip">窗口已挂起,无法进行叫号操作</text>
|
||||
<view class="resume-btn" @click="handleResume">
|
||||
<image class="resume-btn-icon" src="../../static/images/takeTicket/hj_icon.png" mode="aspectFit" />
|
||||
<text class="resume-btn-text">恢复</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 转移弹窗:选择目标窗口 -->
|
||||
<view class="transfer-mask" v-if="showTransfer" @click="showTransfer = false">
|
||||
<view class="transfer-dialog" @click.stop>
|
||||
<text class="dialog-title">请选择目标窗口</text>
|
||||
<scroll-view class="dialog-list" scroll-y>
|
||||
<view class="transfer-item" v-for="win in targetWindowList" :key="win.id" @click="confirmTransfer(win)">
|
||||
<text class="transfer-name">{{ win.windowName }}</text>
|
||||
</view>
|
||||
<view class="dialog-empty" v-if="targetWindowList.length === 0">
|
||||
<text>暂无可转移的窗口</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="dialog-cancel" @click="showTransfer = false">
|
||||
<text>取消</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getWindowWorkbench, callNext, recall, transferRecord, passRecord, suspendWindow, resumeWindow, getWindowList, finishHandle } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
name: 'CallWindow',
|
||||
data() {
|
||||
return {
|
||||
// 窗口信息(从本地存储读取)
|
||||
windowId: '',
|
||||
windowName: '',
|
||||
serviceStatus: 1, // 1=接号中, 2=挂起中
|
||||
handlerUserName: '',
|
||||
handlerDeptName: '',
|
||||
handlerUserId: '',
|
||||
|
||||
// 当前叫号信息
|
||||
currentRecord: null, // 当前叫号记录对象
|
||||
waitingCount: 0, // 等候人数
|
||||
currentDeptName: '', // 当前办理的部门名称
|
||||
|
||||
// 转移弹窗
|
||||
showTransfer: false,
|
||||
targetWindowList: [],
|
||||
|
||||
// 操作锁(防止重复点击)
|
||||
actionLock: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
// 当前叫号显示
|
||||
currentCallNo() {
|
||||
return this.currentRecord ? this.currentRecord.queueNo : '----'
|
||||
},
|
||||
|
||||
// 按钮禁用逻辑:挂起中全部禁用操作按钮
|
||||
suspended() {
|
||||
return this.serviceStatus === 2
|
||||
},
|
||||
|
||||
// 呼叫按钮:挂起中 或 等候人数为0 或 操作锁时禁用
|
||||
callDisabled() {
|
||||
return this.suspended || this.waitingCount === 0 || this.actionLock
|
||||
},
|
||||
|
||||
// 重呼按钮:挂起中 或 无当前记录 或 状态不是已叫号/办理中 时禁用
|
||||
recallDisabled() {
|
||||
if (this.suspended || !this.currentRecord || this.actionLock) return true
|
||||
return ![2, 7].includes(this.currentRecord.status)
|
||||
},
|
||||
|
||||
// 转移按钮:挂起中 或 无当前记录时禁用
|
||||
transferDisabled() {
|
||||
return this.suspended || !this.currentRecord || this.actionLock
|
||||
},
|
||||
|
||||
// 过号按钮:挂起中 或 无当前记录 或 状态不是已叫号/办理中 时禁用
|
||||
passDisabled() {
|
||||
if (this.suspended || !this.currentRecord || this.actionLock) return true
|
||||
return ![2, 7].includes(this.currentRecord.status)
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 读取窗口信息
|
||||
const winInfo = uni.getStorageSync('windowInfo')
|
||||
if (!winInfo || !winInfo.windowId) {
|
||||
uni.showToast({ title: '请先选择窗口', icon: 'none' })
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({ url: '/pages/callTicket/chooseWindow' })
|
||||
}, 1000)
|
||||
return
|
||||
}
|
||||
|
||||
this.windowId = winInfo.windowId
|
||||
this.windowName = winInfo.windowName
|
||||
this.serviceStatus = winInfo.serviceStatus || 1
|
||||
this.handlerUserName = winInfo.handlerUserName || ''
|
||||
this.handlerDeptName = winInfo.handlerDeptName || ''
|
||||
this.handlerUserId = winInfo.handlerUserId || ''
|
||||
|
||||
// 首次加载工作台
|
||||
this.fetchWorkbench()
|
||||
},
|
||||
|
||||
methods: {
|
||||
// ========== 数据获取 ==========
|
||||
|
||||
// 获取窗口工作台数据
|
||||
async fetchWorkbench() {
|
||||
try {
|
||||
const res = await getWindowWorkbench({ windowId: this.windowId })
|
||||
if (res.success && res.data) {
|
||||
const data = res.data
|
||||
// 更新窗口状态
|
||||
this.serviceStatus = data.serviceStatus
|
||||
this.waitingCount = data.waitingCount || 0
|
||||
this.currentRecord = data.currentRecord || null
|
||||
|
||||
// 同步更新本地存储中的窗口状态
|
||||
const winInfo = uni.getStorageSync('windowInfo') || {}
|
||||
winInfo.serviceStatus = data.serviceStatus
|
||||
uni.setStorageSync('windowInfo', winInfo)
|
||||
|
||||
// 提取部门名称
|
||||
if (data.currentRecord && data.currentRecord.itemDeptName) {
|
||||
this.currentDeptName = data.currentRecord.itemDeptName
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取工作台数据失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 操作后刷新
|
||||
async refreshAfterAction(delay = 500) {
|
||||
await new Promise(resolve => setTimeout(resolve, delay))
|
||||
await this.fetchWorkbench()
|
||||
},
|
||||
|
||||
// ========== 按钮操作 ==========
|
||||
|
||||
// 退出
|
||||
handleExit() {
|
||||
uni.showModal({
|
||||
title: '确认退出',
|
||||
content: '确定要退出当前窗口吗?退出后需重新选择窗口。',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('windowInfo')
|
||||
uni.redirectTo({ url: '/pages/callTicket/chooseWindow' })
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 呼叫下一位(自动完成当前记录)
|
||||
async handleCall() {
|
||||
if (this.callDisabled) return
|
||||
this.actionLock = true
|
||||
|
||||
// 如果当前有记录,先自动完成
|
||||
if (this.currentRecord) {
|
||||
uni.showLoading({ title: '完成当前办理...', mask: true })
|
||||
try {
|
||||
await finishHandle({
|
||||
recordId: this.currentRecord.id,
|
||||
windowId: this.windowId
|
||||
})
|
||||
} catch (e) {
|
||||
// 完成失败不阻塞,继续呼叫(后端可能已处理)
|
||||
console.error('自动完成失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
uni.showLoading({ title: '呼叫中...', mask: true })
|
||||
try {
|
||||
const res = await callNext({ windowId: this.windowId })
|
||||
if (res.success && res.data) {
|
||||
this.currentRecord = res.data
|
||||
this.waitingCount = Math.max(0, this.waitingCount - 1)
|
||||
if (res.data.itemDeptName) {
|
||||
this.currentDeptName = res.data.itemDeptName
|
||||
}
|
||||
uni.showToast({ title: `已呼叫 ${res.data.queueNo}`, icon: 'success', duration: 1500 })
|
||||
await this.refreshAfterAction(1000)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('呼叫失败', e)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
this.actionLock = false
|
||||
}
|
||||
},
|
||||
|
||||
// 重呼
|
||||
async handleReCall() {
|
||||
if (this.recallDisabled) return
|
||||
if (!this.currentRecord) return
|
||||
|
||||
this.actionLock = true
|
||||
uni.showLoading({ title: '重呼中...', mask: true })
|
||||
try {
|
||||
const res = await recall({
|
||||
recordId: this.currentRecord.id,
|
||||
windowId: this.windowId
|
||||
})
|
||||
if (res.success && res.data) {
|
||||
this.currentRecord = res.data
|
||||
uni.showToast({ title: `已重呼 ${res.data.queueNo}`, icon: 'success', duration: 1500 })
|
||||
await this.refreshAfterAction()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('重呼失败', e)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
this.actionLock = false
|
||||
}
|
||||
},
|
||||
|
||||
// 转移 - 打开目标窗口选择弹窗
|
||||
async handleTransfer() {
|
||||
if (this.transferDisabled) return
|
||||
// 获取可选目标窗口(排除自身,只选启用未挂起的)
|
||||
uni.showLoading({ title: '加载窗口...', mask: true })
|
||||
try {
|
||||
const res = await getWindowList({ status: 1, serviceStatus: 1 })
|
||||
if (res.success && res.data) {
|
||||
const allWindows = res.data.records || []
|
||||
this.targetWindowList = allWindows.filter(w => w.id !== this.windowId)
|
||||
if (this.targetWindowList.length === 0) {
|
||||
uni.showToast({ title: '暂无可转移的窗口', icon: 'none' })
|
||||
return
|
||||
}
|
||||
this.showTransfer = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取窗口列表失败', e)
|
||||
uni.showToast({ title: '获取窗口列表失败', icon: 'none' })
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
},
|
||||
|
||||
// 确认转移
|
||||
async confirmTransfer(win) {
|
||||
if (!this.currentRecord) return
|
||||
this.showTransfer = false
|
||||
this.actionLock = true
|
||||
uni.showLoading({ title: '转移中...', mask: true })
|
||||
try {
|
||||
const res = await transferRecord({
|
||||
recordId: this.currentRecord.id,
|
||||
windowId: this.windowId,
|
||||
targetWindowId: win.id
|
||||
})
|
||||
if (res.success) {
|
||||
uni.showToast({ title: `已转移至 ${win.windowName}`, icon: 'success', duration: 1500 })
|
||||
await this.refreshAfterAction(1000)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('转移失败', e)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
this.actionLock = false
|
||||
}
|
||||
},
|
||||
|
||||
// 过号
|
||||
async handlePass() {
|
||||
if (this.passDisabled) return
|
||||
if (!this.currentRecord) return
|
||||
|
||||
uni.showModal({
|
||||
title: '确认过号',
|
||||
content: `确定将 ${this.currentRecord.queueNo} 标记为过号吗?`,
|
||||
success: async modalRes => {
|
||||
if (!modalRes.confirm) return
|
||||
this.actionLock = true
|
||||
uni.showLoading({ title: '处理中...', mask: true })
|
||||
try {
|
||||
const res = await passRecord({
|
||||
recordId: this.currentRecord.id,
|
||||
windowId: this.windowId
|
||||
})
|
||||
if (res.success) {
|
||||
uni.showToast({ title: '已标记过号', icon: 'success', duration: 1500 })
|
||||
await this.refreshAfterAction(1000)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('过号失败', e)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
this.actionLock = false
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 挂起 - 直接挂起
|
||||
async handleSuspend() {
|
||||
this.actionLock = true
|
||||
uni.showLoading({ title: '挂起中...', mask: true })
|
||||
try {
|
||||
const res = await suspendWindow({
|
||||
windowId: this.windowId,
|
||||
reason: '临时离岗'
|
||||
})
|
||||
if (res.success && res.data) {
|
||||
this.serviceStatus = res.data.serviceStatus
|
||||
|
||||
// 同步更新本地存储
|
||||
const winInfo = uni.getStorageSync('windowInfo') || {}
|
||||
winInfo.serviceStatus = res.data.serviceStatus
|
||||
uni.setStorageSync('windowInfo', winInfo)
|
||||
|
||||
uni.showToast({ title: '窗口已挂起', icon: 'success', duration: 1500 })
|
||||
await this.refreshAfterAction()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('挂起失败', e)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
this.actionLock = false
|
||||
}
|
||||
},
|
||||
|
||||
// 恢复窗口
|
||||
async handleResume() {
|
||||
this.actionLock = true
|
||||
uni.showLoading({ title: '恢复中...', mask: true })
|
||||
try {
|
||||
const res = await resumeWindow({ windowId: this.windowId })
|
||||
if (res.success && res.data) {
|
||||
this.serviceStatus = res.data.serviceStatus
|
||||
|
||||
// 同步更新本地存储
|
||||
const winInfo = uni.getStorageSync('windowInfo') || {}
|
||||
winInfo.serviceStatus = res.data.serviceStatus
|
||||
uni.setStorageSync('windowInfo', winInfo)
|
||||
|
||||
uni.showToast({ title: '窗口已恢复', icon: 'success', duration: 1500 })
|
||||
await this.refreshAfterAction()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('恢复失败', e)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
this.actionLock = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: url('../../static/images/home/bg.png') no-repeat center center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/* 顶部头部 */
|
||||
.header-bar {
|
||||
width: 100%;
|
||||
background-color: rgba(19, 114, 255, 1);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.944vh 2.083vw 1.296vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.win-no {
|
||||
font-size: 3.125vw;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user-dept {
|
||||
display: flex;
|
||||
margin-top: 1.111vh;
|
||||
}
|
||||
|
||||
.user-dept text {
|
||||
font-size: 2.083vw;
|
||||
color: #fff;
|
||||
margin-right: 2.604vw;
|
||||
}
|
||||
|
||||
.exit-btn {
|
||||
background: #fff;
|
||||
border-radius: 2.604vw;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1.389vh 1.302vw;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon-exit {
|
||||
width: 2.604vw;
|
||||
height: 2.604vw;
|
||||
margin-right: 1.042vw;
|
||||
}
|
||||
|
||||
.exit-btn text {
|
||||
font-size: 2.083vw;
|
||||
}
|
||||
|
||||
/* 中间内容 */
|
||||
.content-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.col-title {
|
||||
font-size: 3.125vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
/* margin-bottom: 2.778vh; */
|
||||
}
|
||||
|
||||
.call-no {
|
||||
font-size: 11.458vw;
|
||||
color: rgba(19, 114, 255, 1);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.call-name {
|
||||
font-size: 2.5vw;
|
||||
color: #333;
|
||||
margin-top: 2vh;
|
||||
}
|
||||
|
||||
.call-item {
|
||||
font-size: 2vw;
|
||||
color: #666;
|
||||
margin-top: 1vh;
|
||||
}
|
||||
|
||||
/* 状态标签 */
|
||||
.status-tag {
|
||||
margin-top: 2vh;
|
||||
padding: 1vh 2vw;
|
||||
border-radius: 2vw;
|
||||
}
|
||||
|
||||
.status-tag text {
|
||||
font-size: 2vw;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tag-called {
|
||||
background-color: #1976f2;
|
||||
}
|
||||
|
||||
.tag-handling {
|
||||
background-color: #28c958;
|
||||
}
|
||||
|
||||
.wait-num {
|
||||
font-size: 11.458vw;
|
||||
color: #ff5522;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 挂起全屏遮罩 */
|
||||
.suspend-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.suspend-tip {
|
||||
font-size: 3.125vw;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4vh;
|
||||
}
|
||||
|
||||
/* 底部按钮 */
|
||||
.btn-group {
|
||||
display: flex;
|
||||
padding: 0 2.083vw 5.556vh;
|
||||
gap: 1.667vw;
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
flex: 1;
|
||||
height: 22.222vh;
|
||||
border-radius: 1.667vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-item:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
width: 3.646vw;
|
||||
height: 3.646vw;
|
||||
margin-bottom: 1.667vh;
|
||||
}
|
||||
|
||||
.btn-item text {
|
||||
font-size: 3.021vw;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.green {
|
||||
background-color: #28c958;
|
||||
}
|
||||
|
||||
.blue {
|
||||
background-color: #1976f2;
|
||||
}
|
||||
|
||||
.sky {
|
||||
background-color: #18a0f0;
|
||||
}
|
||||
|
||||
.orange {
|
||||
background-color: #ff9922;
|
||||
}
|
||||
|
||||
.red {
|
||||
background-color: #ff6633;
|
||||
}
|
||||
|
||||
.resume-btn {
|
||||
width: 18vw;
|
||||
height: 22.222vh;
|
||||
border-radius: 1.667vw;
|
||||
background-color: #28c958;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.resume-btn:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.resume-btn-icon {
|
||||
width: 3.646vw;
|
||||
height: 3.646vw;
|
||||
margin-bottom: 1.667vh;
|
||||
}
|
||||
|
||||
.resume-btn-text {
|
||||
font-size: 3.021vw;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 按钮禁用态 */
|
||||
.btn-item.disabled {
|
||||
opacity: 0.4;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ========== 弹窗通用 ========== */
|
||||
.transfer-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* 转移弹窗 */
|
||||
.transfer-dialog {
|
||||
width: 55vw;
|
||||
max-height: 70vh;
|
||||
background: #fff;
|
||||
border-radius: 2vw;
|
||||
padding: 3vh 2vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-size: 3vw;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-bottom: 3vh;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dialog-list {
|
||||
flex: 1;
|
||||
max-height: 45vh;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
|
||||
.transfer-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 3vh 2vw;
|
||||
border-bottom: 1px solid #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.transfer-item:active {
|
||||
background: #f0f4ff;
|
||||
}
|
||||
|
||||
.transfer-name {
|
||||
font-size: 2.4vw;
|
||||
font-weight: bold;
|
||||
color: #1976f2;
|
||||
}
|
||||
|
||||
.transfer-desc {
|
||||
font-size: 2vw;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dialog-empty {
|
||||
text-align: center;
|
||||
padding: 6vh 0;
|
||||
font-size: 2.2vw;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dialog-cancel {
|
||||
text-align: center;
|
||||
padding: 2vh 0;
|
||||
font-size: 2.5vw;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dialog-cancel {
|
||||
text-align: center;
|
||||
padding: 2vh 0;
|
||||
font-size: 2.5vw;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
<template>
|
||||
<view class="choose-win-wrap">
|
||||
<!-- 顶部标题栏 -->
|
||||
<view class="top-header">
|
||||
<text class="header-title">环江毛南族自治县政务服务中心</text>
|
||||
</view>
|
||||
|
||||
<!-- 主体内容区 -->
|
||||
<view class="main-content">
|
||||
<text class="main-title">请选择窗口</text>
|
||||
<text class="main-subtitle">选择您当前所在的窗口工位</text>
|
||||
|
||||
<!-- 窗口列表卡片 -->
|
||||
<view class="window-list" v-if="windowList.length > 0">
|
||||
<view class="window-card" v-for="item in windowList" :key="item.id" @click="handleSelect(item)">
|
||||
<view class="win-icon-text">{{ item.windowName }}</view>
|
||||
|
||||
<!-- <view class="win-info">
|
||||
<text class="win-type">{{ item.windowType || '综合窗口' }}</text>
|
||||
<text class="win-biz">{{ item.businessType || '综合业务' }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-else-if="!loading">
|
||||
<text class="empty-text">暂无可选窗口</text>
|
||||
<text class="empty-sub">请联系管理员检查窗口配置</text>
|
||||
</view>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<view class="loading-state" v-if="loading">
|
||||
<text class="loading-text">正在加载窗口列表...</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getWindowList, selectWindow } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
name: 'ChooseWindow',
|
||||
data() {
|
||||
return {
|
||||
windowList: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchWindowList()
|
||||
},
|
||||
methods: {
|
||||
// 获取可选窗口列表
|
||||
async fetchWindowList() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await getWindowList({ status: 1, serviceStatus: 1 })
|
||||
if (res.success && res.data) {
|
||||
this.windowList = res.data.records || []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取窗口列表失败', e)
|
||||
uni.showToast({ title: '获取窗口列表失败', icon: 'none' })
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
// 选择窗口
|
||||
async handleSelect(item) {
|
||||
uni.showLoading({ title: '选择中...', mask: true })
|
||||
try {
|
||||
const res = await selectWindow({ windowId: item.id })
|
||||
if (res.success && res.data) {
|
||||
// 保存窗口信息到本地存储
|
||||
const winInfo = {
|
||||
windowId: res.data.windowId,
|
||||
windowName: res.data.windowName,
|
||||
serviceStatus: res.data.serviceStatus,
|
||||
handlerUserId: res.data.handlerUserId,
|
||||
handlerUserName: res.data.handlerUserName,
|
||||
handlerDeptName: res.data.handlerDeptName
|
||||
}
|
||||
uni.setStorageSync('windowInfo', winInfo)
|
||||
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: `已选择 ${res.data.windowName}`, icon: 'success', duration: 1000 })
|
||||
|
||||
// 跳转到叫号工作台
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: '/pages/callTicket/callTicket'
|
||||
})
|
||||
}, 800)
|
||||
}
|
||||
} catch (e) {
|
||||
uni.hideLoading()
|
||||
console.error('选择窗口失败', e)
|
||||
uni.showToast({ title: '选择窗口失败,请重试', icon: 'none' })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.choose-win-wrap {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ========== 顶部标题栏 ========== */
|
||||
.top-header {
|
||||
width: 100%;
|
||||
background-color: rgba(19, 114, 255, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2.5vh 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 3.125vw;
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
padding-left: 2.083vw;
|
||||
/* letter-spacing: 0.3vw; */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ========== 主体内容区 ========== */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2vh 3vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
font-size: 3.125vw;
|
||||
font-weight: bold;
|
||||
color: #1a1a2e;
|
||||
margin-bottom: 1vh;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.main-subtitle {
|
||||
font-size: 2vw;
|
||||
color: rgba(26, 26, 46, 0.55);
|
||||
margin-bottom: 2vh;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ========== 窗口列表 ========== */
|
||||
.window-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
/* align-content: center; */
|
||||
/* gap: 2vh 1.5vw; */
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.window-card {
|
||||
margin-right: 2vw;
|
||||
width: 14vw;
|
||||
height: 28vh;
|
||||
background: #ffffff;
|
||||
border-radius: 1.5vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 0.4vw 2vw rgba(95, 136, 255, 0.12);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.window-card:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0.2vw 1vw rgba(95, 136, 255, 0.3);
|
||||
}
|
||||
|
||||
.win-icon-text {
|
||||
padding: 0 1vw;
|
||||
font-size: 2vw;
|
||||
font-weight: bold;
|
||||
color: #1976f2;
|
||||
text-align: center;
|
||||
/* white-space: nowrap; */
|
||||
}
|
||||
|
||||
.win-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.win-type {
|
||||
font-size: 1.4vw;
|
||||
font-weight: bold;
|
||||
color: #1a1a2e;
|
||||
margin-bottom: 0.5vh;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.win-biz {
|
||||
font-size: 1.1vw;
|
||||
color: #999999;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
/* ========== 空状态 ========== */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 3vw;
|
||||
color: #999;
|
||||
margin-bottom: 1vh;
|
||||
}
|
||||
|
||||
.empty-sub {
|
||||
font-size: 2vw;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
/* ========== 加载中 ========== */
|
||||
.loading-text {
|
||||
font-size: 2.5vw;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }" title="CRUD 操作"
|
||||
title-color="#fff">
|
||||
</u-navbar>
|
||||
<view class="u-demo">
|
||||
<view class="u-demo-wrap">
|
||||
<view class="u-demo-title">很快到来</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,441 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
formType="uniForm"
|
||||
@search="onSearch"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<template #form>
|
||||
<view class="uni-form">
|
||||
<view class="uni-form-item">
|
||||
<view class="uni-form-item-label uni-form-item-required">通知标题</view>
|
||||
<view class="uni-form-item-input">
|
||||
<input
|
||||
class="uni-input"
|
||||
v-model="form.title"
|
||||
placeholder="通知标题"
|
||||
:placeholder-style="placeholderStyle"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-form-item">
|
||||
<view class="uni-form-item-label uni-form-item-required">通知类型</view>
|
||||
<view class="uni-form-item-input">
|
||||
<picker
|
||||
@change="e => onConfirm(e, 'category')"
|
||||
:range="categoryList"
|
||||
range-key="dictValue"
|
||||
class="curdPicker"
|
||||
:disabled="readonly"
|
||||
>
|
||||
<input
|
||||
class="uni-input"
|
||||
v-model="formLabel.category"
|
||||
disabled
|
||||
placeholder="通知类型"
|
||||
:placeholder-style="placeholderStyle"
|
||||
/>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="uni-form-item-icon"><u-icon name="arrow-right" color="#999" size="28"></u-icon></view>
|
||||
</view>
|
||||
<view class="uni-form-item">
|
||||
<view class="uni-form-item-label uni-form-item-required">通知日期</view>
|
||||
<view class="uni-form-item-input">
|
||||
<picker
|
||||
@change="e => onConfirm(e, 'releaseTime')"
|
||||
mode="date"
|
||||
:value="form.releaseTime"
|
||||
:start="startDate"
|
||||
:end="endDate"
|
||||
class="curdPicker"
|
||||
:disabled="readonly"
|
||||
>
|
||||
<input
|
||||
class="uni-input"
|
||||
v-model="form.releaseTime"
|
||||
disabled
|
||||
placeholder="通知日期"
|
||||
:placeholder-style="placeholderStyle"
|
||||
/>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="uni-form-item-icon"><u-icon name="arrow-right" color="#999" size="28"></u-icon></view>
|
||||
</view>
|
||||
<view class="uni-form-item">
|
||||
<view class="uni-form-item-label">通知内容</view>
|
||||
<view v-if="!readonly" class="uni-form-item-btn" @click="onRichEdit(form.content)">去编辑</view>
|
||||
</view>
|
||||
<mp-html :content="form.content"></mp-html>
|
||||
</view>
|
||||
</template>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import mpHtml from '@/components/rider-crud/components/mp-html/mp-html'
|
||||
import { getList, add, update, remove } from '@/api/notice.js'
|
||||
import { dictionary } from '@/api/system/dict.js'
|
||||
import { logo } from '../../common/setting'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd, mpHtml },
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
content: ''
|
||||
},
|
||||
formLabel: {
|
||||
category: '' ,
|
||||
},
|
||||
list: [],
|
||||
params: {
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
readonly: false, // 查看时控制表单只读
|
||||
labelWidth: 160,
|
||||
placeholderStyle: 'color:rgb(192, 196, 204); font-size:14px',
|
||||
option: {
|
||||
navTitle: 'CRUD 操作', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
column: [
|
||||
{
|
||||
label: '通知标题',
|
||||
prop: 'title'
|
||||
},
|
||||
{
|
||||
label: '通知类型',
|
||||
prop: 'categoryName'
|
||||
},
|
||||
{
|
||||
label: '通知日期',
|
||||
prop: 'releaseTime'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
title: [{ required: true, message: '请输入通知标题', trigger: 'blur' }],
|
||||
category: [{ required: true, message: '请选择通知类型', trigger: 'change', type: 'number' }],
|
||||
releaseTime: [{ required: true, message: '请选择通知日期', trigger: 'change' }]
|
||||
},
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
checkedSwitch: false,
|
||||
timeShow: false,
|
||||
timeParams: {
|
||||
year: true,
|
||||
month: true,
|
||||
day: true,
|
||||
hour: true,
|
||||
minute: true,
|
||||
second: true
|
||||
},
|
||||
categoryShow: false,
|
||||
categoryList: [], //类型
|
||||
category: '',
|
||||
pagesTotal: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
startDate() {
|
||||
return this.getDate('start')
|
||||
},
|
||||
endDate() {
|
||||
return this.getDate('end')
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
let that = this
|
||||
uni.$on('richBack', function(data) {
|
||||
that.$set(that.form, 'content', data)
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.getList(true)
|
||||
this.getCategoryList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getDate(type) {
|
||||
const date = new Date()
|
||||
let year = date.getFullYear()
|
||||
let month = date.getMonth() + 1
|
||||
let day = date.getDate()
|
||||
if (type === 'start') {
|
||||
year = year - 60
|
||||
} else {
|
||||
year = year + 2
|
||||
}
|
||||
month = month > 9 ? month : '0' + month
|
||||
day = day > 9 ? day : '0' + day
|
||||
return `${year}-${month}-${day}`
|
||||
},
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
getList(this.params)
|
||||
.then(res => {
|
||||
const { records, current } = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.list = records
|
||||
} else {
|
||||
this.list = this.list.concat(records)
|
||||
}
|
||||
this.params.current++
|
||||
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
// 通知类型
|
||||
getCategoryList() {
|
||||
dictionary({ code: 'notice' }).then(res => {
|
||||
this.categoryList = res.data
|
||||
})
|
||||
},
|
||||
// picker确定
|
||||
onConfirm(e, type) {
|
||||
if (type == 'category') {
|
||||
const i = this.categoryList[e.detail.value]
|
||||
this.$set(this.formLabel, type, i.dictValue)
|
||||
this.$set(this.form, type, Number(i.dictKey))
|
||||
} else {
|
||||
this.$set(this.form, type, `${e.detail.value} 12:00:00`)
|
||||
}
|
||||
},
|
||||
// 编辑富文本
|
||||
onRichEdit(e) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/rich/index?data=${e}`
|
||||
})
|
||||
},
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
title: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
switch (name) {
|
||||
case '新增':
|
||||
this.formLabel = { category: '' }
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
this.formLabel.category = getDicLabel(data.category, this.categoryList)
|
||||
done()
|
||||
break
|
||||
}
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = { category: '' }
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = { category: '' }
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
|
||||
.uni-picker-container {
|
||||
z-index: 99999 !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.nav-right {
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: normal;
|
||||
padding-right: 24rpx;
|
||||
}
|
||||
|
||||
.uni-form {
|
||||
&-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
line-height: 70rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&-label {
|
||||
width: 160rpx;
|
||||
|
||||
.required {
|
||||
color: #fa3534;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
&-required {
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: '*';
|
||||
position: absolute;
|
||||
left: -8px;
|
||||
color: #fa3534;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
&-input {
|
||||
flex: 1;
|
||||
|
||||
.uni-input {
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
&-btn {
|
||||
color: #fff;
|
||||
width: auto;
|
||||
font-size: 22rpx;
|
||||
line-height: 50rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 6rpx;
|
||||
background: linear-gradient(rgb(95, 136, 255), rgb(105, 176, 255));
|
||||
}
|
||||
}
|
||||
|
||||
&-item:after {
|
||||
content: ' ';
|
||||
border-bottom-width: 2rpx;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
pointer-events: none;
|
||||
box-sizing: border-box;
|
||||
-webkit-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
width: 199.8%;
|
||||
height: 199.7%;
|
||||
-webkit-transform: scale(0.5, 0.5);
|
||||
transform: scale(0.5, 0.5);
|
||||
border: 0 solid #e4e7ed;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&-item:after {
|
||||
border-bottom-width: 2rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@search="onSearch"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<view slot="form">
|
||||
<u-form-item label="通知标题" prop="title" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.title" :disabled="readonly" placeholder="通知标题" />
|
||||
</u-form-item>
|
||||
<u-form-item label="通知类型" prop="category" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-model="formLabel.category"
|
||||
:disabled="readonly"
|
||||
placeholder="通知类型"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) categoryShow = true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="通知日期" prop="releaseTime" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-model="form.releaseTime"
|
||||
:disabled="readonly"
|
||||
placeholder="通知日期"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) timeShow = true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="通知内容" :label-width="option.labelWidth || 160" :border-bottom="false">
|
||||
<template #right v-if="!readonly">
|
||||
<u-button
|
||||
@click="onRichEdit(form.content)"
|
||||
ripple
|
||||
:custom-style="{ background: '#FFF6E9', color: '#FAA646' }"
|
||||
size="mini"
|
||||
>
|
||||
去编辑
|
||||
</u-button>
|
||||
</template>
|
||||
</u-form-item>
|
||||
<mp-html :content="form.content"></mp-html>
|
||||
</view>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
<!-- 通知类型 -->
|
||||
<u-select
|
||||
v-model="categoryShow"
|
||||
:list="categoryList"
|
||||
value-name="dictKey"
|
||||
label-name="dictValue"
|
||||
@confirm="e => onConfirm(e, 'category')"
|
||||
safe-area-inset-bottom
|
||||
></u-select>
|
||||
<!-- 通知日期 -->
|
||||
<u-picker
|
||||
mode="time"
|
||||
v-model="timeShow"
|
||||
:params="timeParams"
|
||||
start-year="2000"
|
||||
end-year="2050"
|
||||
@confirm="e => onConfirm(e, 'releaseTime')"
|
||||
safe-area-inset-bottom
|
||||
></u-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import mpHtml from '@/components/rider-crud/components/mp-html/mp-html'
|
||||
import { getList, add, update, remove } from '@/api/notice.js'
|
||||
import { dictionary } from '@/api/system/dict.js'
|
||||
import { logo } from '../../common/setting'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd, mpHtml },
|
||||
data() {
|
||||
return {
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
checkedSwitch: false, // 默认打开管理
|
||||
form: { content: '' }, // 表单
|
||||
formLabel: {}, // 表单label
|
||||
list: [], // 列表数据
|
||||
params: {
|
||||
// 分页
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
readonly: false, // 查看时控制表单只读
|
||||
option: {
|
||||
// 组件选项
|
||||
navTitle: '通知公告', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '通知标题',
|
||||
prop: 'title'
|
||||
},
|
||||
{
|
||||
label: '通知类型',
|
||||
prop: 'categoryName'
|
||||
},
|
||||
{
|
||||
label: '通知日期',
|
||||
prop: 'releaseTime'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
// 左滑操作按钮
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
// 表单校验规则
|
||||
title: [{ required: true, message: '请输入通知标题', trigger: 'blur' }],
|
||||
category: [{ required: true, message: '请选择通知类型', trigger: 'change', type: 'number' }],
|
||||
releaseTime: [{ required: true, message: '请选择通知日期', trigger: 'change' }]
|
||||
},
|
||||
timeShow: false,
|
||||
timeParams: {
|
||||
year: true,
|
||||
month: true,
|
||||
day: true,
|
||||
hour: true,
|
||||
minute: true,
|
||||
second: true
|
||||
},
|
||||
categoryShow: false,
|
||||
categoryList: [] //类型
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
let that = this
|
||||
uni.$on('richBack', function(data) {
|
||||
that.$set(that.form, 'content', data)
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.getList(true)
|
||||
this.getCategoryList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
getList(this.params)
|
||||
.then(res => {
|
||||
const { records, current } = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.list = records
|
||||
} else {
|
||||
this.list = this.list.concat(records)
|
||||
}
|
||||
this.params.current++
|
||||
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
// 通知类型
|
||||
getCategoryList() {
|
||||
dictionary({ code: 'notice' }).then(res => {
|
||||
this.categoryList = res.data
|
||||
})
|
||||
},
|
||||
// 类型回调
|
||||
onConfirm(e, type) {
|
||||
if (type == 'category') {
|
||||
this.formLabel[type] = e[0].label
|
||||
this.form.category = Number(e[0].value)
|
||||
} else {
|
||||
this.$set(this.form, 'releaseTime', e.year + '-' + e.month + '-' + e.day + ' ' + e.hour + ':' + e.minute + ':' + e.second)
|
||||
}
|
||||
},
|
||||
// 编辑富文本
|
||||
onRichEdit(e) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/rich/index?data=${e}`
|
||||
})
|
||||
},
|
||||
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
title: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
switch (name) {
|
||||
case '新增':
|
||||
this.formLabel = {}
|
||||
this.form = { content: '' }
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
this.formLabel.category = getDicLabel(data.category, this.categoryList)
|
||||
done()
|
||||
break
|
||||
}
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = {}
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = {}
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
export default [{
|
||||
groupName: '基础功能',
|
||||
list: [{
|
||||
path: '/pages/demo/storage',
|
||||
icon: 'cell',
|
||||
title: 'Storage 操作',
|
||||
}, {
|
||||
path: '/pages/demo/vuex',
|
||||
icon: 'sticky',
|
||||
title: 'Vuex 操作',
|
||||
}]
|
||||
},
|
||||
{
|
||||
groupName: '网络功能',
|
||||
list: [{
|
||||
path: '/pages/demo/mock',
|
||||
icon: 'layout',
|
||||
title: 'Mock 调用',
|
||||
}, {
|
||||
path: '/pages/demo/request',
|
||||
icon: 'tabbar',
|
||||
title: 'API 调用',
|
||||
}]
|
||||
}, {
|
||||
groupName: '业务功能',
|
||||
list: [{
|
||||
path: '/pages/demo/crud1',
|
||||
icon: 'tag',
|
||||
title: 'CRUD 操作(基于Uniapp)',
|
||||
},{
|
||||
path: '/pages/demo/crud2',
|
||||
icon: 'tag',
|
||||
title: 'CRUD 操作(基于Uview)',
|
||||
},{
|
||||
path: '/pages/componentsA/parse/index',
|
||||
icon: 'loading',
|
||||
title: '未完待续',
|
||||
}]
|
||||
},
|
||||
]
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<view class="wrap">
|
||||
<page-nav :desc="desc" :title="title"></page-nav>
|
||||
<view class="list-wrap">
|
||||
<u-cell-group title-bg-color="rgb(243, 244, 246)" :title="getGroupTitle(item)" v-for="(item, index) in list"
|
||||
:key="index">
|
||||
<u-cell-item :titleStyle="{fontWeight: 500}" @click="openPage(item1.path)" :title="getFieldTitle(item1)"
|
||||
v-for="(item1, index1) in item.list" :key="index1">
|
||||
<image slot="icon" class="u-cell-icon" :src="getIcon(item1.icon)" mode="widthFix"></image>
|
||||
</u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
<u-gap height="70"></u-gap>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pageNav from '@/components/page-nav/page-nav.vue';
|
||||
import list from "./demo.config.js";
|
||||
export default {
|
||||
components: {
|
||||
pageNav
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: list,
|
||||
title: '基础功能示例合集',
|
||||
desc: '众多示例覆盖开发过程的各个需求,正在不断完善中。可让您快速集成,开箱即用。'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getIcon() {
|
||||
return path => {
|
||||
return 'https://cdn.uviewui.com/uview/example/' + path + '.png';
|
||||
}
|
||||
},
|
||||
},
|
||||
onShow() {
|
||||
uni.setNavigationBarTitle({
|
||||
title: "233"
|
||||
});
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
openPage(path) {
|
||||
this.$u.route({
|
||||
url: path
|
||||
})
|
||||
},
|
||||
getGroupTitle(item) {
|
||||
return item.groupName
|
||||
},
|
||||
getFieldTitle(item) {
|
||||
return item.title
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* page {
|
||||
background-color: rgb(240, 242, 244);
|
||||
} */
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.u-cell-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }" title="Mock 调用"
|
||||
title-color="#fff">
|
||||
</u-navbar>
|
||||
<view class="u-demo">
|
||||
<view class="u-demo-wrap">
|
||||
<view class="u-demo-title">演示效果</view>
|
||||
<view class="u-demo-area u-flex u-row-center">
|
||||
数据为:{{data}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-config-wrap">
|
||||
<view class="u-config-title u-border-bottom">参数操作</view>
|
||||
<view class="u-config-item">
|
||||
<view class="u-item-title">按钮点击</view>
|
||||
<u-button @click="doRequest">获取数据</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
fakeBannerList
|
||||
} from "@/api/mock/home.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
doRequest() {
|
||||
let keyword = "";
|
||||
fakeBannerList().then(data => {
|
||||
this.data = data;
|
||||
this.$u.func.showToast({
|
||||
title: '数据获取成功',
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }" title="API 请求"
|
||||
title-color="#fff">
|
||||
</u-navbar>
|
||||
<view class="u-demo">
|
||||
<view class="u-demo-wrap">
|
||||
<view class="u-demo-title">演示效果</view>
|
||||
<view class="u-demo-area u-flex u-row-center">
|
||||
<u-image width="300rpx" height="100rpx" :src="url"></u-image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-config-wßrap">
|
||||
<view class="u-config-title u-border-bottom">参数操作</view>
|
||||
<view class="u-config-item">
|
||||
<view class="u-item-title">按钮点击</view>
|
||||
<u-button @click="doRequest">刷新验证码</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
url: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
doRequest() {
|
||||
let keyword = "";
|
||||
// 自动挂载至this.$u.api,无需引入
|
||||
// captcha 在 /api/demo.js 内定义
|
||||
this.$u.api.captcha().then(data => {
|
||||
this.url = data.image;
|
||||
this.$u.func.showToast({
|
||||
title: '数据获取成功',
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }" title="Storage 操作"
|
||||
title-color="#fff">
|
||||
</u-navbar>
|
||||
<view class="u-demo">
|
||||
<view class="u-demo-wrap">
|
||||
<view class="u-demo-title">演示效果</view>
|
||||
<view class="u-demo-area u-flex u-row-center">
|
||||
[ BladeX ] 的官网为:{{domain}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-config-wrap">
|
||||
<view class="u-config-title u-border-bottom">参数操作</view>
|
||||
<view class="u-config-item">
|
||||
<view class="u-item-title">按钮点击</view>
|
||||
<u-button @click="modifyStorage">修改变量</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
domain: ''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.domain = uni.getStorageSync('domain');
|
||||
},
|
||||
methods: {
|
||||
modifyStorage() {
|
||||
uni.setStorageSync('domain', 'https://bladex.vip');
|
||||
this.domain = uni.getStorageSync('domain');
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }" title="Vuex 操作"
|
||||
title-color="#fff">
|
||||
</u-navbar>
|
||||
<view class="u-demo">
|
||||
<view class="u-demo-wrap">
|
||||
<view class="u-demo-title">演示效果</view>
|
||||
<view class="u-demo-area u-flex u-row-center">
|
||||
<!-- vuex已做过封装,可以直接使用state内的变量 -->
|
||||
版本号为:{{version}}
|
||||
</view>
|
||||
<view class="u-demo-area u-flex u-row-center">
|
||||
[ BladeX ] 的作者为:{{userInfo.nickName}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-config-wrap">
|
||||
<view class="u-config-title u-border-bottom">参数操作</view>
|
||||
<view class="u-config-item">
|
||||
<view class="u-item-title">按钮点击</view>
|
||||
<u-button @click="modifyVuex">修改变量</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
// vuex已做过封装,可以直接this.$u.vuex(key, value)修改,无需引入
|
||||
modifyVuex() {
|
||||
// version不在lifeData,每次刷新会丢失
|
||||
this.$u.vuex('version', '1.0.1');
|
||||
// userInfo在lifeData,刷新重启会保留
|
||||
this.$u.vuex('userInfo.nickName', '翼');
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
<template>
|
||||
<!-- backBtn+logoutBtn 开启顶部两个按钮 -->
|
||||
<Container backBtn logoutBtn @handleBack="goBack">
|
||||
<template #main>
|
||||
<view class="wrap">
|
||||
<view class="list-card">
|
||||
<view class="item" v-for="(item, idx) in businessList" :key="idx">
|
||||
<view class="left">
|
||||
<text class="dot">◆</text>
|
||||
<text class="title-text">{{ item.itemName }}</text>
|
||||
</view>
|
||||
<view class="btn-box">
|
||||
<view class="btn-guide" @click="openGuide(item)">办事指南</view>
|
||||
<view class="btn-take" @click="toTakeNum(item)">取号</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-if="isEmpty === false"> 暂无事项 </view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Container from '@/components/container/container.vue'
|
||||
import { getBusinessList, getHistoryList, takeNumber } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Container
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
titleName: '',
|
||||
source: '',
|
||||
subjectId: '',
|
||||
deptId: '',
|
||||
businessList: [],
|
||||
isEmpty: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
idcard() {
|
||||
return uni.getStorageSync('idcard') || ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.source = options.source || ''
|
||||
this.subjectId = options.subjectId || ''
|
||||
this.deptId = options.deptId || ''
|
||||
this.titleName = options.titleName || options.subjectName || options.deptName || ''
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
// 根据 source 调用不同接口
|
||||
async fetchList() {
|
||||
let res = null
|
||||
try {
|
||||
switch (this.source) {
|
||||
case 'history':
|
||||
// 历史取号
|
||||
if (!this.idcard) {
|
||||
console.warn('历史取号缺少身份证号')
|
||||
return
|
||||
}
|
||||
res = await getHistoryList({
|
||||
applicantIdCard: this.idcard
|
||||
})
|
||||
break
|
||||
case 'business':
|
||||
// 业务取号(全部事项)
|
||||
res = await getBusinessList({
|
||||
status: 1
|
||||
})
|
||||
break
|
||||
case 'subject':
|
||||
default:
|
||||
// 主题取号 / 部门取号(兼容无 source 的旧跳转)
|
||||
const params = {
|
||||
status: 1
|
||||
}
|
||||
if (this.subjectId) {
|
||||
params.subjectId = this.subjectId
|
||||
} else if (this.deptId) {
|
||||
params.deptId = this.deptId
|
||||
} else {
|
||||
// 兼容默认:无筛选查全部
|
||||
}
|
||||
res = await getBusinessList(params)
|
||||
break
|
||||
}
|
||||
if (res && res.success && res.data) {
|
||||
this.businessList = res.data.records || []
|
||||
this.isEmpty = this.businessList.length > 0 ? true : false
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取列表失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 获取事项 ID(历史记录用 itemId,事项列表用 id)
|
||||
getItemId(item) {
|
||||
return item.itemId || item.id
|
||||
},
|
||||
|
||||
// 点击取号
|
||||
async toTakeNum(row) {
|
||||
if (!this.idcard) {
|
||||
uni.showToast({
|
||||
title: '请先刷身份证',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await takeNumber({
|
||||
applicantIdCard: this.idcard,
|
||||
itemId: this.getItemId(row)
|
||||
})
|
||||
if (res.success) {
|
||||
uni.showToast({
|
||||
title: '取号成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('取号失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 办事指南
|
||||
openGuide(item) {
|
||||
const id = this.getItemId(item)
|
||||
uni.navigateTo({
|
||||
url: `/pages/home/guide?id=${id}&itemName=${item.itemName}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 15vh 5vw 10vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
height: 75vh;
|
||||
background: #fff;
|
||||
border-radius: 5vh;
|
||||
padding: 3vh 5vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 2vh 0;
|
||||
border-bottom: 0.1vh solid rgba(188, 200, 209, 1);
|
||||
}
|
||||
|
||||
.item:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.item:last-child {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
width: 68%;
|
||||
}
|
||||
|
||||
.dot {
|
||||
color: #3688ff;
|
||||
font-size: 1.6vw;
|
||||
margin-right: 1.5vw;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 1.6vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
gap: 1.5vw;
|
||||
}
|
||||
|
||||
.btn-guide {
|
||||
background: #28c068;
|
||||
color: #fff;
|
||||
font-size: 1.6vw;
|
||||
padding: 1.2vh 3vw;
|
||||
border-radius: 99px;
|
||||
}
|
||||
|
||||
.btn-take {
|
||||
background: #367bfa;
|
||||
color: #fff;
|
||||
font-size: 1.6vw;
|
||||
padding: 1.2vh 3vw;
|
||||
border-radius: 99px;
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
font-size: 1.6vw;
|
||||
color: #999;
|
||||
padding: 10vh 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
<template>
|
||||
<view class="choose-wrap">
|
||||
<!-- 顶部标题栏 -->
|
||||
<view class="top-header">
|
||||
<text class="header-title">环江毛南族自治县政务服务中心</text>
|
||||
</view>
|
||||
|
||||
<!-- 主体内容区 -->
|
||||
<view class="main-content">
|
||||
<text class="main-title">请选择设备类型</text>
|
||||
<text class="main-subtitle">请根据当前设备用途选择对应的使用模式</text>
|
||||
|
||||
<!-- 三个选项卡片 -->
|
||||
<view class="card-group">
|
||||
<!-- 取号机 -->
|
||||
<view class="card" @click="goToPage('/pages/home/home', '取号机')">
|
||||
<view class="card-icon-box ticket-bg">
|
||||
<text class="card-icon-text">取</text>
|
||||
</view>
|
||||
<text class="card-title">取号机</text>
|
||||
<text class="card-desc">自助排队取号</text>
|
||||
</view>
|
||||
|
||||
<!-- 叫号机 -->
|
||||
<view class="card" @click="goToPage('/pages/callTicket/chooseWindow', '叫号机')">
|
||||
<view class="card-icon-box call-bg">
|
||||
<text class="card-icon-text call-text">叫</text>
|
||||
</view>
|
||||
<text class="card-title">叫号机</text>
|
||||
<text class="card-desc">窗口叫号管理</text>
|
||||
</view>
|
||||
|
||||
<!-- 公告屏 -->
|
||||
<view class="card" @click="goToPage('/pages/screen/screen', '公告屏')">
|
||||
<view class="card-icon-box screen-bg">
|
||||
<text class="card-icon-text screen-text">屏</text>
|
||||
</view>
|
||||
<text class="card-title">公告屏</text>
|
||||
<text class="card-desc">大屏信息展示</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ChooseMachine',
|
||||
methods: {
|
||||
goToPage(url, name) {
|
||||
uni.showModal({
|
||||
title: '确认选择',
|
||||
content: `确定进入【${name}】模式吗?选择后需重新登录才能切换。`,
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
uni.redirectTo({
|
||||
url: url,
|
||||
fail() {
|
||||
uni.switchTab({
|
||||
url: url
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 全屏自适应容器 - flex弹性布局 */
|
||||
.choose-wrap {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
/* background: linear-gradient(180deg, #5f88ff 0%, #e8edfa 45%, #f5f7fc 100%); */
|
||||
}
|
||||
|
||||
/* ========== 顶部标题栏 ========== */
|
||||
.top-header {
|
||||
width: 100%;
|
||||
height: 16vh;
|
||||
min-height: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(19, 114, 255, 0.95);
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: clamp(32px, 5vw, 64px);
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.4vw;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ========== 主体内容区 ========== */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4vw 4vh;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
font-size: clamp(36px, 6vw, 72px);
|
||||
font-weight: bold;
|
||||
color: #1a1a2e;
|
||||
margin-bottom: 1.5vh;
|
||||
letter-spacing: 0.3vw;
|
||||
}
|
||||
|
||||
.main-subtitle {
|
||||
font-size: clamp(22px, 3vw, 36px);
|
||||
color: rgba(26, 26, 46, 0.55);
|
||||
margin-bottom: 7vh;
|
||||
letter-spacing: 0.1vw;
|
||||
}
|
||||
|
||||
/* ========== 卡片组 ========== */
|
||||
.card-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: clamp(30px, 5vw, 80px);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: clamp(260px, 22vw, 400px);
|
||||
min-width: 200px;
|
||||
background: #ffffff;
|
||||
border-radius: 32px;
|
||||
padding: clamp(40px, 6vh, 80px) clamp(30px, 4vw, 50px) clamp(35px, 5vh, 70px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-shadow: 0 0.8vw 4vw rgba(95, 136, 255, 0.15);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.card:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0.4vw 2vw rgba(95, 136, 255, 0.3);
|
||||
}
|
||||
|
||||
/* 图标圆形 */
|
||||
.card-icon-box {
|
||||
width: clamp(100px, 12vw, 180px);
|
||||
height: clamp(100px, 12vw, 180px);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: clamp(24px, 4vh, 48px);
|
||||
}
|
||||
|
||||
.ticket-bg {
|
||||
background: linear-gradient(135deg, #e8f0ff, #c5d8ff);
|
||||
}
|
||||
|
||||
.call-bg {
|
||||
background: linear-gradient(135deg, #e0f5e8, #b0e0c0);
|
||||
}
|
||||
|
||||
.screen-bg {
|
||||
background: linear-gradient(135deg, #fff3e8, #ffe0c0);
|
||||
}
|
||||
|
||||
/* 图标文字 */
|
||||
.card-icon-text {
|
||||
font-size: clamp(40px, 5vw, 80px);
|
||||
font-weight: bold;
|
||||
color: #5f88ff;
|
||||
}
|
||||
|
||||
.call-text {
|
||||
color: #2e9e5f;
|
||||
}
|
||||
|
||||
.screen-text {
|
||||
color: #e89840;
|
||||
}
|
||||
|
||||
/* 卡片文字 */
|
||||
.card-title {
|
||||
font-size: clamp(28px, 3.5vw, 52px);
|
||||
font-weight: bold;
|
||||
color: #1a1a2e;
|
||||
margin-bottom: 1.5vh;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: clamp(18px, 2.2vw, 30px);
|
||||
color: #999999;
|
||||
letter-spacing: 0.1vw;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
<template>
|
||||
<Container backBtn logoutBtn @handleBack="handleBack">
|
||||
<template #main>
|
||||
<view class="theme-page">
|
||||
<view class="card">
|
||||
<view class="title">部门取号</view>
|
||||
<view class="btn-group">
|
||||
<view class="btn-item" v-for="(item, index) in deptList" :key="index" @click="handleSelect(item)">
|
||||
{{ item.deptName }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Container from '@/components/container/container.vue'
|
||||
import { getList } from '@/api/system/dept.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Container
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
deptList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
idcard() {
|
||||
return uni.getStorageSync('idcard') || ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchDeptList()
|
||||
},
|
||||
methods: {
|
||||
handleBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
handleSelect(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/home/businessList?source=dept&deptId=${item.id}&deptName=${item.deptName}`
|
||||
})
|
||||
},
|
||||
|
||||
async fetchDeptList() {
|
||||
try {
|
||||
const res = await getList({ parentId: '1123598813738675202' })
|
||||
if (res.success && res.data) {
|
||||
this.deptList = res.data.records || res.data || []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取部门列表失败', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.theme-page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 15vh 5vw 10vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
border-radius: 5vh;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 4vh 3vw;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.5vw;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 5vh;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
margin: 0 2vw 2vw 0;
|
||||
padding: 1.5vh 1.5vw;
|
||||
width: 19vw;
|
||||
height: 11vh;
|
||||
text-align: center;
|
||||
background: rgba(236, 243, 255, 1);
|
||||
border-radius: 2vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.7vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn-item:nth-child(4n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
<template>
|
||||
<Container backBtn logoutBtn @handleBack="backPrev">
|
||||
<template #main>
|
||||
<view class="page-wrap">
|
||||
<view class="content-card">
|
||||
<!-- 标题+右上角按钮 -->
|
||||
<view class="top-row">
|
||||
<view class="title">{{ info.title }}</view>
|
||||
<view class="btn-take" @click="goScanCard">立即取号</view>
|
||||
</view>
|
||||
<!-- 部门信息 -->
|
||||
<view class="dept-text">部门:{{ info.dept }}</view>
|
||||
<!-- 办事详情正文 -->
|
||||
<view class="desc-text">{{ info.content }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Container from '@/components/container/container.vue'
|
||||
import { getItemDetail, takeNumber } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Container
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
itemId: '',
|
||||
info: {
|
||||
title: '',
|
||||
dept: '',
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
idcard() {
|
||||
return uni.getStorageSync('idcard') || ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.itemId = options.id || ''
|
||||
if (this.itemId) {
|
||||
this.fetchDetail(this.itemId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
backPrev() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
// 查询事项详情
|
||||
async fetchDetail(id) {
|
||||
try {
|
||||
const res = await getItemDetail({ id })
|
||||
if (res.success && res.data) {
|
||||
const d = res.data
|
||||
this.info.title = d.itemName || ''
|
||||
this.info.dept = d.deptName || ''
|
||||
this.info.content = d.guideContent || ''
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取事项详情失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 立即取号
|
||||
async goScanCard() {
|
||||
if (!this.idcard) {
|
||||
uni.showToast({
|
||||
title: '请先刷身份证',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await takeNumber({
|
||||
applicantIdCard: this.idcard,
|
||||
itemId: this.itemId
|
||||
})
|
||||
if (res.success) {
|
||||
uni.showToast({
|
||||
title: '取号成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('取号失败', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 15vh 5vw 10vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.content-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
border-radius: 5vh;
|
||||
padding: 3vh 5vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 1vh;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2vw;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.btn-take {
|
||||
background-color: #367bfa;
|
||||
color: #fff;
|
||||
font-size: 2vw;
|
||||
padding: 1.5vh 4vw;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.dept-text {
|
||||
font-size: 2vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 3vh;
|
||||
}
|
||||
|
||||
.desc-text {
|
||||
font-size: 2vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 1.8;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,101 +1,253 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<Container>
|
||||
<template #main>
|
||||
<view class="card">
|
||||
<!-- 身份证图标区域 -->
|
||||
<view class="id-card"> </view>
|
||||
<!-- 提示文字 -->
|
||||
<text class="tip">请刷身份证取号</text>
|
||||
<input v-model="inputVal" placeholder="请输入内容" confirm-type="done" @confirm="goRoute" />
|
||||
<!-- 顶部标题栏 -->
|
||||
<view class="header">
|
||||
<text class="title">广西区直住房保障中心</text>
|
||||
</view>
|
||||
|
||||
<!-- 预约功能区 -->
|
||||
<view class="reserve-section">
|
||||
<view class="reserve-card" @click="handleOnlineReserve">
|
||||
<view class="icon online-icon"></view>
|
||||
<text class="card-text">网上预约</text>
|
||||
</view>
|
||||
<view class="reserve-card" @click="handleMyReserve">
|
||||
<view class="icon my-icon"></view>
|
||||
<text class="card-text">我的预约</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 热门服务区 -->
|
||||
<view class="service-section">
|
||||
<text class="section-title">热门服务</text>
|
||||
|
||||
<view class="service-item" v-for="(item, index) in serviceList" :key="index"
|
||||
@click="handleServiceClick(item)">
|
||||
<view class="item-left">
|
||||
<view class="dot"></view>
|
||||
<text class="item-text">{{ item.name }}</text>
|
||||
</view>
|
||||
<view class="arrow"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Container>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Container from '@/components/container/container.vue'
|
||||
import {
|
||||
deptList,
|
||||
itemList
|
||||
} from '@/api/reserve.js'
|
||||
import {
|
||||
dictionary
|
||||
} from '@/api/system/dict.js'
|
||||
|
||||
export default {
|
||||
name: 'SelfServiceMachine',
|
||||
components: {
|
||||
Container
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inputVal: '',
|
||||
currentTime: ''
|
||||
// 热门服务列表(和设计图完全一致)
|
||||
serviceList: [],
|
||||
statusList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updateTime()
|
||||
setInterval(() => {
|
||||
this.updateTime()
|
||||
}, 1000)
|
||||
// APP端强制横屏
|
||||
// #ifdef APP-PLUS
|
||||
plus.screen.lockOrientation('landscape-primary')
|
||||
// #endif
|
||||
onLoad() {
|
||||
this.getItemList()
|
||||
this.getDictionary()
|
||||
},
|
||||
methods: {
|
||||
updateTime() {
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(now.getDate()).padStart(2, '0')
|
||||
const hours = String(now.getHours()).padStart(2, '0')
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0')
|
||||
this.currentTime = `${year}年${month}月${day}日 ${hours}:${minutes}:${seconds}`
|
||||
},
|
||||
goRoute() {
|
||||
// 全局存储身份证号
|
||||
uni.setStorageSync('idcard', this.inputVal)
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/ticket'
|
||||
})
|
||||
getDictionary() {
|
||||
dictionary({
|
||||
code: 'booking_status'
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.statusList = res.data
|
||||
uni.setStorageSync('statusList', this.statusList);
|
||||
}
|
||||
})
|
||||
},
|
||||
// 网上预约点击事件
|
||||
handleOnlineReserve() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/reserve/index'
|
||||
})
|
||||
},
|
||||
// 我的预约点击事件
|
||||
handleMyReserve() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/myReserve/index'
|
||||
})
|
||||
},
|
||||
getItemList() {
|
||||
let params = {
|
||||
size: 5,
|
||||
current: 1,
|
||||
status: 1,
|
||||
}
|
||||
itemList(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.serviceList = res.data.records
|
||||
}
|
||||
})
|
||||
},
|
||||
// 服务项点击事件
|
||||
handleServiceClick(item) {
|
||||
const data = JSON.stringify(item)
|
||||
uni.navigateTo({
|
||||
url: `/pages/reserve/notice?data=${encodeURIComponent(data)}`
|
||||
})
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/reserve/index?id=${item.id}`
|
||||
// })
|
||||
},
|
||||
// // 获取部门列表
|
||||
// getDeptList() {
|
||||
// let params = {
|
||||
// size: 10,
|
||||
// current: 1
|
||||
// }
|
||||
// deptList(params).then(res => {
|
||||
// if (res.code === 200) {
|
||||
// this.serviceList = res.data.records.filter(item => item.parentId != 0)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 中间卡片 - 自适应宽高 */
|
||||
.card {
|
||||
background: #ffffff;
|
||||
width: 63vw;
|
||||
height: 68vh;
|
||||
border-radius: 2.5%;
|
||||
box-shadow: 0 1vh 3vh rgba(0, 123, 255, 0.15);
|
||||
<style scoped lang="scss">
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* 顶部标题栏 */
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
background: linear-gradient(to bottom, #e8f3ff 0%, #f5f5f5 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('/static/images/newImg/home_bg.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 700;
|
||||
color: rgba(49, 134, 255, 1);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 预约功能区 */
|
||||
.reserve-section {
|
||||
display: flex;
|
||||
padding: 0 30rpx 30rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.reserve-card {
|
||||
flex: 1;
|
||||
background-color: #ffffff;
|
||||
border-radius: 32rpx;
|
||||
padding: 40rpx 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 身份证卡片 */
|
||||
.id-card {
|
||||
width: 27vw;
|
||||
height: 28vh;
|
||||
background: url('../../static/images/home/idcard_bg.png');
|
||||
background-size: 100% 100%;
|
||||
.icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 20rpx;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.online-icon {
|
||||
background-image: url('@/static/images/newImg/online_icon.png');
|
||||
}
|
||||
|
||||
.my-icon {
|
||||
background-image: url('@/static/images/newImg/my_icon.png');
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 热门服务区 */
|
||||
.service-section {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: block;
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.service-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 5%;
|
||||
margin-bottom: 5%;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
/* 提示文字 */
|
||||
.tip {
|
||||
font-size: 5vh;
|
||||
color: #222;
|
||||
.item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(to bottom, rgba(49, 134, 255, 1), rgba(21, 167, 255, 1));
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: 34rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.2vh;
|
||||
}
|
||||
|
||||
::v-deep .uni-input-wrapper {
|
||||
width: 60vw;
|
||||
border: 0.2vh solid #ccc;
|
||||
.arrow {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-right: 4rpx solid #165dff;
|
||||
border-top: 4rpx solid #165dff;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
<template>
|
||||
<Container backBtn logoutBtn @handleBack="handleBack">
|
||||
<template #main>
|
||||
<view class="theme-page">
|
||||
<view class="card">
|
||||
<view class="title">主题取号</view>
|
||||
<view class="btn-group">
|
||||
<view class="btn-item" v-for="(item, index) in themeList" :key="index" @click="handleSelect(item)">
|
||||
{{ item.subjectName }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Container from '@/components/container/container.vue'
|
||||
import { getThemeList } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Container
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
themeList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
idcard() {
|
||||
return uni.getStorageSync('idcard') || ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchThemeList()
|
||||
},
|
||||
methods: {
|
||||
handleBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
handleSelect(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/home/businessList?source=subject&subjectId=${item.id}&subjectName=${item.subjectName}`
|
||||
})
|
||||
},
|
||||
|
||||
async fetchThemeList() {
|
||||
try {
|
||||
const res = await getThemeList({ status: 1 })
|
||||
if (res.success && res.data) {
|
||||
this.themeList = res.data.records || []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取主题列表失败', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.theme-page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 15vh 5vw 10vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
border-radius: 5vh;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 4vh 3vw;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.5vw;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 5vh;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
margin: 0 2vw 2vw 0;
|
||||
padding: 1.5vh 1.5vw;
|
||||
width: 19vw;
|
||||
height: 11vh;
|
||||
text-align: center;
|
||||
background: rgba(236, 243, 255, 1);
|
||||
border-radius: 2vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-item:nth-child(4n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
<template>
|
||||
<Container logoutBtn>
|
||||
<template #main>
|
||||
<view class="home-page">
|
||||
<!-- 左侧四大功能按钮 -->
|
||||
<view class="btn-group">
|
||||
<view class="btn-item blue" @click="goTheme"> </view>
|
||||
<view class="btn-item green" @click="goDept"> </view>
|
||||
<view class="btn-item orange" @click="goHistory"> </view>
|
||||
<view class="btn-item red" @click="goBusiness"> </view>
|
||||
</view>
|
||||
|
||||
<!-- 右侧热门推荐 -->
|
||||
<view class="hot-recommend">
|
||||
<view class="recommend-title">热门推荐</view>
|
||||
<view class="recommend-list">
|
||||
<view class="recommend-item" v-for="(item, index) in recommendList" :key="index" @click="handleSelect(item)">
|
||||
<text class="dot">◆</text>
|
||||
<text class="text">{{ item.itemName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Container from '@/components/container/container.vue'
|
||||
import { getBusinessList } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Container
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
recommendList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
idcard() {
|
||||
return uni.getStorageSync('idcard') || ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchHotList()
|
||||
},
|
||||
methods: {
|
||||
// 查询热门事项
|
||||
async fetchHotList() {
|
||||
try {
|
||||
const res = await getBusinessList({
|
||||
hot: 1,
|
||||
status: 1,
|
||||
current: 1,
|
||||
size: 12,
|
||||
descs: 'create_time,id'
|
||||
})
|
||||
if (res.success && res.data) {
|
||||
this.recommendList = res.data.records || []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取热门事项失败', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 点击事项 → 跳转办事指南
|
||||
handleSelect(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/home/guide?id=${item.id}&itemName=${item.itemName}`
|
||||
})
|
||||
},
|
||||
|
||||
// 主题取号
|
||||
goTheme() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/theme'
|
||||
})
|
||||
},
|
||||
// 部门取号
|
||||
goDept() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/dept'
|
||||
})
|
||||
},
|
||||
// 历史取号
|
||||
goHistory() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/businessList?source=history&titleName=历史取号'
|
||||
})
|
||||
},
|
||||
// 业务取号
|
||||
goBusiness() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/businessList?source=business&titleName=业务取号'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.home-page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 4vw;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 左侧四大功能按钮 - 2×2 网格 */
|
||||
.btn-group {
|
||||
padding-top: 2vw;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: center;
|
||||
/* justify-content: center; */
|
||||
/* gap: 3vh 3vw; */
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
margin: 0 2vw 2vw 0;
|
||||
width: 28vw;
|
||||
height: 32vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
.btn-item:nth-child(n + 3),
|
||||
.btn-item:nth-child(n + 4) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.btn-item:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.btn-item.blue {
|
||||
background: url('../../static/images/ticket/theme_bg.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.btn-item.green {
|
||||
background: url('../../static/images/ticket/dept_bg.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.btn-item.orange {
|
||||
background: url('../../static/images/ticket/history_bg.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.btn-item.red {
|
||||
background: url('../../static/images/ticket/business_bg.png');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
/* 右侧热门推荐 */
|
||||
.hot-recommend {
|
||||
margin-top: 2vw;
|
||||
width: 54vw;
|
||||
height: 68vh;
|
||||
background: #fff;
|
||||
border-radius: 1.5vw;
|
||||
box-shadow: 0 0.5vh 1.5vh rgba(0, 0, 0, 0.08);
|
||||
padding: 3vh 2vw 2vh;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.recommend-title {
|
||||
font-size: 2.4vw;
|
||||
font-weight: bold;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
text-align: center;
|
||||
margin-bottom: 2.5vh;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.recommend-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.5vh;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.recommend-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.dot {
|
||||
color: #4080ff;
|
||||
font-size: 1.8vw;
|
||||
margin-right: 0.8vw;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 1.8vw;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
<template>
|
||||
<!-- 空白loading页 -->
|
||||
<view class="loading-container">
|
||||
<view class="loading-text">正在登录中,请稍候...</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
login
|
||||
} from '@/api/login.js'
|
||||
|
||||
export default {
|
||||
onLoad(options) {
|
||||
// 页面加载 → 自动执行流程
|
||||
this.getToken()
|
||||
this.autoLogin(options)
|
||||
},
|
||||
|
||||
methods: {
|
||||
getToken() {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: '/epoint-web-cs/rest/oauth2/token',
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
data: {
|
||||
client_id: '316f983b-2b93-4c57-b912-c00e05aceed2', // 你接口需要的参数名
|
||||
client_secret: 'cd2cf239-1506-47bb-9b63-507b6b759a06',
|
||||
grant_type: 'password',
|
||||
platform: 'mobile',
|
||||
username: '马贤宝',
|
||||
password: 'Epoint@123',
|
||||
// 其他需要的参数继续加
|
||||
},
|
||||
success: (res) => {
|
||||
const data = res.data
|
||||
console.log(data, 'data')
|
||||
|
||||
// 接口返回成功判断(根据接口标准结构)
|
||||
if (data.status.code === 1) {
|
||||
resolve(data.custom) // 返回用户信息:name, phone, idCard
|
||||
} else {
|
||||
reject(new Error(data.status.text || '获取用户信息失败'))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 自动登录流程
|
||||
*/
|
||||
async autoLogin(options) {
|
||||
try {
|
||||
// 1. 从URL获取token
|
||||
const token = options.token
|
||||
if (!token) {
|
||||
uni.showToast({
|
||||
title: '未获取到登录凭证',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 使用token 请求【获取用户信息接口】
|
||||
const userInfo = await this.getUserInfo(token)
|
||||
|
||||
|
||||
// 4. 执行你系统的登录逻辑(保存信息)
|
||||
this.doLocalLogin(userInfo)
|
||||
|
||||
// 5. 登录成功 → 跳首页
|
||||
// uni.switchTab({
|
||||
// url: '/pages/home/home' // 你的首页路径
|
||||
// })
|
||||
|
||||
} catch (err) {
|
||||
console.error('登录失败:', err)
|
||||
uni.showToast({
|
||||
title: err.message || '登录失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 请求接口:获取用户信息(你给的正式接口)
|
||||
* @param {string} token
|
||||
*/
|
||||
getUserInfo(token) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let url = '/epoint-web-cs/rest/wechatloginrest/getuserinfo'
|
||||
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
// // 开发环境接口地址
|
||||
// url = 'epoint-web-cs/rest/wechatloginrest/getuserinfo'
|
||||
// } else if (process.env.NODE_ENV === 'production') {
|
||||
// // 正式环境接口地址
|
||||
// url = 'epoint-web/rest/wechatloginrest/getuserinfo'
|
||||
// }
|
||||
|
||||
uni.request({
|
||||
url: url,
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'authorization': 'Bearer ' + token // 按接口要求携带token
|
||||
},
|
||||
success: (res) => {
|
||||
const data = res.data
|
||||
|
||||
// 接口返回成功判断(根据接口标准结构)
|
||||
if (data.status.code === 1) {
|
||||
resolve(data.custom) // 返回用户信息:name, phone, idCard
|
||||
} else {
|
||||
reject(new Error(data.status.text || '获取用户信息失败'))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 你系统本地登录:缓存token + 用户信息
|
||||
*/
|
||||
doLocalLogin(userInfo) {
|
||||
login({
|
||||
// username: userInfo.idnumber,
|
||||
username: userInfo.mobile,
|
||||
|
||||
grant_type: "third"
|
||||
})
|
||||
.then(data => {
|
||||
this.$u.func.login(data, '/pages/home/home')
|
||||
})
|
||||
.catch(err => {
|
||||
this.$u.func.showToast({
|
||||
title: '用户名或密码错误'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.loading-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
username: '',
|
||||
password: '',
|
||||
disabled: false,
|
||||
redirect: '/pages/home/chooseMachine'
|
||||
redirect: '/pages/home/home'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,377 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@search="onSearch"
|
||||
@child="onChildren"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<template #form>
|
||||
<u-form-item label="机构名称" prop="deptName" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.deptName" :disabled="readonly" placeholder="机构名称" />
|
||||
</u-form-item>
|
||||
<u-form-item label="机构全称" prop="fullName" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.fullName" :disabled="readonly" placeholder="机构全称" />
|
||||
</u-form-item>
|
||||
<u-form-item label="上级机构" prop="parentId" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-if="!isAddChild"
|
||||
v-model="formLabel.parentName"
|
||||
placeholder="机构全称"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) $refs.treePicker._show()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<u-input v-else v-model="formLabel.parentName" placeholder="机构全称" disabled />
|
||||
</u-form-item>
|
||||
<u-form-item label="机构类型" prop="deptCategory" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-model="formLabel.category"
|
||||
placeholder="机构类型"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) categoryShow = true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="排序" prop="sort" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.sort" :disabled="readonly" type="number" placeholder="排序" />
|
||||
</u-form-item>
|
||||
<u-form-item label="描述" :label-width="option.labelWidth || 160" prop="remark">
|
||||
<u-input v-model="form.remark" :disabled="readonly" type="textarea" :maxlength="-1" :height="35" placeholder="描述" />
|
||||
</u-form-item>
|
||||
</template>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
<u-select
|
||||
v-model="categoryShow"
|
||||
:list="categoryList"
|
||||
value-name="dictKey"
|
||||
label-name="dictValue"
|
||||
@confirm="onConfirm"
|
||||
safe-area-inset-bottom
|
||||
></u-select>
|
||||
<!-- 上级机构tree -->
|
||||
<rider-tree
|
||||
ref="treePicker"
|
||||
:range="deptTreeList"
|
||||
idKey="id"
|
||||
nameKey="title"
|
||||
:multiple="false"
|
||||
:cascade="false"
|
||||
:foldAll="false"
|
||||
confirmColor="#4E7FF9"
|
||||
cancelColor="#757575"
|
||||
title="上级机构"
|
||||
titleColor="#757575"
|
||||
@cancel="$refs.treePicker._hide()"
|
||||
@confirm="onTreeConfirm"
|
||||
></rider-tree>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import riderTree from '@/components/rider-crud/components/tree-picker'
|
||||
import { getList, add, update, remove, deptTree } from '@/api/system/dept.js'
|
||||
import { tenantSelect } from '@/api/system/tenant.js'
|
||||
import { dictionary } from '@/api/system/dict.js'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd, riderTree },
|
||||
data() {
|
||||
return {
|
||||
checkedSwitch: false,
|
||||
form: {},
|
||||
formLabel: {},
|
||||
list: [],
|
||||
params: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
parentId: 0
|
||||
},
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
readonly: false, // 查看时控制表单只读
|
||||
option: {
|
||||
navTitle: '部门管理', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '机构名称',
|
||||
prop: 'deptName'
|
||||
},
|
||||
{
|
||||
label: '所属租户',
|
||||
prop: 'tenantName'
|
||||
},
|
||||
{
|
||||
label: '机构全称',
|
||||
prop: 'fullName'
|
||||
},
|
||||
{
|
||||
label: '机构类型',
|
||||
prop: 'deptCategoryName'
|
||||
},
|
||||
{
|
||||
label: '排序',
|
||||
prop: 'sort'
|
||||
},
|
||||
{
|
||||
label: '描述',
|
||||
prop: 'remark'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
},
|
||||
{
|
||||
name: '新增子项',
|
||||
icon: 'plus',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
deptCategory: [{ required: true, message: '请选择机构类型', trigger: 'change', type: 'number' }],
|
||||
deptName: [{ required: true, message: '请输入机构名称', trigger: 'blur' }],
|
||||
fullName: [{ required: true, message: '请输入机构全称', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '请输入排序', trigger: 'blur', type: 'number' }]
|
||||
},
|
||||
categoryShow: false,
|
||||
categoryList: [],
|
||||
tenantList: [],
|
||||
deptTreeList: [],
|
||||
isAddChild: false
|
||||
}
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.getList(true)
|
||||
this.getTenant().then(() => {
|
||||
this.getList(true)
|
||||
})
|
||||
this.getCategoryList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
getList(this.params)
|
||||
.then(res => {
|
||||
const records = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) this.list = records
|
||||
else this.list = this.list.concat(records)
|
||||
if (this.list && this.list.length > 0) {
|
||||
this.list.map(e => {
|
||||
e.tenantName = getDicLabel(e.tenantId, this.tenantList, { label: 'tenantName', value: 'tenantId' })
|
||||
e.children = []
|
||||
})
|
||||
this.$refs.crud.setLazyLoad((item, index, cb) => {
|
||||
getList({ parentId: item.id }).then(res => {
|
||||
res.data.map(e => {
|
||||
e.tenantName = getDicLabel(e.tenantId, this.tenantList, { label: 'tenantName', value: 'tenantId' })
|
||||
})
|
||||
cb(res.data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.params.current++
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
|
||||
// 获取类型
|
||||
getCategoryList() {
|
||||
dictionary({ code: 'org_category' }).then(res => {
|
||||
this.categoryList = res.data
|
||||
})
|
||||
},
|
||||
|
||||
// 租户类型
|
||||
getTenant() {
|
||||
return new Promise(resolve => {
|
||||
deptTree().then(res => {
|
||||
this.deptTreeList = res.data
|
||||
})
|
||||
tenantSelect().then(res => {
|
||||
this.tenantList = res.data
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
// 类型回调
|
||||
onConfirm(e) {
|
||||
this.$set(this.formLabel, 'category', e[0].label)
|
||||
this.$set(this.form, 'deptCategory', Number(e[0].value))
|
||||
},
|
||||
//上级机构选择回调
|
||||
onTreeConfirm(e) {
|
||||
this.$set(this.form, 'parentId', e[0].id)
|
||||
this.$set(this.formLabel, 'parentName', e[0].name)
|
||||
},
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
deptName: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
switch (name) {
|
||||
case '新增':
|
||||
this.form = {}
|
||||
this.formLabel = {}
|
||||
this.isAddChild = false
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
this.isAddChild = false
|
||||
this.formLabel = {
|
||||
category: getDicLabel(data.deptCategory, this.categoryList),
|
||||
parentName: getDicLabel(data.parentId, this.deptTreeList, { label: 'title', value: 'id' })
|
||||
}
|
||||
done()
|
||||
break
|
||||
case '新增子项':
|
||||
this.isAddChild = true
|
||||
this.form = {}
|
||||
this.formLabel = {
|
||||
parentName: getDicLabel(data.id, this.deptTreeList, { label: 'title', value: 'id' })
|
||||
}
|
||||
this.$set(this.form, 'parentId', data.id)
|
||||
done()
|
||||
break
|
||||
}
|
||||
if (['删除', '编辑', '新增子项'].includes(name)) this.$refs['crud'].hideChildren()
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增' || action == '新增子项') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.nav-right {
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: normal;
|
||||
padding-right: 24rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,489 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@search="onSearch"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<template #form>
|
||||
<u-form-item label="字典编号" prop="code" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.code" :disabled="readonly" placeholder="字典编号" />
|
||||
</u-form-item>
|
||||
<u-form-item label="字典名称" prop="dictValue" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.dictValue" :disabled="readonly" placeholder="字典名称" />
|
||||
</u-form-item>
|
||||
<u-form-item label="字典排序" prop="sort" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.sort" :disabled="readonly" type="number" placeholder="字典排序" />
|
||||
</u-form-item>
|
||||
<u-form-item label="封存" prop="isSealed" :label-width="option.labelWidth || 160" required>
|
||||
<u-radio-group v-model="form.isSealed" :disabled="readonly">
|
||||
<u-radio shape="circle" :name="1" active-color="#4E7FF9">是</u-radio>
|
||||
<u-radio shape="circle" :name="0" active-color="#4E7FF9">否</u-radio>
|
||||
</u-radio-group>
|
||||
</u-form-item>
|
||||
<u-form-item label="字典备注" :label-width="option.labelWidth || 160" prop="remark">
|
||||
<u-input
|
||||
v-model="form.remark"
|
||||
:disabled="readonly"
|
||||
type="textarea"
|
||||
:maxlength="-1"
|
||||
:height="35"
|
||||
placeholder="字典备注"
|
||||
/>
|
||||
</u-form-item>
|
||||
</template>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
<!-- 字典配置 -->
|
||||
<u-popup v-model="configShow" mode="bottom" height="100vh" @close="onConfigClose" :mask-close-able="false">
|
||||
<scroll-view scroll-y="true" style="height: 100vh; background: #f5f5f5">
|
||||
<rider-curd
|
||||
ref="childCrud"
|
||||
v-model="childForm"
|
||||
:navBack="onConfigClose"
|
||||
@search="onChildSearch"
|
||||
:option="{ ...configOption, navTitle: `${configName} - 字典配置` }"
|
||||
:data="childList"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
>
|
||||
<template #form>
|
||||
<u-form-item label="字典编号" prop="code" :label-width="configOption.labelWidth || 160" required>
|
||||
<u-input v-model="childForm.code" disabled placeholder="字典编号" />
|
||||
</u-form-item>
|
||||
<u-form-item label="字典名称" prop="dictValue" :label-width="configOption.labelWidth || 160" required>
|
||||
<u-input v-model="childForm.dictValue" :disabled="readonly" placeholder="字典名称" />
|
||||
</u-form-item>
|
||||
<u-form-item label="上级字典" :label-width="configOption.labelWidth || 160">
|
||||
<u-input v-model="parentData.dictValue" disabled placeholder="上级字典" />
|
||||
</u-form-item>
|
||||
<u-form-item label="字典键值" prop="dictKey" :label-width="configOption.labelWidth || 160" required>
|
||||
<u-input v-model="childForm.dictKey" :disabled="readonly" placeholder="字典键值" />
|
||||
</u-form-item>
|
||||
<u-form-item label="字典排序" prop="sort" :label-width="configOption.labelWidth || 160" required>
|
||||
<u-input v-model="childForm.sort" :disabled="readonly" type="number" placeholder="字典排序" />
|
||||
</u-form-item>
|
||||
<u-form-item label="封存" prop="isSealed" :label-width="configOption.labelWidth || 160" required>
|
||||
<u-radio-group v-model="childForm.isSealed" :disabled="readonly">
|
||||
<u-radio shape="circle" :name="1" active-color="#4E7FF9">是</u-radio>
|
||||
<u-radio shape="circle" :name="0" active-color="#4E7FF9">否</u-radio>
|
||||
</u-radio-group>
|
||||
</u-form-item>
|
||||
<u-form-item label="字典备注" prop="remark" :label-width="configOption.labelWidth || 160">
|
||||
<u-input
|
||||
v-model="childForm.remark"
|
||||
:disabled="readonly"
|
||||
type="textarea"
|
||||
:maxlength="-1"
|
||||
:height="35"
|
||||
placeholder="字典备注"
|
||||
/>
|
||||
</u-form-item>
|
||||
</template>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="childLoadStatus" @loadmore="getChild()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</scroll-view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import { parentList, add, update, remove, dictionary, child, dictTree } from '@/api/system/dict.js'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd },
|
||||
data() {
|
||||
return {
|
||||
configShow: false, //字典管理弹窗
|
||||
form: {
|
||||
isSealed: 0
|
||||
},
|
||||
list: [],
|
||||
params: {
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
readonly: false, // 查看时控制表单只读
|
||||
parentData: {}, // 上级数据信息
|
||||
childList: [],
|
||||
childForm: {
|
||||
isSealed: 0
|
||||
},
|
||||
childParams: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
parentId: null
|
||||
},
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
childLoadStatus: 'loadmore', // 列表加载状态
|
||||
option: {
|
||||
navTitle: '字典管理', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '字典编号',
|
||||
prop: 'code'
|
||||
},
|
||||
{
|
||||
label: '字典名称',
|
||||
prop: 'dictValue'
|
||||
},
|
||||
|
||||
{
|
||||
label: '字典排序',
|
||||
prop: 'sort'
|
||||
},
|
||||
{
|
||||
label: '封存',
|
||||
prop: 'sealedName'
|
||||
},
|
||||
{
|
||||
label: '字典备注',
|
||||
prop: 'remark'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
},
|
||||
{
|
||||
name: '设置',
|
||||
icon: 'setting',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
configName: '',
|
||||
configOption: {
|
||||
navBackIcon: 'close', //导航栏左上角icon
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '字典编号',
|
||||
prop: 'code'
|
||||
},
|
||||
{
|
||||
label: '字典名称',
|
||||
prop: 'dictValue'
|
||||
},
|
||||
{
|
||||
label: '字典键值',
|
||||
prop: 'dictKey'
|
||||
},
|
||||
{
|
||||
label: '字典排序',
|
||||
prop: 'sort'
|
||||
},
|
||||
{
|
||||
label: '封存',
|
||||
prop: 'sealedName'
|
||||
},
|
||||
{
|
||||
label: '字典备注',
|
||||
prop: 'remark'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
},
|
||||
{
|
||||
name: '新增子项',
|
||||
icon: 'plus',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
code: [{ required: true, message: '请输入字典编号', trigger: 'blur' }],
|
||||
dictValue: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '请输入字典排序', trigger: 'blur', type: 'number' }],
|
||||
isSealed: [{ required: true, message: '请选择是否封存', trigger: 'blur', type: 'number' }],
|
||||
dictKey: [{ required: true, message: '请输入字典键值', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.getList(true)
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
this.getChild(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
|
||||
if (this.childLoadStatus == 'nomore') return
|
||||
this.getChild()
|
||||
},
|
||||
methods: {
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
parentList(this.params)
|
||||
.then(res => {
|
||||
const { records } = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.list = records
|
||||
} else {
|
||||
this.list = this.list.concat(records)
|
||||
}
|
||||
if (this.list && this.list.length > 0) {
|
||||
this.list.map(e => {
|
||||
e.sealedName = e.isSealed ? '是' : '否'
|
||||
})
|
||||
}
|
||||
this.params.current++
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
// 获取子类列表
|
||||
getChild(override = false) {
|
||||
if (override) {
|
||||
this.childParams.current = 1
|
||||
}
|
||||
const { size } = this.childParams
|
||||
child(this.childParams)
|
||||
.then(res => {
|
||||
const records = res.data
|
||||
if (records.length < size) this.childLoadStatus = 'nomore'
|
||||
else this.childLoadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.childList = records
|
||||
} else {
|
||||
this.childList = this.childList.concat(records)
|
||||
}
|
||||
if (this.childList && this.childList.length > 0) {
|
||||
this.childList.map(e => {
|
||||
e.sealedName = e.isSealed ? '是' : '否'
|
||||
})
|
||||
}
|
||||
this.childParams.current++
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
switch (name) {
|
||||
case '新增':
|
||||
if (this.parentData.code) {
|
||||
this.$set(this.childForm, 'code', this.parentData.code)
|
||||
this.$set(this.childForm, 'parentId', this.parentData.id)
|
||||
this.$set(this.childParams, 'parentId', this.parentData.id)
|
||||
}
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
if (data.id) done()
|
||||
break
|
||||
case '设置':
|
||||
this.childForm = {}
|
||||
this.parentData = data
|
||||
this.configName = data.dictValue
|
||||
this.$set(this.childParams, 'parentId', data.id)
|
||||
this.getChild(true)
|
||||
setTimeout(() => {
|
||||
this.configShow = true
|
||||
}, 100)
|
||||
break
|
||||
case '新增子项':
|
||||
this.childForm = {}
|
||||
this.parentData = data
|
||||
this.$set(this.childForm, 'code', data.code)
|
||||
this.$set(this.childForm, 'parentId', data.id)
|
||||
this.$set(this.childParams, 'parentId', data.id)
|
||||
done()
|
||||
break
|
||||
}
|
||||
if (['删除', '编辑', '新增子项'].includes(name)) {
|
||||
this.$refs['crud'].hideChildren()
|
||||
this.$refs['childCrud'].hideChildren()
|
||||
}
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增' || action == '新增子项') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
},
|
||||
//字典配置关闭
|
||||
onConfigClose() {
|
||||
this.configShow = false
|
||||
this.childParams = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
parentId: null
|
||||
}
|
||||
this.parentData = {}
|
||||
this.form = { isSealed: 0 }
|
||||
this.childForm = { isSealed: 0 }
|
||||
setTimeout(() => {
|
||||
this.getChild(true)
|
||||
})
|
||||
},
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
dictValue: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 子级搜索
|
||||
onChildSearch(val) {
|
||||
this.childForm = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
dictValue: val
|
||||
}
|
||||
this.getChild(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.nav-right {
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: normal;
|
||||
padding-right: 24rpx;
|
||||
}
|
||||
|
||||
.config-title {
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 20rpx solid #f5f5f5;
|
||||
color: #fff;
|
||||
background: linear-gradient(45deg, #4e7ff9 0%, #59a5fb 100%);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar
|
||||
:is-fixed="false"
|
||||
:border-bottom="false"
|
||||
:is-back="false"
|
||||
title="管理"
|
||||
:background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }"
|
||||
title-color="#fff"
|
||||
>
|
||||
<image slot="right" src="/static/images/home/message.png" class="message-icon" mode="widthFix"></image>
|
||||
</u-navbar>
|
||||
|
||||
<view class="tab">
|
||||
<u-tabs
|
||||
:list="list"
|
||||
:is-scroll="false"
|
||||
:current="current"
|
||||
active-color="#5f88ff"
|
||||
inactive-color="#595959"
|
||||
height="100"
|
||||
@change="change"
|
||||
></u-tabs>
|
||||
</view>
|
||||
|
||||
<swiper id="swiperBox" :style="{ height: swiperHeight + 'px' }" :current="current" @change="tabsChange">
|
||||
|
||||
<swiper-item class="swiper-item" key="0">
|
||||
<scroll-view scroll-y style="width: 100%;height: 100%;" @scrolltolower="onreachBottom">
|
||||
<view class="content">
|
||||
<u-grid :col="3">
|
||||
<u-grid-item v-for="(_item, _index) in deskList" :key="_index">
|
||||
<navigator :url="_item.path" hover-class="none" class="gitem">
|
||||
<image :src="require(`@/static/images/manage/${_item.type}.png`)" class="img" mode="widthFix"></image>
|
||||
<view class="name">{{ _item.name }}</view>
|
||||
</navigator>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
|
||||
<swiper-item class="swiper-item" key="1">
|
||||
<scroll-view scroll-y style="width: 100%;height: 100%;" @scrolltolower="onreachBottom">
|
||||
<view class="content">
|
||||
<u-grid :col="3">
|
||||
<u-grid-item v-for="(_item, _index) in systemList" :key="_index">
|
||||
<navigator :url="_item.path" hover-class="none" class="gitem">
|
||||
<image :src="require(`@/static/images/manage/${_item.type}.png`)" class="img" mode="widthFix"></image>
|
||||
<view class="name">{{ _item.name }}</view>
|
||||
</navigator>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
current: 0,
|
||||
swiperHeight: 0,
|
||||
list: [
|
||||
{
|
||||
name: '工作台'
|
||||
},
|
||||
{
|
||||
name: '系统'
|
||||
},
|
||||
],
|
||||
deskList: [
|
||||
{
|
||||
name: '公告',
|
||||
type: 'notice',
|
||||
path: '/pages/manage/notice'
|
||||
},
|
||||
],
|
||||
systemList: [
|
||||
{
|
||||
name: '角色',
|
||||
type: 'role',
|
||||
path: '/pages/manage/role'
|
||||
},
|
||||
{
|
||||
name: '部门',
|
||||
type: 'dept',
|
||||
path: '/pages/manage/dept'
|
||||
},
|
||||
{
|
||||
name: '字典',
|
||||
type: 'dict',
|
||||
path: '/pages/manage/dict'
|
||||
},
|
||||
{
|
||||
name: '岗位',
|
||||
type: 'post',
|
||||
path: '/pages/manage/post'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
let that = this
|
||||
uni.getSystemInfo({
|
||||
success(e) {
|
||||
console.log(e)
|
||||
let { windowWidth, windowHeight, safeArea } = e
|
||||
const query = uni.createSelectorQuery().in(that)
|
||||
query
|
||||
.select('#swiperBox')
|
||||
.boundingClientRect(data => {
|
||||
that.swiperHeight = safeArea.bottom - data.top
|
||||
})
|
||||
.exec()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
tabsChange(e) {
|
||||
this.current = e.detail.current
|
||||
},
|
||||
change(index) {
|
||||
this.current = index
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.swiper-box {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.message-icon {
|
||||
width: 32rpx;
|
||||
height: auto;
|
||||
margin-right: 27rpx;
|
||||
}
|
||||
|
||||
.tab {
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.gitem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
|
||||
.img {
|
||||
width: 54rpx;
|
||||
height: auto;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #030305;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@search="onSearch"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<view slot="form">
|
||||
<u-form-item label="通知标题" prop="title" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.title" :disabled="readonly" placeholder="通知标题" />
|
||||
</u-form-item>
|
||||
<u-form-item label="通知类型" prop="category" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-model="formLabel.category"
|
||||
:disabled="readonly"
|
||||
placeholder="通知类型"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) categoryShow = true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="通知日期" prop="releaseTime" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-model="form.releaseTime"
|
||||
:disabled="readonly"
|
||||
placeholder="通知日期"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) timeShow = true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="通知内容" :label-width="option.labelWidth || 160" :border-bottom="false">
|
||||
<template #right v-if="!readonly">
|
||||
<u-button
|
||||
@click="onRichEdit(form.content)"
|
||||
ripple
|
||||
:custom-style="{ background: '#FFF6E9', color: '#FAA646' }"
|
||||
size="mini"
|
||||
>
|
||||
去编辑
|
||||
</u-button>
|
||||
</template>
|
||||
</u-form-item>
|
||||
<mp-html :content="form.content"></mp-html>
|
||||
</view>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
<!-- 通知类型 -->
|
||||
<u-select
|
||||
v-model="categoryShow"
|
||||
:list="categoryList"
|
||||
value-name="dictKey"
|
||||
label-name="dictValue"
|
||||
@confirm="e => onConfirm(e, 'category')"
|
||||
safe-area-inset-bottom
|
||||
></u-select>
|
||||
<!-- 通知日期 -->
|
||||
<u-picker
|
||||
mode="time"
|
||||
v-model="timeShow"
|
||||
:params="timeParams"
|
||||
start-year="2000"
|
||||
end-year="2050"
|
||||
@confirm="e => onConfirm(e, 'releaseTime')"
|
||||
safe-area-inset-bottom
|
||||
></u-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import mpHtml from '@/components/rider-crud/components/mp-html/mp-html'
|
||||
import { getList, add, update, remove } from '@/api/notice.js'
|
||||
import { dictionary } from '@/api/system/dict.js'
|
||||
import { logo } from '../../common/setting'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd, mpHtml },
|
||||
data() {
|
||||
return {
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
checkedSwitch: false, // 默认打开管理
|
||||
form: { content: '' }, // 表单
|
||||
formLabel: {}, // 表单label
|
||||
list: [], // 列表数据
|
||||
params: {
|
||||
// 分页
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
readonly: false, // 查看时控制表单只读
|
||||
option: {
|
||||
// 组件选项
|
||||
navTitle: '通知公告', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '通知标题',
|
||||
prop: 'title'
|
||||
},
|
||||
{
|
||||
label: '通知类型',
|
||||
prop: 'categoryName'
|
||||
},
|
||||
{
|
||||
label: '通知日期',
|
||||
prop: 'releaseTime'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
// 左滑操作按钮
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
// 表单校验规则
|
||||
title: [{ required: true, message: '请输入通知标题', trigger: 'blur' }],
|
||||
category: [{ required: true, message: '请选择通知类型', trigger: 'change', type: 'number' }],
|
||||
releaseTime: [{ required: true, message: '请选择通知日期', trigger: 'change' }]
|
||||
},
|
||||
timeShow: false,
|
||||
timeParams: {
|
||||
year: true,
|
||||
month: true,
|
||||
day: true,
|
||||
hour: true,
|
||||
minute: true,
|
||||
second: true
|
||||
},
|
||||
categoryShow: false,
|
||||
categoryList: [] //类型
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
let that = this
|
||||
uni.$on('richBack', function(data) {
|
||||
that.$set(that.form, 'content', data)
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.getList(true)
|
||||
this.getCategoryList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
getList(this.params)
|
||||
.then(res => {
|
||||
const { records, current } = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.list = records
|
||||
} else {
|
||||
this.list = this.list.concat(records)
|
||||
}
|
||||
this.params.current++
|
||||
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
// 通知类型
|
||||
getCategoryList() {
|
||||
dictionary({ code: 'notice' }).then(res => {
|
||||
this.categoryList = res.data
|
||||
})
|
||||
},
|
||||
// 类型回调
|
||||
onConfirm(e, type) {
|
||||
if (type == 'category') {
|
||||
this.formLabel[type] = e[0].label
|
||||
this.form.category = Number(e[0].value)
|
||||
} else {
|
||||
this.$set(this.form, 'releaseTime', e.year + '-' + e.month + '-' + e.day + ' ' + e.hour + ':' + e.minute + ':' + e.second)
|
||||
}
|
||||
},
|
||||
// 编辑富文本
|
||||
onRichEdit(e) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/rich/index?data=${e}`
|
||||
})
|
||||
},
|
||||
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
title: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
switch (name) {
|
||||
case '新增':
|
||||
this.formLabel = {}
|
||||
this.form = { content: '' }
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
this.formLabel.category = getDicLabel(data.category, this.categoryList)
|
||||
done()
|
||||
break
|
||||
}
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = {}
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = {}
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@search="onSearch"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<template #form>
|
||||
<u-form-item label="岗位类型" prop="category" :label-width="option.labelWidth || 160" required>
|
||||
<u-input
|
||||
v-model="formLabel.category"
|
||||
placeholder="角色名称"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) categoryShow = true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="岗位编号" prop="postCode" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.postCode" :disabled="readonly" placeholder="岗位编号" />
|
||||
</u-form-item>
|
||||
<u-form-item label="岗位名称" prop="postName" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.postName" :disabled="readonly" placeholder="岗位名称" />
|
||||
</u-form-item>
|
||||
<u-form-item label="岗位排序" prop="sort" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.sort" :disabled="readonly" type="number" placeholder="岗位排序" />
|
||||
</u-form-item>
|
||||
<u-form-item label="岗位描述" prop="remark" :label-width="option.labelWidth || 160">
|
||||
<u-input
|
||||
v-model="form.remark"
|
||||
:disabled="readonly"
|
||||
type="textarea"
|
||||
:maxlength="-1"
|
||||
:height="35"
|
||||
placeholder="岗位描述"
|
||||
/>
|
||||
</u-form-item>
|
||||
</template>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
<u-select
|
||||
v-model="categoryShow"
|
||||
:list="categoryList"
|
||||
value-name="dictKey"
|
||||
label-name="dictValue"
|
||||
@confirm="onConfirm"
|
||||
safe-area-inset-bottom
|
||||
></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import { getList, add, update, remove } from '@/api/system/post.js'
|
||||
import { tenantSelect } from '@/api/system/tenant.js'
|
||||
import { dictionary } from '@/api/system/dict.js'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd },
|
||||
data() {
|
||||
return {
|
||||
checkedSwitch: false,
|
||||
form: {},
|
||||
formLabel: {},
|
||||
list: [],
|
||||
params: {
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
readonly: false, // 查看时控制表单只读
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
option: {
|
||||
navTitle: '岗位管理', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '岗位名称',
|
||||
prop: 'postName'
|
||||
},
|
||||
{
|
||||
label: '岗位编号',
|
||||
prop: 'postCode'
|
||||
},
|
||||
{
|
||||
label: '所属租户',
|
||||
prop: 'tenantName'
|
||||
},
|
||||
{
|
||||
label: '岗位类型',
|
||||
prop: 'categoryName'
|
||||
},
|
||||
{
|
||||
label: '岗位排序',
|
||||
prop: 'sort'
|
||||
},
|
||||
{
|
||||
label: '岗位描述',
|
||||
prop: 'remark'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
category: [{ required: true, message: '请选择岗位类型', trigger: 'change', type: 'number' }],
|
||||
postCode: [{ required: true, message: '请输入岗位编号', trigger: 'blur' }],
|
||||
postName: [{ required: true, message: '请输入岗位名称', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '请输入岗位排序', trigger: 'blur', type: 'number' }]
|
||||
},
|
||||
categoryShow: false,
|
||||
categoryList: [],
|
||||
category: '',
|
||||
tenantList: []
|
||||
}
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.getTenant().then(() => {
|
||||
this.getList(true)
|
||||
})
|
||||
this.getCategoryList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
getList(this.params)
|
||||
.then(res => {
|
||||
const { records, current } = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.list = records
|
||||
} else {
|
||||
this.list = this.list.concat(records)
|
||||
}
|
||||
|
||||
if (this.list && this.list.length > 0) {
|
||||
this.list.map(e => {
|
||||
e.tenantName = getDicLabel(e.tenantId, this.tenantList, { label: 'tenantName', value: 'tenantId' })
|
||||
})
|
||||
}
|
||||
this.params.current++
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
// 获取类型
|
||||
getCategoryList() {
|
||||
dictionary({ code: 'post_category' }).then(res => {
|
||||
this.categoryList = res.data
|
||||
})
|
||||
},
|
||||
// 租户类型
|
||||
getTenant() {
|
||||
return new Promise(resolve => {
|
||||
tenantSelect().then(res => {
|
||||
this.tenantList = res.data
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
// 类型回调
|
||||
onConfirm(e) {
|
||||
this.$set(this.form, 'category', Number(e[0].value))
|
||||
this.$set(this.formLabel, 'category', e[0].label)
|
||||
},
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
postName: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
console.log(name, index)
|
||||
switch (name) {
|
||||
case '新增':
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
this.formLabel.category = getDicLabel(data.category, this.categoryList)
|
||||
done()
|
||||
break
|
||||
}
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = {}
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
this.formLabel = {}
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.nav-right {
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: normal;
|
||||
padding-right: 24rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="safe-area-inset-bottom">
|
||||
<rider-curd
|
||||
v-model="form"
|
||||
:option="option"
|
||||
:data="list"
|
||||
:rules="rules"
|
||||
:readonly.sync="readonly"
|
||||
@search="onSearch"
|
||||
@action-click="onActionClick"
|
||||
@submit="onSubmit"
|
||||
@del="onRemove"
|
||||
ref="crud"
|
||||
>
|
||||
<template #form>
|
||||
<u-form-item label="角色名称" prop="roleName" :label-width="option.labelWidth || 160" required>
|
||||
<u-input v-model="form.roleName" :disabled="readonly" placeholder="角色名称" />
|
||||
</u-form-item>
|
||||
<u-form-item label="上级角色" prop="parentId" :label-width="option.labelWidth || 160">
|
||||
<u-input
|
||||
v-model="formLabel.parentName"
|
||||
placeholder="上级角色"
|
||||
type="select"
|
||||
@click="
|
||||
() => {
|
||||
if (!readonly) $refs.treePicker._show()
|
||||
}
|
||||
"
|
||||
/>
|
||||
</u-form-item>
|
||||
<u-form-item label="角色别名" prop="roleAlias" required :label-width="option.labelWidth || 160">
|
||||
<u-input v-model="form.roleAlias" :disabled="readonly" placeholder="角色别名" />
|
||||
</u-form-item>
|
||||
<u-form-item label="角色排序" prop="sort" required :label-width="option.labelWidth || 160">
|
||||
<u-input v-model="form.sort" :disabled="readonly" type="number" placeholder="角色排序" />
|
||||
</u-form-item>
|
||||
</template>
|
||||
<template #loadmore>
|
||||
<u-loadmore :status="loadStatus" @loadmore="getList()" />
|
||||
</template>
|
||||
</rider-curd>
|
||||
</view>
|
||||
<!-- 上级角色tree -->
|
||||
<rider-tree
|
||||
ref="treePicker"
|
||||
:range="roleTreeList"
|
||||
@cancel="$refs.treePicker._hide()"
|
||||
@confirm="onTreeConfirm"
|
||||
idKey="id"
|
||||
nameKey="title"
|
||||
:multiple="false"
|
||||
:cascade="false"
|
||||
:foldAll="false"
|
||||
confirmColor="#4E7FF9"
|
||||
cancelColor="#757575"
|
||||
title="上级角色"
|
||||
titleColor="#757575"
|
||||
></rider-tree>
|
||||
<!-- 菜单权限 -->
|
||||
<rider-tree
|
||||
ref="menuPicker"
|
||||
:range="menuTreeList"
|
||||
@cancel="$refs.menuPicker._hide()"
|
||||
@confirm="onMenuConfirm"
|
||||
idKey="id"
|
||||
nameKey="title"
|
||||
:multiple="true"
|
||||
:cascade="true"
|
||||
:foldAll="true"
|
||||
confirmColor="#4E7FF9"
|
||||
cancelColor="#757575"
|
||||
title="菜单权限"
|
||||
titleColor="#757575"
|
||||
></rider-tree>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import riderCurd from '@/components/rider-crud/index'
|
||||
import riderTree from '@/components/rider-crud/components/tree-picker'
|
||||
import { getList, add, update, remove, roleTree, menuTree, menuTreeKey, grant } from '@/api/system/role.js'
|
||||
import { tenantSelect } from '@/api/system/tenant.js'
|
||||
import { getDicLabel } from '@/components/rider-crud/util/tool.js'
|
||||
export default {
|
||||
components: { riderCurd, riderTree },
|
||||
data() {
|
||||
return {
|
||||
checkedSwitch: false,
|
||||
form: {},
|
||||
formLabel: {},
|
||||
list: [],
|
||||
params: {
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
readonly: false, // 查看时控制表单只读
|
||||
loadStatus: 'loadmore', // 列表加载状态
|
||||
option: {
|
||||
navTitle: '角色管理', //标题
|
||||
manageBtn: true, // 右上角管理按钮,默认不显示
|
||||
searchShow: true, //是否显示搜索,默认不显示
|
||||
labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
|
||||
column: [
|
||||
{
|
||||
label: '角色名称',
|
||||
prop: 'roleName'
|
||||
},
|
||||
{
|
||||
label: '所属租户',
|
||||
prop: 'tenantName'
|
||||
},
|
||||
{
|
||||
label: '角色别名',
|
||||
prop: 'roleAlias'
|
||||
},
|
||||
{
|
||||
label: '角色排序',
|
||||
prop: 'sort'
|
||||
}
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '编辑', // 操作名称
|
||||
icon: 'edit-pen', //操作图标,有图标文字不显示
|
||||
color: '#333', // 字体颜色
|
||||
fontsize: 30, //字体大小,单位rpx
|
||||
width: 40, // 宽度,单位px
|
||||
background: '#fff' // 菜单按钮背景色
|
||||
},
|
||||
{
|
||||
name: '删除',
|
||||
icon: 'trash',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
},
|
||||
{
|
||||
name: '菜单权限',
|
||||
icon: 'setting',
|
||||
color: '#333',
|
||||
fontsize: 30,
|
||||
width: 40,
|
||||
background: '#fff'
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
|
||||
roleAlias: [{ required: true, message: '请输入角色别名', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '请输入角色排序', trigger: 'blur', type: 'number' }]
|
||||
},
|
||||
tenantList: [],
|
||||
roleTreeList: [],
|
||||
menuTreeList: [],
|
||||
menuCheckIds: [],
|
||||
roleIds: null
|
||||
}
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.getTenant().then(() => {
|
||||
this.getList(true)
|
||||
})
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.getList(true)
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.loadStatus == 'nomore') return
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取列表
|
||||
getList(override = false) {
|
||||
if (override) {
|
||||
this.params.current = 1
|
||||
}
|
||||
const { size } = this.params
|
||||
getList(this.params)
|
||||
.then(res => {
|
||||
const records = res.data
|
||||
if (records.length < size) this.loadStatus = 'nomore'
|
||||
else this.loadStatus = 'loadmore'
|
||||
if (override) {
|
||||
this.list = records
|
||||
} else {
|
||||
this.list = this.list.concat(records)
|
||||
}
|
||||
if (this.list && this.list.length > 0) {
|
||||
this.list = this.filterList(this.list)
|
||||
}
|
||||
this.params.current++
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
.catch(err => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
filterList(list) {
|
||||
if (!list || list.length == 0) return list
|
||||
list.forEach(e => {
|
||||
e.tenantName = getDicLabel(e.tenantId, this.tenantList, { label: 'tenantName', value: 'tenantId' })
|
||||
if (e.children) this.filterList(e.children)
|
||||
})
|
||||
return list
|
||||
},
|
||||
// 租户类型
|
||||
getTenant() {
|
||||
return new Promise(resolve => {
|
||||
roleTree().then(res => {
|
||||
this.roleTreeList = res.data
|
||||
})
|
||||
tenantSelect().then(res => {
|
||||
this.tenantList = res.data
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取菜单权限内容
|
||||
getMenu(roleIds) {
|
||||
menuTreeKey({ roleIds }).then(res => {
|
||||
this.menuCheckIds = res.data.menu
|
||||
})
|
||||
menuTree().then(res => {
|
||||
this.recursion(this.menuCheckIds, res.data.menu)
|
||||
this.menuTreeList = res.data.menu
|
||||
setTimeout(() => {
|
||||
this.$refs.menuPicker._show()
|
||||
}, 10)
|
||||
})
|
||||
},
|
||||
// 递归
|
||||
recursion(arr, menu) {
|
||||
menu.forEach(e => {
|
||||
if (arr.includes(e.id)) e.checked = true
|
||||
if (e.hasChildren || (e.children && e.children.length > 0)) {
|
||||
this.recursion(arr, e.children)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 菜单权限勾选回调
|
||||
onMenuConfirm(e) {
|
||||
let arr = []
|
||||
e.forEach(e => {
|
||||
arr.push(e.id)
|
||||
})
|
||||
const params = {
|
||||
apiScopeIds: [],
|
||||
dataScopeIds: [],
|
||||
roleIds: [this.roleIds],
|
||||
menuIds: arr
|
||||
}
|
||||
grant(params).then(res => {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '操作成功'
|
||||
})
|
||||
})
|
||||
},
|
||||
//机构选择回调
|
||||
onTreeConfirm(e) {
|
||||
this.$set(this.form, 'parentId', e[0].id)
|
||||
this.$set(this.formLabel, 'parentName', e[0].name)
|
||||
},
|
||||
// 搜索 (自行配置搜索内容)
|
||||
onSearch(val) {
|
||||
this.params = {
|
||||
current: 1,
|
||||
size: 10,
|
||||
roleName: val
|
||||
}
|
||||
this.getList(true)
|
||||
},
|
||||
// 左滑按钮点击
|
||||
onActionClick({ index, data, action, done }) {
|
||||
const { name } = action
|
||||
console.log(name, index)
|
||||
switch (name) {
|
||||
case '新增':
|
||||
done()
|
||||
break
|
||||
case '删除':
|
||||
this.onRemove(data.id)
|
||||
break
|
||||
case '查看':
|
||||
this.readonly = true
|
||||
case '编辑':
|
||||
this.$set(this.formLabel, 'parentName', data.parentName)
|
||||
done()
|
||||
break
|
||||
case '菜单权限':
|
||||
this.roleIds = data.id
|
||||
this.getMenu(data.id)
|
||||
break
|
||||
}
|
||||
if (['删除', '编辑'].includes(name)) this.$refs['crud'].hideChildren()
|
||||
},
|
||||
// 删除
|
||||
onRemove(id) {
|
||||
uni.showModal({
|
||||
title: '确定要删除吗?',
|
||||
success: action => {
|
||||
if (action.confirm) {
|
||||
remove(id).then(() => {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$refs['crud'].allCheckHide(false)
|
||||
}, 100)
|
||||
// #ifdef APP
|
||||
this.getList(true)
|
||||
// #endif
|
||||
// #ifndef APP
|
||||
uni.startPullDownRefresh({})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
onSubmit(form, action, unloading, done) {
|
||||
if (action == '新增') {
|
||||
add(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'none'
|
||||
})
|
||||
// this.category = ''
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
} else if (action == '编辑') {
|
||||
update(form)
|
||||
.then(res => {
|
||||
uni.showToast({
|
||||
title: '编辑成功',
|
||||
icon: 'none'
|
||||
})
|
||||
// this.category = ''
|
||||
done()
|
||||
uni.startPullDownRefresh({})
|
||||
})
|
||||
.catch(() => {
|
||||
unloading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.nav-right {
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: normal;
|
||||
padding-right: 24rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
|
||||
<!-- 蓝色头部信息区 -->
|
||||
<view class="header-section">
|
||||
<view class="serial-no">流水号:{{orderInfo.code}}</view>
|
||||
<view class="time-info">{{orderInfo.bookingTime}}</view>
|
||||
<view class="project-info"> {{orderInfo.itemName}} </view>
|
||||
</view>
|
||||
|
||||
<!-- 取号信息卡片 -->
|
||||
<view class="info-card new-card" v-if="isTicketInfoShow">
|
||||
<view class="ticket_status">无感取号成功</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">排队号</text>
|
||||
<text class="info-value">{{ticketInfo.queueNum}}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">窗口号</text>
|
||||
<text class="info-value">{{ticketInfo.counterlist}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详情信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<text class="info-label">预约大厅</text>
|
||||
<text class="info-value">广西区直住房保障中心</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">预约部门</text>
|
||||
<text class="info-value">{{orderInfo.deptName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<text class="info-label">姓名</text>
|
||||
<text class="info-value">{{ userinfo.name }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">手机号</text>
|
||||
<text class="info-value">{{ userinfo.phone }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">证件类型</text>
|
||||
<text class="info-value">身份证</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">证件号码</text>
|
||||
<text class="info-value">{{ userinfo.idCard }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 取消预约按钮 -->
|
||||
<view class="btn-wrap">
|
||||
<button class="btn-cancel" v-if="orderInfo.status==1" @click="handleCancel">取消预约</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getDetail,
|
||||
getUserInfo,
|
||||
cancel,
|
||||
getIsSuccessTicket
|
||||
} from '@/api/reserve.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 可通过页面传参动态获取以下数据
|
||||
isTicketInfoShow: false,
|
||||
ticketInfo: {},
|
||||
orderInfo: {},
|
||||
userinfo: {},
|
||||
id: '',
|
||||
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.id = options.id
|
||||
this.getTicketInfo()
|
||||
this.getUserInfo()
|
||||
this.getDetail()
|
||||
|
||||
},
|
||||
methods: {
|
||||
// 取号详情
|
||||
getTicketInfo() {
|
||||
getIsSuccessTicket({
|
||||
yyNo: this.id
|
||||
}).then(res => {
|
||||
if (res.code) {
|
||||
this.isTicketInfoShow = Object.keys(res.data).length > 0 ? true : false
|
||||
this.ticketInfo = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
// 预约详情
|
||||
getDetail() {
|
||||
getDetail({
|
||||
id: this.id
|
||||
}).then(res => {
|
||||
this.orderInfo = res.data
|
||||
|
||||
})
|
||||
},
|
||||
// 个人信息详情
|
||||
getUserInfo() {
|
||||
getUserInfo().then(res => {
|
||||
this.userinfo = res.data
|
||||
})
|
||||
},
|
||||
// 返回上一页
|
||||
handleGoBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
// 取消预约
|
||||
handleCancel() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消该预约吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
cancel({
|
||||
id: this.orderInfo.id
|
||||
}).then(res => {
|
||||
if (res.code == 200) {
|
||||
uni.showToast({
|
||||
title: '取消成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({
|
||||
delta: 1 // 返回的页面数
|
||||
})
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 蓝色头部信息区 */
|
||||
.header-section {
|
||||
width: 100%;
|
||||
background: linear-gradient(to right, rgba(75, 112, 252, 1), rgba(67, 195, 252, 1));
|
||||
padding: 40rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.serial-no {
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.time-info {
|
||||
font-size: 38rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
margin-bottom: 15rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.project-info {
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
line-height: 1.5;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
/* 信息卡片 */
|
||||
.info-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
margin: 20rpx 30rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.new-card {
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.ticket_status {
|
||||
margin: 0 auto;
|
||||
padding: 10rpx 32rpx;
|
||||
width: fit-content;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: rgba(3, 195, 106, 1);
|
||||
background-color: rgba(220, 255, 239, 1);
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
width: 220rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
font-size: 34rpx;
|
||||
color: #333333;
|
||||
text-align: right;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 取消预约按钮 */
|
||||
.btn-wrap {
|
||||
padding: 20rpx 30rpx 40rpx;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(255, 239, 239, 1);
|
||||
color: rgba(244, 54, 54, 1);
|
||||
border-radius: 44rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(255, 195, 195, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 预约列表 -->
|
||||
<view class="list-container">
|
||||
<!-- 预约成功状态 -->
|
||||
<view class="reserve-item" v-for="(item, index) in successList" :key="`success-${index}`">
|
||||
<view class="item-header">
|
||||
<text class="item-time">{{ item.bookingTime }}</text>
|
||||
<text
|
||||
:class="['status', item.status == 1 ? 'success' : 'canceled']">{{ item.status == 1 ? '预约成功' : '已取消' }}</text>
|
||||
</view>
|
||||
<view class="item-content">
|
||||
<text class="item-project">{{ item.itemName }}</text>
|
||||
</view>
|
||||
<view class="item-btns">
|
||||
<button class="btn-cancel" v-if="item.status == 1" @click="handleCancel(item)">取消预约</button>
|
||||
<button class="btn-cancel" v-if="item.status == 4">{{getStatus(item.status)}}</button>
|
||||
<button class="btn-detail" @click="handleDetail(item)">查看详情</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-tip" v-if="successList.length === 0"> 暂无预约记录 </view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getUserInfo,
|
||||
myReserve,
|
||||
cancel
|
||||
} from '@/api/reserve.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 预约成功列表(和设计图完全一致)
|
||||
successList: [],
|
||||
userinfo: {},
|
||||
statusList: [],
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.getUserInfo()
|
||||
this.statusList = uni.getStorageSync('statusList');
|
||||
},
|
||||
methods: {
|
||||
getStatus(code){
|
||||
return this.statusList.find(item=>item.dictKey == code)?.dictValue
|
||||
},
|
||||
getUserInfo() {
|
||||
getUserInfo().then(res => {
|
||||
this.userinfo = res.data
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
let params = {
|
||||
size: 10,
|
||||
current: 1,
|
||||
idCard: this.userinfo.idCard,
|
||||
descs: 'update_time'
|
||||
}
|
||||
myReserve(params).then(res => {
|
||||
this.successList = res.data.records
|
||||
})
|
||||
},
|
||||
// 返回上一页
|
||||
handleGoBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
// 取消预约
|
||||
handleCancel(item) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消该预约吗?',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
cancel({
|
||||
id: item.id
|
||||
}).then(res => {
|
||||
if (res.code == 200) {
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 查看详情
|
||||
handleDetail(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/myReserve/detail?id=${item.id}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 列表容器 */
|
||||
.list-container {
|
||||
flex: 1;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
/* 预约项卡片 */
|
||||
.reserve-item {
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.item-time {
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.status.success {
|
||||
background-color: #e6f9e6;
|
||||
color: #00b578;
|
||||
}
|
||||
|
||||
.status.canceled {
|
||||
background-color: #f0f0f0;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.item-project {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.item-btns {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
margin: 0;
|
||||
width: 200rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
background-color: rgba(255, 239, 239, 1);
|
||||
color: rgba(244, 54, 54, 1);
|
||||
border-radius: 35rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(255, 195, 195, 1);
|
||||
}
|
||||
|
||||
.btn-detail {
|
||||
margin: 0;
|
||||
width: 200rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
background-color: rgba(242, 247, 255, 1);
|
||||
color: rgba(49, 134, 255, 1);
|
||||
border-radius: 35rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
|
||||
/* 空状态提示 */
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 100rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward" title="新闻详情页"
|
||||
:background="{ background: '#fff' }" title-color="#000000">
|
||||
<view class="right-nav" slot="right">
|
||||
<image src="/static/images/news/search.png" class="icon icon-search" mode="widthFix"></image>
|
||||
<image src="/static/images/news/menu.png" class="icon icon-menu" mode="widthFix"></image>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<view class="header">
|
||||
<image src="" class="avatar" mode=""></image>
|
||||
<view class="info">
|
||||
<view class="name">
|
||||
中国空间站
|
||||
<text class="tag">专栏作家</text>
|
||||
</view>
|
||||
<view class="date">11-12</view>
|
||||
</view>
|
||||
<view class="btn">+关注</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<view class="title">
|
||||
天舟五号创造多个航天新纪录
|
||||
</view>
|
||||
<view class="static">
|
||||
<view class="left">
|
||||
<view class="block">
|
||||
<image src="/static/images/news/gf.png" class="gf"></image>
|
||||
官方
|
||||
</view>
|
||||
<view class="block">
|
||||
<image src="/static/images/news/x.png" class="gf"></image>
|
||||
焦点新闻
|
||||
</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<image src="/static/images/news/l.png" class="l" mode="widthFix"></image>
|
||||
66666
|
||||
</view>
|
||||
</view>
|
||||
<view class="detail">
|
||||
<u-parse :html="content"></u-parse>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="footer">
|
||||
<input type="text" value="" placeholder="说点什么..." class="ipt" />
|
||||
<view class="control">
|
||||
<view class="block">
|
||||
<image src="/static/images/news/c.png" class="icon c" mode="widthFix"></image>
|
||||
458
|
||||
</view>
|
||||
<view class="block">
|
||||
<image src="/static/images/news/s.png" class="icon s" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="block">
|
||||
<image src="/static/images/news/t.png" class="icon t" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
content: `<p>在北京航天飞行控制中心拍摄的天舟五号货运飞船与空间站组合体完成自主快速交会对接示意图。孙丰晓摄(新华社发)</p>
|
||||
<p>北京时间2022年11月12日10时03分,在文昌航天发射场,搭载天舟五号货运飞船的长征七号遥六运载火箭点火发射,将天舟五号货运飞船送入预定轨道。随后,天舟五号货运飞船与在轨运行的空间站组合体进行自主快速交会对接,中国航天员首次在空间站迎接货运飞船来访。</p>
|
||||
<p>朝着在距离地面约400公里轨道上运行的中国空间站组合体,天舟五号首次实现2小时自主快速交会对接,创造世界纪录。这一技术突破对于提升我国空间交会对接水平,提升空间站任务应急物资补给能力具有重要意义。</p>
|
||||
<p>空间站阶段最快交会对接,让人类航天器交会对接用时进入“2小时”时代。</p>
|
||||
<p>此次任务是中国空间站“T”字基本构型在轨组装完成后,“太空快递”首次送达,执行运输任务的仍是长七火箭。</p>`
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 0 0 150rpx;
|
||||
}
|
||||
|
||||
.right-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 40rpx;
|
||||
|
||||
.icon {
|
||||
height: auto;
|
||||
|
||||
&-search {
|
||||
width: 40rpx;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
|
||||
&-menu {
|
||||
width: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 44rpx;
|
||||
|
||||
.avatar {
|
||||
flex-shrink: 0;
|
||||
width: 69rpx;
|
||||
height: 69rpx;
|
||||
background: #ffffff;
|
||||
border: 1px solid #69b0ff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
margin-left: 14rpx;
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
line-height: 36rpx;
|
||||
|
||||
.tag {
|
||||
margin-left: 10rpx;
|
||||
display: inline-block;
|
||||
padding: 8rpx 10rpx;
|
||||
font-size: 14rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #4cbeca;
|
||||
line-height: 21rpx;
|
||||
border: 1px solid #0bb9c8;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #a3a3a3;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8rpx 19rpx;
|
||||
background: #e6e6e6;
|
||||
border-radius: 6rpx;
|
||||
font-size: 20rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #4cbeca;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 44rpx;
|
||||
|
||||
.title {
|
||||
font-size: 40rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
line-height: 47rpx;
|
||||
}
|
||||
|
||||
.static {
|
||||
margin-top: 34rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
font-size: 20rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #787878;
|
||||
line-height: 1;
|
||||
|
||||
.gf {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
font-size: 20rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #787878;
|
||||
line-height: 1;
|
||||
|
||||
.l {
|
||||
width: 25rpx;
|
||||
height: auto;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
line-height: 47rpx;
|
||||
margin-top: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
height: 100rpx;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ffffff;
|
||||
|
||||
.ipt {
|
||||
width: 380rpx;
|
||||
height: 77rpx;
|
||||
background: #f7f7f7;
|
||||
border-radius: 38px;
|
||||
padding: 0 37rpx;
|
||||
box-sizing: border-box;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.control {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
|
||||
.block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.c {
|
||||
width: 41rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.s {
|
||||
width: 36rpx;
|
||||
}
|
||||
|
||||
.t {
|
||||
width: 31rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" title="新闻动态" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }"
|
||||
title-color="#fff">
|
||||
<image slot="right" src="/static/images/home/message.png" class="message-icon" mode="widthFix"></image>
|
||||
</u-navbar>
|
||||
|
||||
<view class="tab">
|
||||
<u-tabs :list="tabs" :is-scroll="false" :current="current" active-color="#69b0ff" inactive-color="#595959"
|
||||
height="100" @change="change"></u-tabs>
|
||||
</view>
|
||||
|
||||
<swiper id="swiperBox" :style="{ height: swiperHeight + 'px' }" :current="current" @change="tabsChange">
|
||||
<swiper-item class="swiper-item" v-for="(pitem, pindex) in tabs" :key="pindex">
|
||||
<scroll-view scroll-y style="width: 100%;height: 100%;" refresher-enabled
|
||||
:refresher-triggered="pitem.triggered" @scrolltolower="onreachBottom"
|
||||
@refresherrefresh="refresherrefresh(pindex)" @refresherrestore="refresherrestore(pindex)"
|
||||
@refresherabort="refresherabort(pindex)">
|
||||
<view class="content">
|
||||
<navigator class="news" v-for="(item, index) in contentList[pindex].list" :key="index"
|
||||
url="/pages/news/detail" hover-class="none">
|
||||
<view class="head">
|
||||
<image src="" class="avatar" mode=""></image>
|
||||
<view class="info">
|
||||
<view class="name">
|
||||
中国空间站
|
||||
<text class="tag">专栏作家</text>
|
||||
</view>
|
||||
<view class="date">11-12</view>
|
||||
</view>
|
||||
<u-icon name="arrow-right" size="35" color="#C5C5C5"></u-icon>
|
||||
</view>
|
||||
<view class="des">
|
||||
天舟五号创造多个航天新纪录。
|
||||
</view>
|
||||
</navigator>
|
||||
<view class="nomore">
|
||||
<u-loadmore :status="contentList[pindex].status" />
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
swiperHeight: 0,
|
||||
tabs: [{
|
||||
name: '互动',
|
||||
triggered: false,
|
||||
_triggered: false
|
||||
},
|
||||
{
|
||||
name: '动态',
|
||||
triggered: false,
|
||||
_triggered: false
|
||||
},
|
||||
{
|
||||
name: '通知',
|
||||
triggered: false,
|
||||
_triggered: false
|
||||
}
|
||||
],
|
||||
contentList: [{
|
||||
list: 8,
|
||||
page: 1,
|
||||
status: 'loadmore'
|
||||
},
|
||||
{
|
||||
list: 8,
|
||||
page: 1,
|
||||
status: 'loadmore'
|
||||
},
|
||||
{
|
||||
list: 8,
|
||||
page: 1,
|
||||
status: 'loadmore'
|
||||
}
|
||||
],
|
||||
current: 0
|
||||
};
|
||||
},
|
||||
onLoad() {},
|
||||
onReady() {
|
||||
let that = this;
|
||||
uni.getSystemInfo({
|
||||
success(e) {
|
||||
console.log(e);
|
||||
let {
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
safeArea
|
||||
} = e;
|
||||
const query = uni.createSelectorQuery().in(that);
|
||||
query
|
||||
.select('#swiperBox')
|
||||
.boundingClientRect(data => {
|
||||
that.swiperHeight = safeArea.bottom - data.top;
|
||||
})
|
||||
.exec();
|
||||
}
|
||||
});
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 1500);
|
||||
},
|
||||
methods: {
|
||||
tabsChange(e) {
|
||||
this.current = e.detail.current;
|
||||
},
|
||||
refresherrefresh(index) {
|
||||
console.log('自定义下拉刷新被触发');
|
||||
let _this = this;
|
||||
if (_this.tabs[index]._triggered) {
|
||||
return;
|
||||
}
|
||||
_this.tabs[index]._triggered = true;
|
||||
//界面下拉触发,triggered可能不是true,要设为true
|
||||
if (!_this.tabs[index].triggered) {
|
||||
_this.tabs[index].triggered = true;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
_this.tabs[index].triggered = false; //触发onRestore,并关闭刷新图标
|
||||
_this.tabs[index]._triggered = false;
|
||||
}, 10);
|
||||
},
|
||||
refresherrestore(index) {
|
||||
console.log('自定义下拉刷新被复位');
|
||||
let _this = this;
|
||||
_this.tabs[index].triggered = false;
|
||||
_this.tabs[index]._triggered = false;
|
||||
},
|
||||
refresherabort(index) {
|
||||
console.log('自定义下拉刷新被中止 ');
|
||||
let _this = this;
|
||||
_this.tabs[index].triggered = false;
|
||||
_this.tabs[index]._triggered = false;
|
||||
},
|
||||
// scroll-view到底部加载更多
|
||||
onreachBottom() {
|
||||
let current = this.current;
|
||||
if (this.contentList[current].page >= 3) return;
|
||||
this.contentList[current].status = 'loading';
|
||||
setTimeout(() => {
|
||||
this.contentList[current].page = ++this.contentList[current].page;
|
||||
this.contentList[current].list += 10;
|
||||
if (this.contentList[current].page >= 3)
|
||||
this.contentList[current].status = 'nomore';
|
||||
else this.contentList[current].status = 'loading';
|
||||
}, 2000);
|
||||
},
|
||||
change(index) {
|
||||
this.current = index;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message-icon {
|
||||
width: 32rpx;
|
||||
height: auto;
|
||||
margin-right: 27rpx;
|
||||
}
|
||||
|
||||
.tab {
|
||||
margin: 0 0 10rpx;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 0 150rpx;
|
||||
|
||||
.news {
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: 2rpx solid #e4e7ed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nomore {
|
||||
padding: 30rpx 20rpx;
|
||||
}
|
||||
|
||||
.news {
|
||||
margin: 30rpx 30rpx 0;
|
||||
padding: 0 0 30rpx;
|
||||
|
||||
.head {
|
||||
display: flex;
|
||||
|
||||
.avatar {
|
||||
flex-shrink: 0;
|
||||
width: 69rpx;
|
||||
height: 69rpx;
|
||||
background: #ffffff;
|
||||
// border: 1px solid #14b9c8;
|
||||
border: 1px solid #5f88ff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
margin-left: 14rpx;
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
line-height: 36rpx;
|
||||
|
||||
.tag {
|
||||
margin-left: 15rpx;
|
||||
display: inline-block;
|
||||
padding: 8rpx 10rpx;
|
||||
font-size: 14rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #69b0ff;
|
||||
line-height: 21rpx;
|
||||
border: 1px solid #69b0ff;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #a3a3a3;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.des {
|
||||
margin-top: 40rpx;
|
||||
font-size: 30rpx;
|
||||
font-family: PingFang SC;
|
||||
color: #000000;
|
||||
line-height: 47rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 预约信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<text class="info-label">预约项目</text>
|
||||
<text class="info-value">{{ itemData.name }}</text>
|
||||
</view>
|
||||
<view class="info-row split-row">
|
||||
<text class="info-label">预约时间</text>
|
||||
<text class="info-value">{{ reserveTime }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">预约大厅</text>
|
||||
<text class="info-value">广西区直住房保障中心</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">预约部门</text>
|
||||
<text class="info-value">{{ itemData.deptName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 个人信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<text class="info-label">姓名</text>
|
||||
<text class="info-value">{{ userinfo.name }}</text>
|
||||
</view>
|
||||
<view class="info-row split-row">
|
||||
<text class="info-label">手机号</text>
|
||||
<text class="info-value">{{ userinfo.phone }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">证件类型</text>
|
||||
<text class="info-value">身份证</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">证件号码</text>
|
||||
<text class="info-value">{{ userinfo.idCard }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮栏 -->
|
||||
<view class="btn-bar">
|
||||
<button class="btn-back" @click="handleGoBack">返回</button>
|
||||
<button class="btn-confirm" @click="handleConfirm">确认预约</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getUserInfo,
|
||||
submit
|
||||
} from '@/api/reserve.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userinfo: {},
|
||||
itemData: {},
|
||||
reserveTime: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.itemData = JSON.parse(decodeURIComponent(options.data))
|
||||
this.reserveTime = options.time
|
||||
// this.userinfo = this.$store.state.userInfo
|
||||
this.getUserInfo()
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
handleGoBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
getUserInfo(){
|
||||
getUserInfo().then(res=>{
|
||||
this.userinfo = res.data
|
||||
})
|
||||
},
|
||||
// 确认预约
|
||||
handleConfirm() {
|
||||
const params = {
|
||||
userId: this.userinfo.id,
|
||||
applicant: this.userinfo.name,
|
||||
phone: this.userinfo.phone,
|
||||
idCard: this.userinfo.idCard,
|
||||
itemId: this.itemData.id,
|
||||
itemName: this.itemData.name,
|
||||
deptId: this.itemData.deptId,
|
||||
bookingDate: this.reserveTime.slice(0, 10),
|
||||
timeSlot: this.reserveTime.slice(11),
|
||||
}
|
||||
|
||||
submit(params).then(res => {
|
||||
if (res.code == 200) {
|
||||
uni.showToast({
|
||||
title: '预约成功!',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
}, 2000)
|
||||
}
|
||||
}).catch(err => {})
|
||||
|
||||
|
||||
// 可在此处添加跳转至预约成功页/首页逻辑
|
||||
// uni.reLaunch({ url: '/pages/index/index' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
min-height: 92vh;
|
||||
background-color: #f5f5f5;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 信息卡片 */
|
||||
.info-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
margin: 20rpx 30rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.split-row {
|
||||
border-bottom: 1rpx solid #eeeeee;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
width: 220rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
font-size: 34rpx;
|
||||
color: #333333;
|
||||
text-align: right;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 底部按钮栏 */
|
||||
.btn-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 20rpx 30rpx 40rpx;
|
||||
background-color: #fff;
|
||||
gap: 30rpx;
|
||||
margin-top: auto;
|
||||
box-shadow: 0 -8rpx 20rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(242, 247, 255, 1);
|
||||
color: rgba(49, 134, 255, 1);
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
flex: 2;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(49, 134, 255, 1);
|
||||
color: #ffffff;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 顶部Tab切换 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item" :class="{ active: activeTab === 'department' }" @click="switchTab('department')">
|
||||
单位预约 </view>
|
||||
<view class="tab-item" :class="{ active: activeTab === 'person' }" @click="switchTab('person')"> 个人预约
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-bar">
|
||||
<view class="search-input-wrap">
|
||||
<view class="search-icon"></view>
|
||||
<input class="search-input" v-model="searchKeyword" clearable placeholder="请输入关键字搜索"
|
||||
placeholder-class="placeholder-class" @confirm="handleSearch" />
|
||||
</view>
|
||||
<button class="search-btn" @click="handleSearch">搜索</button>
|
||||
</view>
|
||||
|
||||
<!-- 部门列表 -->
|
||||
<!-- <view class="list-container">
|
||||
<view v-if="departmentList.length > 0">
|
||||
<view class="list-item" v-for="(item, index) in departmentList" :key="index"
|
||||
@click="handleDeptClick(item)">
|
||||
<view class="item-left">
|
||||
<view class="dot"></view>
|
||||
<text class="item-text">{{ item.deptName }}</text>
|
||||
</view>
|
||||
<view class="arrow"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="empty-tip">暂无事项数据</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 事项列表 -->
|
||||
<view class="list-container">
|
||||
<view v-if="itemList.length > 0">
|
||||
<view class="list-item" v-for="(item, index) in itemList" :key="index" @click="handleItemClick(item)">
|
||||
<view class="item-left">
|
||||
<view class="dot"></view>
|
||||
<text class="item-text">{{ item.name }}</text>
|
||||
</view>
|
||||
<view class="arrow"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
deptList,
|
||||
itemList
|
||||
} from '@/api/reserve.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'department', // 当前激活的Tab:department-部门预约,person-事项预约
|
||||
searchKeyword: '', // 搜索关键词
|
||||
deptId: '',
|
||||
// 部门列表(和设计图完全一致)
|
||||
departmentList: [],
|
||||
itemList: [],
|
||||
type: 2 // 1个人, 2单位
|
||||
}
|
||||
},
|
||||
onLoad(option) {
|
||||
if (option.id) {
|
||||
this.deptId = option.id
|
||||
// this.switchTab('person')
|
||||
} else {
|
||||
// this.getDeptList()
|
||||
}
|
||||
this.getItemList()
|
||||
},
|
||||
methods: {
|
||||
// Tab切换
|
||||
switchTab(tab) {
|
||||
if (this.activeTab === tab) return
|
||||
|
||||
if (tab == 'department') {
|
||||
// this.getDeptList()
|
||||
this.type = 2
|
||||
} else {
|
||||
this.type = 1
|
||||
}
|
||||
this.activeTab = tab
|
||||
this.searchKeyword = '' // 切换Tab清空搜索
|
||||
this.getItemList()
|
||||
// this.deptId = ''
|
||||
},
|
||||
// 搜索事件
|
||||
handleSearch() {
|
||||
// if (this.activeTab == 'department') {
|
||||
// // this.getDeptList()
|
||||
// } else {}
|
||||
this.getItemList()
|
||||
},
|
||||
// 部门列表项点击事件
|
||||
handleDeptClick(item) {
|
||||
this.deptId = item.id
|
||||
this.switchTab('person')
|
||||
},
|
||||
// 事项列表项点击事件
|
||||
handleItemClick(item) {
|
||||
const data = JSON.stringify(item)
|
||||
uni.navigateTo({
|
||||
url: `/pages/reserve/notice?data=${encodeURIComponent(data)}`
|
||||
})
|
||||
},
|
||||
// 获取部门列表
|
||||
getDeptList() {
|
||||
let params = {
|
||||
size: 10,
|
||||
current: 1,
|
||||
status: 1,
|
||||
deptName: this.searchKeyword
|
||||
}
|
||||
deptList(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.departmentList = res.data.records.filter(item => item.parentId != 0)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取事项列表
|
||||
getItemList() {
|
||||
// type:1个人, 2单位
|
||||
let params = {
|
||||
size: 10,
|
||||
current: 1,
|
||||
status: 1,
|
||||
// deptId: this.deptId || '',
|
||||
itemType: this.type,
|
||||
name: this.searchKeyword
|
||||
}
|
||||
itemList(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.itemList = res.data.records
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Tab栏 */
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #409eff;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 120rpx;
|
||||
height: 6rpx;
|
||||
background-color: #409eff;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* 搜索栏 */
|
||||
.search-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #f5f5f5;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #ffffff;
|
||||
border-radius: 50rpx;
|
||||
height: 70rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23999999"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.placeholder-class {
|
||||
color: #999999;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
width: 140rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
background: linear-gradient(to left, rgba(49, 134, 255, 1), rgba(21, 167, 255, 1));
|
||||
color: #ffffff;
|
||||
border-radius: 50rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 列表容器 */
|
||||
.list-container {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(to bottom, rgba(49, 134, 255, 1), rgba(21, 167, 255, 1));
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: 34rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-right: 4rpx solid #165dff;
|
||||
border-top: 4rpx solid #165dff;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
/* 空状态提示 */
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 100rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 协议内容区域 -->
|
||||
<view class="agreement-content">
|
||||
<view class="article" v-html="article"> </view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮栏 -->
|
||||
<view class="btn-bar">
|
||||
<button class="btn-back" @click="handleGoBack">返回</button>
|
||||
<button class="btn-confirm" @click="handleConfirm">确定预约</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { noticeData } from '@/api/reserve.js'
|
||||
|
||||
export default {
|
||||
name: 'ConfirmPage',
|
||||
data() {
|
||||
return {
|
||||
article: '',
|
||||
itemData: {}
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
this.itemData = JSON.parse(decodeURIComponent(options.data))
|
||||
this.getNotice()
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
handleGoBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
// 确定预约
|
||||
handleConfirm() {
|
||||
const data = JSON.stringify(this.itemData)
|
||||
uni.navigateTo({
|
||||
url: `/pages/reserve/timeSelect?data=${encodeURIComponent(data)}`
|
||||
})
|
||||
},
|
||||
getNotice() {
|
||||
let params = {
|
||||
descs: 'update_time',
|
||||
size: 10,
|
||||
current: 1,
|
||||
deptId: this.itemData.id
|
||||
}
|
||||
noticeData(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.article = res.data.records[0].content
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 🔥 uni-app 必须加这个,页面高度才会生效 */
|
||||
// page {
|
||||
// height: 100%;
|
||||
// }
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 最外层 flex 容器 */
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
/* 兼容更好 */
|
||||
background-color: #f5f5f5;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
/* 内容区域:自动占满剩余高度 + 滚动 */
|
||||
.agreement-content {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: 40rpx 30rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.article {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-left: 20rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
/* 底部按钮:固定在最下方,不使用 absolute */
|
||||
.btn-bar {
|
||||
display: flex;
|
||||
padding: 20rpx 30rpx 40rpx;
|
||||
background-color: #ffffff;
|
||||
gap: 30rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
box-shadow: 0 -8rpx 20rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(242, 247, 255, 1);
|
||||
color: rgba(49, 134, 255, 1);
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
flex: 2;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(49, 134, 255, 1);
|
||||
color: #ffffff;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,327 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
|
||||
<!-- 信息栏 -->
|
||||
<view class="info-bar">
|
||||
<view class="info-title">住房档案变更(房屋坐落变更)</view>
|
||||
<view class="info-dept">公积金管理中心</view>
|
||||
</view>
|
||||
|
||||
<!-- 日历 -->
|
||||
<view class="calendar-wrap">
|
||||
<view class="calendar-header">
|
||||
<text class="week-item" v-for="week in weekList" :key="week">{{ week }}</text>
|
||||
</view>
|
||||
|
||||
<view class="date-row" v-for="(row, index) in calendarList" :key="index">
|
||||
<view class="date-item" :class="{
|
||||
active: item && item.active,
|
||||
has: item && item.isAvailable,
|
||||
disabled: !item || !item.isAvailable
|
||||
}" v-for="(item, idx) in row" :key="idx" @click="selectDate(item)">
|
||||
|
||||
<text class="date-num">{{ item ? getDay(item.date) : '无' }}</text>
|
||||
<text class="date-status" v-if="item">{{ item.isAvailable ? '有' : '无' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 时段 -->
|
||||
<view class="time-list">
|
||||
<view class="time-item" :class="{ selected: item.selected, disabled: item.remainingCount <= 0 }"
|
||||
v-for="item in currentTimeSlots" :key="item.time" @click="selectTime(item)">
|
||||
<view>{{ item.time }}</view>
|
||||
<view>可预约 {{ item.remainingCount }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部 -->
|
||||
<view class="footer-bar">
|
||||
<view class="selected-info">已选:{{ selectedDate }} {{ selectedTime }}</view>
|
||||
<view class="btn-box">
|
||||
<button class="btn-gray" @click="handleGoBack">返回</button>
|
||||
<button class="btn-blue" @click="handleNext">下一步</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
availableDate
|
||||
} from '@/api/reserve.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
weekList: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
dateList: [],
|
||||
calendarList: [],
|
||||
currentTimeSlots: [],
|
||||
selectedDate: "",
|
||||
selectedTime: "",
|
||||
itemData: {}
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
this.itemData = JSON.parse(decodeURIComponent(options.data))
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
availableDate({
|
||||
itemId: this.itemData.id
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.dateList = res.data
|
||||
this.initCalendar()
|
||||
// 兼容无数据/首条不可选情况
|
||||
const firstAva = this.dateList.find(item => item.isAvailable)
|
||||
firstAva && this.selectDate(firstAva)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 核心重写:100%贴合需求 - 按weekDayName对列+跨周换行+今日为起点前后空
|
||||
initCalendar() {
|
||||
// 初始化两行(最多跨周展示两行,满足业务场景)
|
||||
const row1 = Array(7).fill(null) // 第一行(今日所在周)
|
||||
const row2 = Array(7).fill(null) // 第二行(跨周后的下一周)
|
||||
// 星期转列索引映射(固定匹配表头)
|
||||
const weekToCol = {
|
||||
"星期一": 0,
|
||||
"星期二": 1,
|
||||
"星期三": 2,
|
||||
"星期四": 3,
|
||||
"星期五": 4,
|
||||
"星期六": 5,
|
||||
"星期日": 6
|
||||
}
|
||||
// 今日是列表第一条,获取今日所在星期列,作为展示起点
|
||||
const today = this.dateList[0]
|
||||
if (!today) {
|
||||
this.calendarList = [row1, row2]
|
||||
return
|
||||
}
|
||||
const todayCol = weekToCol[today.weekDayName]
|
||||
// 遍历所有日期,按规则分配到对应行/列
|
||||
this.dateList.forEach(item => {
|
||||
const col = weekToCol[item.weekDayName]
|
||||
if (col === undefined) return
|
||||
// 规则:今日所在列及右侧 → 第一行;今日所在列左侧(跨周)→ 第二行
|
||||
if (col >= todayCol) {
|
||||
row1[col] = item
|
||||
} else {
|
||||
row2[col] = item
|
||||
}
|
||||
})
|
||||
// 最终日历列表(仅保留有数据的行,无数据则不展示)
|
||||
this.calendarList = [row1]
|
||||
if (row2.some(item => item)) {
|
||||
this.calendarList.push(row2)
|
||||
}
|
||||
},
|
||||
|
||||
getDay(date) {
|
||||
if (!date) return "";
|
||||
return date.split("-")[2];
|
||||
},
|
||||
|
||||
formatDate(date) {
|
||||
const arr = date.split("-");
|
||||
return arr[0] + "-" + arr[1] + "-" + arr[2];
|
||||
},
|
||||
|
||||
selectDate(item) {
|
||||
if (!item || !item.isAvailable) return;
|
||||
this.selectedTime = ''
|
||||
this.dateList.forEach(i => (i.active = false));
|
||||
item.active = true;
|
||||
this.selectedDate = this.formatDate(item.date);
|
||||
this.currentTimeSlots = (item.timeSlots || []).map(t => {
|
||||
return {
|
||||
...t,
|
||||
selected: false
|
||||
};
|
||||
});
|
||||
if (this.currentTimeSlots.length > 0) {
|
||||
this.selectTime(this.currentTimeSlots[0]);
|
||||
}
|
||||
},
|
||||
|
||||
selectTime(item) {
|
||||
if (item.remainingCount <= 0) return;
|
||||
this.currentTimeSlots.forEach(t => (t.selected = false));
|
||||
item.selected = true;
|
||||
this.selectedTime = item.time;
|
||||
},
|
||||
|
||||
handleGoBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
handleNext() {
|
||||
if (!this.selectedDate || !this.selectedTime) {
|
||||
uni.showToast({
|
||||
title: "请选择完整",
|
||||
icon: "none"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const data = JSON.stringify(this.itemData)
|
||||
const time = this.selectedDate + " " + this.selectedTime
|
||||
uni.navigateTo({
|
||||
url: `/pages/reserve/confirm?data=${encodeURIComponent(data)}&time=${time}`
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
background: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.info-bar {
|
||||
background: linear-gradient(90deg, rgba(49, 134, 255, 1), #53a8ff);
|
||||
padding: 30rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.info-title {
|
||||
font-size: 34rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.info-dept {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.calendar-wrap {
|
||||
background: #fff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
border: 2rpx solid rgba(49, 134, 255, 1);
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.week-item {
|
||||
flex: 1;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.date-row {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.date-item {
|
||||
flex: 1;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.date-item.has {
|
||||
color: rgba(49, 134, 255, 1);
|
||||
}
|
||||
|
||||
.date-item.active {
|
||||
background: rgba(49, 134, 255, 1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.date-item.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.date-num {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.date-status {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.time-list {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.time-item {
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.time-item.selected {
|
||||
background: #e8f3ff;
|
||||
border: 2rpx solid rgba(49, 134, 255, 1);
|
||||
}
|
||||
|
||||
.time-item.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.footer-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
padding: 20rpx 30rpx 40rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.selected-info {
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
display: flex;
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.btn-gray {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(242, 247, 255, 1);
|
||||
color: rgba(49, 134, 255, 1);
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
|
||||
.btn-blue {
|
||||
flex: 2;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background-color: rgba(49, 134, 255, 1);
|
||||
color: #ffffff;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: 2rpx solid rgba(208, 227, 255, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
<template>
|
||||
<view>
|
||||
<view class="editor_toolbox" :style="{ top: `${statusBarHeight}px` }">
|
||||
<u-icon name="arrow-leftward" size="40rpx" color="#303133" @click="onSave"></u-icon>
|
||||
<!-- <i class="iconfont icon-save" @tap="onSave" /> -->
|
||||
<i class="iconfont icon-undo" data-method="undo" @tap="edit" />
|
||||
<i class="iconfont icon-redo" data-method="redo" @tap="edit" />
|
||||
<i class="iconfont icon-img" data-method="insertImg" @tap="edit" />
|
||||
<i class="iconfont icon-video" data-method="insertVideo" @tap="edit" />
|
||||
<i class="iconfont icon-link" data-method="insertLink" @tap="edit" />
|
||||
<i class="iconfont icon-text" data-method="insertText" @tap="edit" />
|
||||
<i class="iconfont icon-clear" @tap="clear" />
|
||||
</view>
|
||||
<view :style="{ paddingTop: `${statusBarHeight + 50}px` }">
|
||||
<mp-html ref="article" container-style="padding:20px" :content="content" domain="" :editable="editable" @remove="remove" />
|
||||
</view>
|
||||
<block v-if="modal">
|
||||
<view class="mask" />
|
||||
<view class="modal">
|
||||
<view class="modal_title">{{ modal.title }}</view>
|
||||
<input class="modal_input" :value="modal.value" maxlength="-1" auto-focus @input="modalInput" />
|
||||
<view class="modal_foot">
|
||||
<view class="modal_button" @tap="modalCancel">取消</view>
|
||||
<view class="modal_button" style="color:#576b95;border-left:1px solid rgba(0,0,0,.1)" @tap="modalConfirm">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpHtml from '@/components/rider-crud/components/mp-html/mp-html'
|
||||
import http from '@/http/api.js'
|
||||
// 上传图片方法
|
||||
function upload(src, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log('上传', type === 'img' ? '图片' : '视频', ':', src)
|
||||
// resolve(src)
|
||||
const params = {
|
||||
// #ifdef MP-ALIPAY
|
||||
fileType: 'image/video/audio', // 仅支付宝小程序,且必填。
|
||||
// #endif
|
||||
filePath: src,
|
||||
name: 'file'
|
||||
}
|
||||
http.upload('/api/blade-resource/oss/endpoint/put-file', params).then(res => {
|
||||
resolve(res.data.link)
|
||||
})
|
||||
})
|
||||
}
|
||||
// 删除图片方法
|
||||
function remove(src) {
|
||||
console.log('删除图片:', src)
|
||||
// 实际使用时,删除线上资源
|
||||
}
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
content: null,
|
||||
modal: null,
|
||||
editable: true,
|
||||
statusBarHeight: 0
|
||||
}
|
||||
},
|
||||
components: {
|
||||
mpHtml
|
||||
},
|
||||
onReady() {
|
||||
/**
|
||||
* @description 设置获取链接的方法
|
||||
* @param {String} type 链接的类型(img/video/audio/link)
|
||||
* @param {String} value 修改链接时,这里会传入旧值
|
||||
* @returns {Promise} 返回线上地址
|
||||
* type 为音视频时可以返回一个数组作为源地址
|
||||
* type 为 audio 时,可以返回一个 object,包含 src、name、author、poster 等字段
|
||||
*/
|
||||
this.$refs.article.getSrc = (type, value) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (type === 'img' || type === 'video') {
|
||||
uni.showActionSheet({
|
||||
itemList: ['本地选取', '远程链接'],
|
||||
success: res => {
|
||||
if (res.tapIndex === 0) {
|
||||
// 本地选取
|
||||
if (type === 'img') {
|
||||
uni.chooseImage({
|
||||
count: value === undefined ? 9 : 1, // 2.2.0 版本起插入图片时支持多张(修改图片链接时仅限一张)
|
||||
success: res => {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (res.tempFilePaths.length == 1 && wx.editImage) {
|
||||
// 单张图片时进行编辑
|
||||
wx.editImage({
|
||||
src: res.tempFilePaths[0],
|
||||
complete: res2 => {
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
})
|
||||
upload(res2.tempFilePath || res.tempFilePaths[0], type).then(res => {
|
||||
uni.hideLoading()
|
||||
resolve(res)
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// #endif
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
})
|
||||
;(async () => {
|
||||
const arr = []
|
||||
for (let item of res.tempFilePaths) {
|
||||
// 依次上传
|
||||
const src = await upload(item, type)
|
||||
arr.push(src)
|
||||
}
|
||||
return arr
|
||||
})().then(res => {
|
||||
uni.hideLoading()
|
||||
resolve(res)
|
||||
})
|
||||
// #ifdef MP-WEIXIN
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
fail: reject
|
||||
})
|
||||
} else {
|
||||
uni.chooseVideo({
|
||||
success: res => {
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
})
|
||||
upload(res.tempFilePath, type).then(res => {
|
||||
uni.hideLoading()
|
||||
resolve(res)
|
||||
})
|
||||
},
|
||||
fail: reject
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 远程链接
|
||||
this.callback = {
|
||||
resolve,
|
||||
reject
|
||||
}
|
||||
this.$set(this, 'modal', {
|
||||
title: (type === 'img' ? '图片' : '视频') + '链接',
|
||||
value
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.callback = {
|
||||
resolve,
|
||||
reject
|
||||
}
|
||||
let title
|
||||
if (type === 'audio') {
|
||||
title = '音频链接'
|
||||
} else if (type === 'link') {
|
||||
title = '链接地址'
|
||||
}
|
||||
this.$set(this, 'modal', {
|
||||
title,
|
||||
value
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(option) {
|
||||
let that = this
|
||||
that.content = option.data
|
||||
// 获取高度 - 小程序设配
|
||||
uni.getSystemInfo({
|
||||
success: function(res) {
|
||||
// #ifdef MP-WEIXIN
|
||||
that.statusBarHeight = Number(res.statusBarHeight) + Number(res.platform == 'ios' ? 44 : 48)
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
that.statusBarHeight = Number(res.statusBarHeight)
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 删除图片/视频/音频标签事件
|
||||
remove(e) {
|
||||
// 删除线上资源
|
||||
remove(e.src)
|
||||
},
|
||||
// 处理模态框
|
||||
modalInput(e) {
|
||||
this.value = e.detail.value
|
||||
},
|
||||
modalConfirm() {
|
||||
this.callback.resolve(this.value || this.modal.value || '')
|
||||
this.$set(this, 'modal', null)
|
||||
},
|
||||
modalCancel() {
|
||||
this.callback.reject()
|
||||
this.$set(this, 'modal', null)
|
||||
},
|
||||
// 调用编辑器接口
|
||||
edit(e) {
|
||||
this.$refs.article[e.currentTarget.dataset.method]()
|
||||
},
|
||||
// 清空编辑器内容
|
||||
clear() {
|
||||
uni.showModal({
|
||||
title: '确认',
|
||||
content: '确定清空内容吗?',
|
||||
success: res => {
|
||||
if (res.confirm) this.$refs.article.clear()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 保存编辑器内容
|
||||
onSave() {
|
||||
setTimeout(() => {
|
||||
var content = this.$refs.article.getContent()
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否保存当前内容返回上一级?',
|
||||
confirmText: '保存',
|
||||
cancelText: '不保存',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
uni.$emit('richBack', content)
|
||||
}
|
||||
this.editable = false
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}
|
||||
})
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.editor_toolbox {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background-color: #ededed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAeYAAsAAAAADlAAAAdLAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCEAgqOYItrATYCJAMkCxQABCAFhG0HcBv/CzOjdoNyEiD7nwnxpstuRCLrGmPTaffv/hnWZJHUNtWZeOD/3t03mks73vmC/3jA8SRom0aatimgfv7d9M8lBEJCIHRBKua0E7EEOqedMBEJm8N7js0MWpgq9PlMkGcTsS8NgH3X/AEbFaFGZNFvH+xR2uYofWlu9NO9ypmTgvNlW8CitMbdT7rHpgAXaKxBOfzWBdQCFgyrMV3kKtMLUFGd7GEC0JSkACq79OKAIMbDAW2W48z1QESSiQsUARGRZFyYAZ0AR8Q1ogsAjs7vhy+UBQIgwhPwR83HdB4F7R6gR25M+CrAUEwAobtM6LuBBBRA1qlLZvYO80KFg8isxmImAH1xHwzc0UPpQ/ph9cNLD+8+cn/9mnAgGQwUGkVj0B1kUhL4EP94IgQIVeCoDc62pg7uyLCRwUMCauARlsQ0ElWAq5EoAV9CogB8FzYieLq7qQM0rM5DYAriAik/Li6hNpHBj2knBBuokIJWymUizhppEknSNKNTIHnPfnR5WRIjFnmB0MgyTh9CFr9W5WgCNNfq00hdfi0KEVVL7I0kQvMYjy8OUbDAQIFwzDiGGzMKX+/PVu1sih2FbLk8PneQ0e84zT9a9GckbXu06x/h1C0hw45Twmlb0BLgUtCw7qqMfsqCGhV6bZl8tzTOhwXIwI1ZQCJLIIvccUoHE88h4XC2eGu4M/1XNB3fedRypMHlpyhbEwA5zn0qQ+4JIFxpmvQRIqHR6kOYxT8yRF6DufwjDl1JEG+8Wqk8ej0Z33StarLSdvb0fhAL+06dIRXWc4EDCLccDJ7nRTRGNUgi5S3sUk8hG4BAIuuqdJzCcXaWtWpZK0O7I0Mqs9SeBk6HJs+pMZ3cqWSo18Up8nh2vcql1drvYnRZfFaWawwlbAjnNuUeD0fz47f2GNsa/fF7o5EiX96JqiMhfWMOZ3c32aoWarUuu1GgZb3ZijxTszPBoebYYVU51WtjNSTXad3ekZzB2YUmmynf7Frv87CjOrjBApsDIHqPD//DhUKGSMSAEKRwBgqH+XDUGI0YIlaOKiYk2EnSqUEWF7XAageI3OVCf/PhsDEaNSKnhrSzKBTiQlVdDbJsPEl0ONSUS4ssTnLO4dOJ8O/y7lwLIsG9w6MxwIZTFYojgSR8c7B6ksJqZ8UOB6W0ubb0SifPuQb42mUpNFyJuQI0OLvELTPRSN5ODs3CBUKIBoDa1xrz1K/SNy3fVPVDMKK2XqdM6a9QLFycnZWRVUJ89QUvJOjZoAOfr7zKhGDrb79CEfP5M8/DTEvPngRh8AWBr9OZ66+89rX3tVtZ8tVf0r2fhur6+fMn0ALooJU7KIuS79+fpFNWX018UNVONCAU6vv7QGWHX5rbxpdvCW5JI9sFt9aUVW1pjXfr1K+5X6dOeOsts8vm/p1Iq+glCpUiObh4EVm2JbClPL5V603DrqjoTQomnlFsolUURBISwDpcroJ7b0oA02NQonc6VOv1iZVzBiYiduCcysTgHXF6OAN6GftRd0b3kZV9q0+AxEQ+IRESEvhEqIl262o2d+ZSUQfnmQcNY2dMXbp06rKxDTkJDJeW6vN3QmnfdO+etSJLmp0tSazIHjphQaZo7r6Dq2MZ3eom36nkLlp5St+X1jcrBkv4xK/79qbGfer3tXOWL0+NzJUNjuev1m2r8TwarGszs8uaVXMJRufavYvjGRWXNvLMw4a6hqnTp+OWddN3rFg+ixl4/IR5XXolag7ZzhxpDtvDmd17wTeo3HzocG+79mhzQ6GYS6SY3AUFNu1aUC5jsE6YcVIdLZk+YIqhI161tOWSVwtt2jUJey9Kv5VI+tWYJCCe8U3j1Nhp6t/ry8zF48oidd2GdLkxpPOAeiG9UXgmkpyh9YWSltIkJvUm3/2XckNk/emn1TPGhuRv5ddp5qpQ5XLRDWCzQqyzQ4tWrMxPsIRfxsInjYr7g9evq5O7w5KQAvAPYk1YW0p4kkSoGpozaS3WThNOfixfE8B+wzrpbqcdWAzzu1akq+jGw+IgeIpNPUYoW30gqPdHzI3c6qeif0AMzVuoE4HK3keDt+KE/PXzUOM3K4anQW5D40VTGYGmWAAeCflDN7ulJpW9TyBKHUAklQgJIYOROQVQQamAKkJbaMrX9fKWFqYDBmUZgJkVDBDGXhBRCAKGcdEJJzg3AKfxAiSYgAHJgFrckJIVVqPJSTBWzCD5AKVcG5mmE7ftHW1TxhL2O+o/lEBlsJjO43U3rFG6OCU87VLVgBGu4Moeh2XJ4IVzTHXqVP1xNjNZp05TrlqTVkfBWC3zDJKPPaVcm611kvj5O9qmjKVgyI/9H0qg7cNiOq/AuKG60pBT6RyedqmUacDoLVzBlTKxFNUMPnu/HFOdugaV/jijqUxVNB2eqs41gtM3LCcta4sQhsQIRxIkRQSSIRLEim8daOMprvsqcXCDRdX2cFgMy8TbcsJh6vBNMY++jmv7bXgQHHmqWy0A')
|
||||
format('woff2');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-family: 'iconfont' !important;
|
||||
font-size: 22px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-undo:before {
|
||||
content: '\e607';
|
||||
}
|
||||
|
||||
.icon-redo:before {
|
||||
content: '\e606';
|
||||
}
|
||||
|
||||
.icon-img:before {
|
||||
content: '\e6e2';
|
||||
}
|
||||
|
||||
.icon-video:before {
|
||||
content: '\e798';
|
||||
}
|
||||
|
||||
.icon-link:before {
|
||||
content: '\e60d';
|
||||
}
|
||||
|
||||
.icon-text:before {
|
||||
content: '\e6ce';
|
||||
}
|
||||
|
||||
.icon-clear:before {
|
||||
content: '\e637';
|
||||
}
|
||||
|
||||
.icon-save:before {
|
||||
content: '\e501';
|
||||
}
|
||||
|
||||
/* 模态框 */
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
right: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.modal_title {
|
||||
padding: 32px 24px 16px;
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal_input {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
margin: 0 24px 32px 24px;
|
||||
font-size: 14px;
|
||||
border: 1px solid #dfe2e5;
|
||||
}
|
||||
|
||||
.modal_foot {
|
||||
display: flex;
|
||||
line-height: 56px;
|
||||
font-weight: 700;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.modal_button {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 蒙版 */
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: black;
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
<template>
|
||||
<view class="screen-wrap">
|
||||
<!-- 顶部标题栏 -->
|
||||
<view class="top-header">
|
||||
<text class="title-left">{{ screenTitle }}</text>
|
||||
<view class="title-right">
|
||||
<text>{{ dateStr }}</text>
|
||||
<text>{{ weekStr }} {{ timeStr }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 中间大字播报区 -->
|
||||
<view class="big-call">
|
||||
<text class="normal-text">请</text>
|
||||
<text class="yellow-text">{{ currCallNo }}</text>
|
||||
<text class="normal-text">到</text>
|
||||
<text class="yellow-text">{{ currWinNo }}</text>
|
||||
</view>
|
||||
<!-- 左右双栏表格区域 -->
|
||||
<view class="table-box">
|
||||
<!-- 左:当前呼叫 -->
|
||||
<view class="table-left">
|
||||
<view class="table-head">
|
||||
<text>当前呼叫</text>
|
||||
<text class="tip-text">(过号需重新取号)</text>
|
||||
</view>
|
||||
<view class="table-list">
|
||||
<view class="table-row" v-for="(item, idx) in callList" :key="idx" :class="idx % 2 === 1 ? 'row-blue' : ''">
|
||||
<text>请</text>
|
||||
<text class="row-no">{{ item.no }}</text>
|
||||
<text>到</text>
|
||||
<text class="row-no">{{ item.win }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 右:等候办理 -->
|
||||
<view class="table-right">
|
||||
<view class="table-head">等候办理</view>
|
||||
<view class="table-list">
|
||||
<view class="table-row wait-row" v-for="(row, idx) in waitList" :key="idx" :class="idx % 2 === 1 ? 'row-blue' : ''">
|
||||
<text v-for="(item, i) in row" :key="i">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getDisplayScreen } from '@/api/ticket.js'
|
||||
|
||||
export default {
|
||||
name: 'CallScreen',
|
||||
data() {
|
||||
return {
|
||||
// 大屏标题(来自接口)
|
||||
screenTitle: '环江毛南族自治县政务服务中心',
|
||||
// 实时日期时间
|
||||
dateStr: '',
|
||||
weekStr: '',
|
||||
timeStr: '',
|
||||
serverTimeOffset: 0, // 服务端时间与本地时间的差值(毫秒)
|
||||
clockTimer: null, // 时钟刷新定时器
|
||||
fetchTimer: null, // 数据轮询定时器
|
||||
// 顶部大字播报
|
||||
currCallNo: '',
|
||||
currWinNo: '',
|
||||
// 左侧当前呼叫列表
|
||||
callList: [],
|
||||
// 右侧等候队列(每行3个)
|
||||
waitList: []
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 首次加载数据(获取服务端时间后启动时钟)
|
||||
this.fetchDisplayData()
|
||||
// 定时轮询刷新叫号数据
|
||||
this.fetchTimer = setInterval(() => {
|
||||
this.fetchDisplayData()
|
||||
}, 5000)
|
||||
},
|
||||
onUnload() {
|
||||
clearInterval(this.clockTimer)
|
||||
clearInterval(this.fetchTimer)
|
||||
},
|
||||
methods: {
|
||||
// 启动时钟(首次拿到 serverTime 后调用)
|
||||
startClock() {
|
||||
clearInterval(this.clockTimer)
|
||||
this.tick()
|
||||
this.clockTimer = setInterval(() => {
|
||||
this.tick()
|
||||
}, 1000)
|
||||
},
|
||||
// 每秒走时
|
||||
tick() {
|
||||
// 服务端时间 + 本地已流逝的毫秒 = 当前展示时间
|
||||
const now = this.serverTimeOffset ? new Date(Date.now() + this.serverTimeOffset) : new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = this.addZero(now.getMonth() + 1)
|
||||
const day = this.addZero(now.getDate())
|
||||
const hour = this.addZero(now.getHours())
|
||||
const minute = this.addZero(now.getMinutes())
|
||||
const weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
const week = weekArr[now.getDay()]
|
||||
|
||||
this.dateStr = `${year}年${month}月${day}日`
|
||||
this.weekStr = week
|
||||
this.timeStr = `${hour}:${minute}`
|
||||
},
|
||||
addZero(num) {
|
||||
return num < 10 ? '0' + num : num
|
||||
},
|
||||
// 获取大屏展示数据
|
||||
fetchDisplayData() {
|
||||
getDisplayScreen({ calledSize: 8, waitingSize: 24 })
|
||||
.then(res => {
|
||||
const data = res.data
|
||||
if (!data) return
|
||||
|
||||
// 1. 标题
|
||||
if (data.title) {
|
||||
this.screenTitle = data.title
|
||||
}
|
||||
|
||||
// 2. 服务端时间(首次计算偏移量后启动时钟)
|
||||
if (data.serverTime && !this.serverTimeOffset) {
|
||||
const serverTs = new Date(data.serverTime.replace(/-/g, '/')).getTime()
|
||||
this.serverTimeOffset = serverTs - Date.now()
|
||||
this.startClock()
|
||||
}
|
||||
|
||||
// 3. 顶部大字播报(最新呼叫)
|
||||
if (data.latestCall) {
|
||||
this.currCallNo = data.latestCall.queueNo || ''
|
||||
this.currWinNo = data.latestCall.windowName || ''
|
||||
} else {
|
||||
this.currCallNo = ''
|
||||
this.currWinNo = ''
|
||||
}
|
||||
|
||||
// 4. 左侧当前呼叫列表
|
||||
if (data.callingList && Array.isArray(data.callingList)) {
|
||||
this.callList = data.callingList.map(item => ({
|
||||
no: item.queueNo || '',
|
||||
win: item.windowName || ''
|
||||
}))
|
||||
} else {
|
||||
this.callList = []
|
||||
}
|
||||
|
||||
// 5. 右侧等候队列(每行3个)
|
||||
if (data.waitingList && Array.isArray(data.waitingList)) {
|
||||
const waitNos = data.waitingList.map(item => item.queueNo || '')
|
||||
const rows = []
|
||||
for (let i = 0; i < waitNos.length; i += 3) {
|
||||
const row = waitNos.slice(i, i + 3)
|
||||
while (row.length < 3) {
|
||||
row.push('')
|
||||
}
|
||||
rows.push(row)
|
||||
}
|
||||
this.waitList = rows
|
||||
} else {
|
||||
this.waitList = []
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('获取大屏数据失败:', err)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 使用 vw/vh 自适应屏幕,设计基准 1920*1080 */
|
||||
.screen-wrap {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: #083378;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*顶部蓝色栏 */
|
||||
.top-header {
|
||||
width: 100%;
|
||||
height: 12.963vh; /* 140/1080*100 */
|
||||
background: #167bff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 2.604vw; /* 50/1920*100 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.title-left {
|
||||
font-size: 3.229vw; /* 62/1920*100 */
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.title-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.title-right text {
|
||||
font-size: 2.083vw; /* 40/1920*100 */
|
||||
color: #fff;
|
||||
line-height: 4.63vh; /* 50/1080*100 */
|
||||
}
|
||||
|
||||
/*中间大字叫号 */
|
||||
.big-call {
|
||||
height: 24.074vh; /* 260/1080*100 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1.563vw; /* 30/1920*100 */
|
||||
}
|
||||
|
||||
.normal-text {
|
||||
font-size: 6.25vw; /* 120/1920*100 */
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.yellow-text {
|
||||
font-size: 6.25vw; /* 120/1920*100 */
|
||||
color: #ffef33;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*左右表格容器 */
|
||||
.table-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 1.563vw; /* 30/1920*100 */
|
||||
padding: 0 1.563vw 2.778vh; /* 0 30/1920*100 30/1080*100 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.table-left,
|
||||
.table-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 0.833vw; /* 16/1920*100 */
|
||||
}
|
||||
|
||||
.table-head {
|
||||
width: 100%;
|
||||
height: 10.185vh; /* 110/1080*100 */
|
||||
background: #167bff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 2.708vw; /* 52/1920*100 */
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 1.875vw; /* 36/1920*100 */
|
||||
margin-left: 1.042vw; /* 20/1920*100 */
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.table-list {
|
||||
height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/*表格行样式 */
|
||||
.table-row {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 2.813vw; /* 54/1920*100 */
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.wait-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.row-blue {
|
||||
background: #e6f0ff;
|
||||
}
|
||||
|
||||
.row-no {
|
||||
color: #0055ff;
|
||||
font-weight: bold;
|
||||
margin: 0 1.042vw; /* 20/1920*100 */
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="head">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-color="#fff" back-icon-size="35" :background="{ background: 'linear-gradient(90deg, #69b0ff, #5f88ff)' }" title="服务"
|
||||
title-color="#fff"></u-navbar>
|
||||
<view class="head-bg"></view>
|
||||
<!-- 我的订阅 start -->
|
||||
<view class="card sub">
|
||||
<view class="title">我的订阅</view>
|
||||
<view class="list">
|
||||
<u-grid :col="4" :border="false">
|
||||
<u-grid-item bg-color="transparent" v-for="(item, index) in subscribeList" :key="index">
|
||||
<navigator url="" hover-class="none" class="nav-item">
|
||||
<image :src="item.img" mode="widthFix" class="nav-item-img"></image>
|
||||
<view class="nav-item-name">{{ item.name }}</view>
|
||||
</navigator>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 我的订阅 end -->
|
||||
|
||||
<!-- 服务列表 start -->
|
||||
<view class="card wrap" v-for="(item, index) in serviceList" :key="index">
|
||||
<view class="title">{{item.name}}</view>
|
||||
<view class="list">
|
||||
<u-grid :col="4" :border="false">
|
||||
<u-grid-item bg-color="transparent" v-for="(_item, _index) in item.list" :key="_index">
|
||||
<navigator url="" hover-class="none" class="nav-item">
|
||||
<image :src="_item.img" mode="widthFix" class="nav-item-img"></image>
|
||||
<view class="nav-item-name">{{ _item.name }}</view>
|
||||
</navigator>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 服务列表 end -->
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
fakeSubscribeList,
|
||||
fakeServiceList,
|
||||
} from "@/api/mock/service.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 我的订阅
|
||||
subscribeList: [],
|
||||
// 服务列表
|
||||
serviceList: [],
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
// 后续将改为与后端联动
|
||||
// 加载我的订阅数据
|
||||
fakeSubscribeList().then(data => {
|
||||
this.subscribeList = data;
|
||||
})
|
||||
// 加载服务集合数据
|
||||
fakeServiceList().then(data => {
|
||||
this.serviceList = data;
|
||||
})
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
background-color: #f7f7f7;
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.head {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.head-bg {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
z-index: -1;
|
||||
width: 750rpx;
|
||||
height: 270rpx;
|
||||
background: linear-gradient(90deg, #69b0ff, #5f88ff);
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 30rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
margin-top: 36rpx;
|
||||
}
|
||||
|
||||
.sub {
|
||||
.title {
|
||||
padding-top: 36rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
font-size: 30rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 135rpx;
|
||||
height: 1rpx;
|
||||
background: #e4e7ed;
|
||||
margin: 0 17rpx;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 135rpx;
|
||||
height: 1rpx;
|
||||
background: #e4e7ed;
|
||||
margin: 0 17rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 0 30rpx;
|
||||
|
||||
.nav-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #131313;
|
||||
line-height: 48rpx;
|
||||
opacity: 0.77;
|
||||
|
||||
&-img {
|
||||
width: 54rpx;
|
||||
height: 54rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
&-name {
|
||||
font-size: 26rpx;
|
||||
font-family: PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #585b61;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wrap {
|
||||
.title {
|
||||
padding: 36rpx 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 5rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 10rpx;
|
||||
background: #3ac4d1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward"
|
||||
back-icon-size="35" :background="{ background: '#fff' }" title="设置" title-color="#000">
|
||||
</u-navbar>
|
||||
<view class="u-demo">
|
||||
<view class="u-demo-wrap">
|
||||
<view class="u-demo-title">很快到来</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<view class="head" :style="{height: `${headHeight}rpx`}">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="false" title="个人中心" :background="{ background: 'transprent' }" title-color="#FFFFFF">
|
||||
<view @click="$u.func.route('/pages/system/setting')" slot="right">
|
||||
<image src="/static/images/user/setting.png" class="set-icon" mode="widthFix"></image>
|
||||
</view>
|
||||
</u-navbar>
|
||||
<image src="/static/images/user/bg.png" class="head-bg" :style="{height: `${headHeight}rpx`}" />
|
||||
|
||||
<!-- 用户信息 -->
|
||||
<view class="user-box">
|
||||
<view class="left">
|
||||
<image :src="userInfo.avatar" class="avatar" mode=""></image>
|
||||
<view class="user-name">{{ userInfo.nick_name }}</view>
|
||||
<view class="tag">{{ userInfo.tenant_id }}</view>
|
||||
</view>
|
||||
<view @click="$u.func.route('/pages/user/profile')" class="edit-btn">编辑资料</view>
|
||||
</view>
|
||||
<!-- 操作按钮 -->
|
||||
<view class="nav">
|
||||
<navigator url="" hover-class="none" class="nav-item">
|
||||
<image src="/static/images/user/n1.png" class="icon" mode=""></image>
|
||||
<view class="name">我的消息</view>
|
||||
</navigator>
|
||||
<navigator url="" hover-class="none" class="nav-item">
|
||||
<image src="/static/images/user/n2.png" class="icon" mode=""></image>
|
||||
<view class="name">我的待办</view>
|
||||
</navigator>
|
||||
<navigator url="" hover-class="none" class="nav-item">
|
||||
<image src="/static/images/user/n3.png" class="icon" mode=""></image>
|
||||
<view class="name">我的地址</view>
|
||||
</navigator>
|
||||
<navigator url="" hover-class="none" class="nav-item">
|
||||
<image src="/static/images/user/n4.png" class="icon" mode=""></image>
|
||||
<view class="name">我的收藏</view>
|
||||
</navigator>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 功能列表 -->
|
||||
<view class="cell-box">
|
||||
<u-cell-group :border="false">
|
||||
<u-cell-item title="我的评价">
|
||||
<image slot="icon" src="/static/images/user/c1.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
<u-cell-item title="常见问题">
|
||||
<image slot="icon" src="/static/images/user/c2.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
<u-cell-item title="客服中心" :border-bottom="false">
|
||||
<image slot="icon" src="/static/images/user/c3.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
<view class="cell-box">
|
||||
<u-cell-group :border="false">
|
||||
<u-cell-item title="推荐">
|
||||
<image slot="icon" src="/static/images/user/c4.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
<u-cell-item title="评分">
|
||||
<image slot="icon" src="/static/images/user/c5.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
<u-cell-item title="反馈">
|
||||
<image slot="icon" src="/static/images/user/c6.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
<u-cell-item title="关于" :border-bottom="false">
|
||||
<image slot="icon" src="/static/images/user/c7.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
<view class="cell-box">
|
||||
<u-cell-group :border="false">
|
||||
<u-cell-item title="设置" :border-bottom="false" @click="$u.func.route('/pages/system/setting')">
|
||||
<image slot="icon" src="/static/images/user/c8.png" class="icon" mode=""></image>
|
||||
</u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
headHeight: 582
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.setHeadHeight()
|
||||
},
|
||||
methods: {
|
||||
setHeadHeight() {
|
||||
const that = this
|
||||
// #ifndef H5
|
||||
uni.getSystemInfo({
|
||||
success: function(res) {
|
||||
that.headHeight = Number(res.statusBarHeight) + Number(res.platform == 'ios' ? 44 : 48) + 582
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
background-color: #f7f7f7;
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.head {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
min-height: 582rpx;
|
||||
overflow: hidden;
|
||||
background: #55A2F9;
|
||||
|
||||
.set-icon {
|
||||
vertical-align: middle;
|
||||
width: 41rpx;
|
||||
height: auto;
|
||||
margin-right: 35rpx;
|
||||
}
|
||||
|
||||
.head-bg {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
z-index: -1;
|
||||
width: 750rpx;
|
||||
height: 582rpx;
|
||||
background: #55A2F9;
|
||||
}
|
||||
}
|
||||
|
||||
.user-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx 0 64rpx;
|
||||
margin-top: 36rpx;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.avatar {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
margin-top: 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 5rpx 16rpx;
|
||||
border: 1px solid #f5f5f5;
|
||||
border-radius: 7rpx;
|
||||
|
||||
font-size: 19rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 300;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
margin-top: 20rpx;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: 165rpx;
|
||||
height: 54rpx;
|
||||
border: 2rpx solid #f5f5f5;
|
||||
border-radius: 11rpx;
|
||||
|
||||
font-size: 27rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
//border-top: 2rpx solid #7dcdd6;
|
||||
margin: 36rpx 38rpx 0;
|
||||
padding: 36rpx 0 42rpx;
|
||||
|
||||
.nav-item {
|
||||
width: calc(100% / 4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
font-size: 25rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
content: '';
|
||||
display: block;
|
||||
width: 2rpx;
|
||||
background-color: #fff;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cell-box {
|
||||
background: #ffffff;
|
||||
margin: 18rpx;
|
||||
|
||||
.icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 22rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar :is-fixed="false" :border-bottom="false" :is-back="true" back-icon-name="arrow-leftward" title="个人资料"
|
||||
back-icon-size="35" :background="{ background: '#fff' }" title-color="#000">
|
||||
<view class="complie" slot="right" @click="submit">完成</view>
|
||||
</u-navbar>
|
||||
|
||||
<view class="content">
|
||||
<view class="avatar">
|
||||
<image :src="userInfo.avatar" class="avatar-image" mode=""></image>
|
||||
<view class="a" @click="handleChooseImg">更换头像</view>
|
||||
</view>
|
||||
<view class="form">
|
||||
<view class="cell">
|
||||
<view class="name">昵称</view>
|
||||
<input type="text" placeholder="请输入昵称" v-model="userInfo.nick_name" class="ipt"
|
||||
placeholder-class="hold" />
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view class="name">生日</view>
|
||||
<picker mode="date" class="ipt" :class="{ hold: !detail.birthday }"
|
||||
@change="changeDefaultPicker('birthday', $event)">
|
||||
<view>{{ detail.birthday || '请选择生日' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view class="name">性别</view>
|
||||
<picker mode="selector" :range="sexPicker" range-key="name" class="ipt"
|
||||
:class="{ hold: !detail.sex }" @change="changePicker('sex', $event)">
|
||||
<view>{{ detail.sex === 1?'男':'女' || '请选择性别' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view class="name">手机号</view>
|
||||
<input type="number" placeholder="请填写手机号" v-model="detail.phone" class="ipt"
|
||||
placeholder-class="hold" />
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view class="name">邮箱</view>
|
||||
<input v-model="detail.email" class="ipt" placeholder-class="hold" />
|
||||
</view>
|
||||
<!--<view class="cell">
|
||||
<view class="name">国家/地区</view>
|
||||
<pickRegions :defaultRegion="detail.region" v-model="detail.region"
|
||||
:class="{ hold: !detail.region, ipt: true }">
|
||||
<view>{{ detail.region || '请选择国家/地区' }}</view>
|
||||
</pickRegions>
|
||||
</view>-->
|
||||
</view>
|
||||
</view>
|
||||
<!-- -->
|
||||
<view class="back" @click="logout">退出登录</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pickRegions from '@/components/pick-regions/pick-regions.vue';
|
||||
export default {
|
||||
components: {
|
||||
pickRegions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sexPicker: [{
|
||||
name: '男'
|
||||
},
|
||||
{
|
||||
name: '女'
|
||||
}
|
||||
],
|
||||
detail: {}
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.$u.api.userInfo().then(data => {
|
||||
console.log(data);
|
||||
if (data.success) {
|
||||
this.detail = data.data;
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
this.$u.func.showToast({
|
||||
title: err,
|
||||
})
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
logout() {
|
||||
this.$u.func.logout();
|
||||
},
|
||||
submit() {
|
||||
let detail = this.detail
|
||||
if (!detail.phone && !/^1\d{10}$/.test(detail.phone)) {
|
||||
return uni.showToast({
|
||||
title: '请输入正确的手机号',
|
||||
duration: 2000,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
console.log(JSON.stringify(detail));
|
||||
},
|
||||
changeDefaultPicker(name, e) {
|
||||
this.detail[name] = e.detail.value;
|
||||
},
|
||||
changePicker(name, e) {
|
||||
this.detail[name] = this[`${name}Picker`][e.detail.value].name;
|
||||
},
|
||||
handleChooseImg() {
|
||||
let that = this;
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success(e) {
|
||||
that.detail.avatar = e.tempFilePaths[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
background-color: #f7f7f7;
|
||||
min-height: 100vh;
|
||||
padding: 0 0 200rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.complie {
|
||||
vertical-align: middle;
|
||||
padding: 10rpx 20rpx;
|
||||
font-size: 32rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5f88ff;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin-top: 30rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
font-size: 30rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #5f88ff;
|
||||
.avatar-image {
|
||||
width: 162rpx;
|
||||
height: 162rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
background-color: #82848a;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
padding: 0 36rpx;
|
||||
|
||||
.cell {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 40rpx 0;
|
||||
|
||||
font-size: 30rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: bold;
|
||||
color: #666666;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: 2rpx solid #efefef;
|
||||
}
|
||||
|
||||
.ipt {
|
||||
flex: 1;
|
||||
margin-left: 40rpx;
|
||||
text-align: right;
|
||||
font-size: 23rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hold {
|
||||
font-size: 27rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: bold;
|
||||
color: #c8c8ce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.back {
|
||||
margin-top: 40rpx;
|
||||
text-align: center;
|
||||
height: 109rpx;
|
||||
background: #ffffff;
|
||||
|
||||
font-size: 34rpx;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: bold;
|
||||
color: #141414;
|
||||
line-height: 109rpx;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 607 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
Before Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 422 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 538 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 915 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 662 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |