main
岩仔88 4 weeks ago
parent 7d8fd2bbfe
commit 81cfd72096

@ -11,7 +11,7 @@ class EntrustController extends Controller
public function GetList(Request $request)
{
$searchInfo = request('searchInfo');
$userid = $request->get('(userid)'); // 中间件产生的参数
$userid = $request->get('userid');//中间件产生的参数
$list = DB::table('s_list')
->leftJoin('s_period', 's_list.reservation_time', '=', 's_period.id')

@ -1,7 +1,6 @@
<script>
export default {
onLaunch: function() {
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
console.log('App Launch')
},
onShow: function() {
@ -14,19 +13,158 @@
</script>
<style lang="scss">
/*每个页面公共css */
@import '@/static/styles/theme.scss';
@import '@/uni_modules/uni-scss/index.scss';
/* #ifndef APP-NVUE */
@import '@/static/customicons.css';
//
page {
background-color: #f5f5f5;
background-color: #F5F7FA;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
/* #endif */
.example-info {
font-size: 14px;
color: #333;
padding: 10px;
.page-container {
min-height: 100vh;
background-color: #F5F7FA;
padding-bottom: 40rpx;
}
.primary-btn {
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
color: #FFFFFF;
border-radius: 24rpx;
font-weight: 500;
border: none;
&:active {
opacity: 0.9;
}
}
.secondary-btn {
background: linear-gradient(135deg, #1976D2 0%, #42A5F5 100%);
color: #FFFFFF;
border-radius: 24rpx;
font-weight: 500;
}
.danger-btn {
background: linear-gradient(135deg, #F44336 0%, #EF5350 100%);
color: #FFFFFF;
border-radius: 24rpx;
font-weight: 500;
}
.card {
background-color: #FFFFFF;
border-radius: 24rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
overflow: hidden;
}
.card-header {
padding: 24rpx 32rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
color: #FFFFFF;
}
.card-body {
padding: 32rpx;
}
.info-row {
display: flex;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #F0F0F0;
&:last-child {
border-bottom: none;
}
.label {
color: #999999;
font-size: 28rpx;
width: 160rpx;
flex-shrink: 0;
}
.value {
color: #333333;
font-size: 28rpx;
font-weight: 500;
flex: 1;
}
}
.status-badge {
display: inline-flex;
align-items: center;
padding: 6rpx 20rpx;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 500;
&.status-pending {
background-color: rgba(255, 152, 0, 0.1);
color: #FF9800;
}
&.status-success {
background-color: rgba(76, 175, 80, 0.1);
color: #4CAF50;
}
&.status-info {
background-color: rgba(33, 150, 243, 0.1);
color: #2196F3;
}
&.status-done {
background-color: rgba(158, 158, 158, 0.1);
color: #9E9E9E;
}
}
.action-bar {
display: flex;
justify-content: flex-end;
gap: 20rpx;
padding-top: 24rpx;
margin-top: 24rpx;
border-top: 1rpx solid #F0F0F0;
}
.action-btn {
padding: 16rpx 40rpx;
border-radius: 40rpx;
font-size: 28rpx;
font-weight: 500;
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 40rpx;
color: #CCCCCC;
.empty-icon {
font-size: 120rpx;
margin-bottom: 24rpx;
}
.empty-text {
font-size: 28rpx;
}
}
/* #endif */
</style>

@ -1,12 +1,14 @@
import {
useHttp
} from '@/tools/http';
import { getBaseUrl } from '@/config';
const {
isLoading,
sendRequest
} = useHttp();
let Url='http://192.168.80.76'
//let Url='http://yiji-qhdzhongyiyuan'
let Url = getBaseUrl();
let BaseUrl = Url + '/api/'
export const BaseFileUrl=()=>{

@ -0,0 +1,18 @@
const env = process.env.NODE_ENV || 'development'
const config = {
development: {
baseUrl: 'http://yiji-qhdzhongyiyuan'
},
production: {
baseUrl: 'http://192.168.80.76'
}
}
export const getBaseUrl = () => {
return config[env]?.baseUrl || config.development.baseUrl
}
export default {
getBaseUrl
}

@ -2,42 +2,44 @@
"pages": [{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
"navigationBarTitleText": "秦皇岛中医院",
"navigationStyle": "custom"
}
},
{
"path" : "pages/CheckItemMainList",
"path" : "pages/Login",
"style" :
{
"navigationBarTitleText" : "",
"navigationBarTitleText" : "登录",
"enablePullDownRefresh" : false,
"navigationStyle": "custom"
}
},
{
"path" : "pages/Login",
"path" : "pages/CheckItemMainList",
"style" :
{
"navigationBarTitleText" : "",
"enablePullDownRefresh" : false
"navigationBarTitleText" : "检查项目",
"enablePullDownRefresh" : true,
"navigationStyle": "custom"
}
},
{
"path" : "pages/PlanList",
"style" :
{
"navigationBarTitleText" : "",
"navigationBarTitleText" : "预约时段",
"enablePullDownRefresh" : false,
"navigationStyle": "custom"
}
}],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "秦皇岛中医院",
"navigationBarBackgroundColor": "#2E7D32",
"backgroundColor": "#F5F7FA",
"app-plus": {
"background": "#efeff4"
"background": "#F5F7FA"
}
}
}

@ -1,102 +1,174 @@
<template>
<view class="CheckItemMain">
<view class="head"></view>
<view class="userInfo" >
<view v-if="List.length>0">
<view class="title">患者信息</view>
<view class="row">
<view class="label" >姓名</view>
<view class="value" >{{List[0].user_name}}</view>
<view class="page-container">
<view class="page-header">
<view class="header-bg"></view>
<view class="header-content">
<view class="header-title">医技预约</view>
<view class="header-subtitle">秦皇岛中医院</view>
</view>
</view>
<view class="row">
<view class="label">性别</view>
<view class="value"><span v-if="List[0].user_sex==1"></span><span v-if="List[0].user_sex==2"></span></view>
<view class="user-card" v-if="List.length > 0">
<view class="user-info">
<view class="user-avatar">
<text class="avatar-text">{{ List[0].user_name ? List[0].user_name.substring(0, 1) : '患' }}</text>
</view>
<view class="user-detail">
<view class="user-name">{{ List[0].user_name }}</view>
<view class="user-meta">
<text class="meta-item">{{ List[0].user_sex == 1 ? '男' : '女' }}</text>
<text class="meta-divider">|</text>
<text class="meta-item">{{ List[0].user_phone || '未填写手机号' }}</text>
</view>
</view>
</view>
<view class="row">
<view class="label">手机号</view>
<view class="value">{{List[0].user_phone}}</view>
<view class="user-reg-num">
<text class="reg-label">登记号</text>
<text class="reg-value">{{ List[0].reg_num }}</text>
</view>
<view class="row">
<view class="label">注册号</view>
<view class="value">{{List[0].reg_num}}</view>
</view>
<view class="filter-section">
<view class="date-picker-wrapper">
<uni-icons type="calendar" size="18" color="#2E7D32"></uni-icons>
<view class="date-picker">
<uni-datetime-picker
v-model="SearchInfo.dateRange"
type="daterange"
@change="dateSelecteFunc"
:start="startDate"
:end="endDate"
/>
</view>
<view class="date">
<view class="datetime">
<uni-datetime-picker v-model="SearchInfo.dateRange" type="daterange" @change="dateSelecteFunc" />
</view>
</view>
<view class="list-section" v-if="List.length > 0">
<view class="section-header">
<text class="section-title">检查项目</text>
<text class="section-count"> {{ List.length }} </text>
</view>
<view class="item-card" v-for="(item, index) in List" :key="item.id">
<view class="item-header">
<view class="item-title">
<uni-icons type="medal" size="18" color="#2E7D32"></uni-icons>
<text class="title-text">{{ item.entrust }}</text>
</view>
<view class="item-status" :class="getStatusClass(item.list_status)">
{{ getStatusText(item.list_status) }}
</view>
</view>
<view class="item-body">
<view class="info-grid">
<view class="info-item">
<text class="info-label">医嘱时间</text>
<text class="info-value">{{ item.entrust_date }}</text>
</view>
<view class="info-item">
<text class="info-label">申请科室</text>
<text class="info-value">{{ item.reservation_department || '-' }}</text>
</view>
</view>
<view class="appointment-info" v-if="item.list_status == 1">
<uni-icons type="location" size="14" color="#2E7D32"></uni-icons>
<text class="appointment-text">
预约时段{{ item.reservation_date }}
{{ item.period_begin_time ? item.period_begin_time.substring(0, 5) : '' }}~{{ item.period_end_time ? item.period_end_time.substring(0, 5) : '' }}
</text>
</view>
<view v-if="List.length>0" class="list">
<view class="info" v-for="(item,index) in List">
<view class="row title_row">
<view class="item_title">检查项目{{item.entrust}}</view>
<view class="detail_button" @click="openDetail(item.id)"></view>
</view>
<view class="item_info">
<view>医嘱时间<span class="item_value">{{item.entrust_date}}</span></view>
<view>申请科室<span class="item_value">{{item.reservation_department}}</span></view>
<view>状态
<span v-if="item.list_status==0" class="item_value"></span>
<span v-if="item.list_status==1" class="item_value"></span>
<span v-if="item.list_status==2" class="item_value"></span>
<span v-if="item.list_status==3" class="item_value"></span>
<view class="item-footer">
<view class="detail-btn" @click="openDetail(item.id)">
<uni-icons type="info" size="14" color="#666"></uni-icons>
<text>详情</text>
</view>
<view v-if="item.list_status==1"><span class="item_value">{{item.reservation_date}} {{item.period_begin_time.substring(0,5)}}~{{item.period_end_time.substring(0,5)}}</span></view>
<view class="button_row" v-if="item.list_status==0">
<view class="button" @click="ToPlanList(1,item)"> </view>
<view class="action-btns">
<view v-if="item.list_status == 0" class="action-btn primary" @click="ToPlanList(1, item)">
<uni-icons type="plus" size="14" color="#FFFFFF"></uni-icons>
<text>预约</text>
</view>
<template v-if="item.list_status == 1">
<view class="action-btn danger" @click="Cancel(item)">
<uni-icons type="close" size="14" color="#FFFFFF"></uni-icons>
<text>取消</text>
</view>
<view class="action-btn secondary" @click="ToPlanList(2, item)">
<uni-icons type="refresh" size="14" color="#FFFFFF"></uni-icons>
<text>改约</text>
</view>
</template>
</view>
</view>
</view>
</view>
<view class="empty-state" v-else>
<view class="empty-icon">
<uni-icons type="inbox" size="80" color="#CCCCCC"></uni-icons>
</view>
<text class="empty-text">暂无检查项目</text>
<text class="empty-desc">请在日期范围内查询您的检查项目</text>
</view>
<uni-popup ref="popupDetail" type="center">
<view class="detail-popup" v-if="entrustInfo != null">
<view class="popup-header">
<text class="popup-title">检查详情</text>
<view class="popup-close" @click="popupDetail.close()">
<uni-icons type="close" size="20" color="#999"></uni-icons>
</view>
<view class="button_row" v-if="item.list_status==1">
<view class="button red" @click="Cancel(item)"> </view>
<view class="button blue" @click="ToPlanList(2,item)"> </view>
</view>
<view class="popup-body">
<view class="detail-item">
<text class="detail-label">检查项目</text>
<text class="detail-value">{{ entrustInfo.entrust }}</text>
</view>
<view class="detail-item">
<text class="detail-label">当前状态</text>
<view class="detail-value">
<view class="status-tag" :class="getStatusClass(entrustInfo.list_status)">
{{ getStatusText(entrustInfo.list_status) }}
</view>
</view>
<view class="nodata" v-else>
暂无记录
</view>
<uni-popup ref="popupDetail">
<view class="detail_main" v-if="entrustInfo!=null">
<view class="row">
<view>检查项目</view>
<view>{{entrustInfo.entrust}}</view>
<view class="detail-item">
<text class="detail-label">医嘱时间</text>
<text class="detail-value">{{ entrustInfo.entrust_date }} {{ entrustInfo.entrust_time || '' }}</text>
</view>
<view class="row">
<view>状态</view>
<view>
<span v-if="entrustInfo.list_status==0" class="item_value"></span>
<span v-if="entrustInfo.list_status==1" class="item_value"></span>
<span v-if="entrustInfo.list_status==2" class="item_value"></span>
<span v-if="entrustInfo.list_status==3" class="item_value"></span>
<view class="detail-item">
<text class="detail-label">申请科室</text>
<text class="detail-value">{{ entrustInfo.reservation_department || '-' }}</text>
</view>
<view class="detail-item">
<text class="detail-label">开单医生</text>
<text class="detail-value">{{ entrustInfo.docotr || '-' }}</text>
</view>
<view class="row">
<view>医嘱时间</view>
<view>{{entrustInfo.entrust_date}}</view>
<view class="detail-item">
<text class="detail-label">缴费状态</text>
<view class="detail-value">
<view class="pay-tag" :class="entrustInfo.is_pay == 1 ? 'paid' : 'unpaid'">
{{ entrustInfo.is_pay == 1 ? '已缴费' : '未缴费' }}
</view>
<view class="row">
<view>申请科室</view>
<view>{{entrustInfo.reservation_department}}</view>
</view>
<view class="row">
<view>开单医生</view>
<view>{{entrustInfo.docotr}}</view>
</view>
<view class="row">
<view>支付</view>
<view>
<uni-tag v-if="entrustInfo.is_pay==1" :inverted="true" text="否" type="warning" />
<uni-tag v-if="entrustInfo.is_pay==0" :inverted="true" text="是" type="success" />
<view class="detail-item" v-if="entrustInfo.list_status == 1">
<text class="detail-label">预约时段</text>
<text class="detail-value highlight">
{{ entrustInfo.reservation_date }}
{{ entrustInfo.period_begin_time ? entrustInfo.period_begin_time.substring(0, 5) : '' }}~{{ entrustInfo.period_end_time ? entrustInfo.period_end_time.substring(0, 5) : '' }}
</text>
</view>
</view>
<view class="row" v-if="entrustInfo.list_status==1">
<view>预约时段</view>
<view>{{entrustInfo.reservation_date}} {{entrustInfo.period_begin_time.substring(0,5)}}~{{entrustInfo.period_end_time.substring(0,5)}}</view>
<view class="popup-footer">
<view class="popup-btn" @click="popupDetail.close()"></view>
</view>
</view>
</uni-popup>
@ -104,40 +176,71 @@
</template>
<script setup>
import{ref,onMounted} from "vue"
import { ref, computed } from "vue"
import { EntrustGetList, H5_CancelYuYue, GetEntrustDetail } from "@/api"
import { onLoad, onShow } from "@dcloudio/uni-app"
let SearchInfo = ref({
dateRange:['2021-05-01','2049-01-01'],
})
let List=ref([])
dateRange: []
});
let List = ref([]);
let entrustInfo = ref(null);
let popupDetail=ref('')
let popupDetail = ref(null);
let startDate = ref('2024-01-01');
let endDate = ref('2030-12-31');
const getStatusClass = (status) => {
const classMap = {
0: 'status-pending',
1: 'status-success',
2: 'status-info',
3: 'status-done'
};
return classMap[status] || 'status-pending';
};
const getStatusText = (status) => {
const textMap = {
0: '待预约',
1: '已预约',
2: '已登记',
3: '已完成'
};
return textMap[status] || '未知';
};
const GetList = () => {
uni.showLoading({ title: '加载中' });
EntrustGetList({ searchInfo: SearchInfo.value }).then(res => {
console.log(res)
uni.hideLoading();
if (res.status) {
List.value=res.data.list
}
})
List.value = res.data.list;
}
}).catch(() => {
uni.hideLoading();
});
};
const openDetail = (id) => {
popupDetail.value.open()
GetEntrustDetailFunc(id)
}
popupDetail.value.open();
GetEntrustDetailFunc(id);
};
const GetEntrustDetailFunc = (id) => {
GetEntrustDetail({ id: id }).then(res => {
if (res.status) {
entrustInfo.value=res.data.info
}
})
entrustInfo.value = res.data.info;
}
});
};
const dateSelecteFunc = (e) => {
SearchInfo.value.dateRange=e
GetList()
}
//
SearchInfo.value.dateRange = e;
GetList();
};
const ToPlanList = (do_type, item) => {
let data = {
do_type: do_type,
@ -145,203 +248,510 @@
regnum: item.reg_num,
entrustid: [item.entrust_id],
episodeid: item.episodeid
}
};
uni.navigateTo({
url: '/pages/PlanList?data=' + encodeURIComponent(JSON.stringify(data))
})
}
//
});
};
const Cancel = (item) => {
uni.showModal({
cancelText: "取消",
confirmText: "确定",
title: '提示',
content: '确定取消预约吗?',
title: '取消预约',
content: '确定要取消该预约吗?取消后需要重新预约。',
confirmColor: '#F44336',
success: function(res) {
if (res.confirm) {
H5_CancelYuYue({MainListId:item.id}).then(res => {
console.log(res)
uni.showLoading({ title: '处理中' });
H5_CancelYuYue({
MainListId: item.id,
reg_num: item.reg_num
}).then(res => {
uni.hideLoading();
if (res.status) {
GetList()
uni.showToast({
title: '取消成功',
icon: 'success'
});
GetList();
}
})
}).catch(() => {
uni.hideLoading();
});
}
}
});
};
function getDateRange() {
const today = new Date();
const prevMonth = new Date(today.getFullYear(), today.getMonth() - 1, today.getDate());
const nextMonth = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate());
const formatDate = (date) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
return [formatDate(prevMonth), formatDate(nextMonth)];
}
// 1
function getDatesAroundCurrentMonth() {
var today = new Date();
//
function getPreviousMonth(date) {
return new Date(date.getFullYear(), date.getMonth() - 1, date.getDate());
onLoad(() => {
SearchInfo.value.dateRange = getDateRange();
GetList();
});
onShow(() => {
GetList();
});
</script>
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background: #F5F7FA;
padding-bottom: 40rpx;
}
//
function getNextMonth(date) {
return new Date(date.getFullYear(), date.getMonth() + 1, date.getDate());
.page-header {
position: relative;
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 200rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
border-radius: 0 0 48rpx 48rpx;
}
// YYYY-MM-DD
function formatDate(date) {
var year = date.getFullYear();
var month = ("0" + (date.getMonth() + 1)).slice(-2); // 0+1
var day = ("0" + date.getDate()).slice(-2);
return year + "-" + month + "-" + day;
.header-content {
position: relative;
z-index: 1;
padding: 60rpx 40rpx 40rpx;
text-align: center;
.header-title {
font-size: 40rpx;
font-weight: 600;
color: #FFFFFF;
letter-spacing: 4rpx;
}
.header-subtitle {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
margin-top: 8rpx;
}
}
}
var currentDateFormatted = formatDate(today);
var previousMonthDate = formatDate(getPreviousMonth(today));
var nextMonthDate = formatDate(getNextMonth(today));
.user-card {
margin: -40rpx 32rpx 24rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
position: relative;
z-index: 2;
return {
currentDate: currentDateFormatted,
previousMonth: previousMonthDate,
nextMonth: nextMonthDate
};
.user-info {
display: flex;
align-items: center;
.user-avatar {
width: 96rpx;
height: 96rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
.avatar-text {
font-size: 40rpx;
font-weight: 600;
color: #FFFFFF;
}
}
onLoad(()=>{
var dates = getDatesAroundCurrentMonth();
.user-detail {
flex: 1;
margin-left: 24rpx;
SearchInfo.value.dateRange=[dates.previousMonth,dates.nextMonth]
.user-name {
font-size: 36rpx;
font-weight: 600;
color: #333333;
}
GetList()
})
</script>
.user-meta {
display: flex;
align-items: center;
margin-top: 8rpx;
.meta-item {
font-size: 26rpx;
color: #999999;
}
<style scoped>
.CheckItemMain{
height: calc(100vh - 120rpx) ;
background: radial-gradient(circle at top center, #dcdcdc 30%, #e3e3e3, transparent 2%);
padding-top: 30rpx;
}
.userInfo{
background-color: #33cdc9;
margin-left: 20rpx;
margin-right: 20rpx;
border-radius: 30rpx;
padding: 40rpx 40rpx 0rpx 40rpx;
border: 1rpx solid #fff;
}
.userInfo .row{
.meta-divider {
margin: 0 16rpx;
color: #E0E0E0;
}
}
}
}
.user-reg-num {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20rpx;
padding-top: 20rpx;
border-top: 1rpx solid #F0F0F0;
.reg-label {
font-size: 26rpx;
color: #999999;
}
.reg-value {
font-size: 28rpx;
font-weight: 500;
color: #2E7D32;
}
}
}
.filter-section {
margin: 0 32rpx 24rpx;
.date-picker-wrapper {
display: flex;
align-items: center;
background: #FFFFFF;
border-radius: 16rpx;
padding: 20rpx 24rpx;
.date-picker {
flex: 1;
margin-left: 12rpx;
}
}
}
.list-section {
padding: 0 32rpx;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
color: #fff;
.section-count {
font-size: 26rpx;
color: #999999;
}
.userInfo .value{
margin-left: 20rpx;
}
.userInfo .label {
text-align: right;
width: 30% ;
.item-card {
background: #FFFFFF;
border-radius: 24rpx;
margin-bottom: 24rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 28rpx;
background: #FAFAFA;
border-bottom: 1rpx solid #F0F0F0;
.item-title {
display: flex;
align-items: center;
.title-text {
font-size: 30rpx;
font-weight: 600;
color: #333333;
margin-left: 12rpx;
}
.row{
}
.item-status {
padding: 8rpx 20rpx;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 500;
&.status-pending {
background: rgba(255, 152, 0, 0.1);
color: #FF9800;
}
&.status-success {
background: rgba(76, 175, 80, 0.1);
color: #4CAF50;
}
&.status-info {
background: rgba(33, 150, 243, 0.1);
color: #2196F3;
}
&.status-done {
background: rgba(158, 158, 158, 0.1);
color: #9E9E9E;
}
}
}
.item-body {
padding: 24rpx 28rpx;
.info-grid {
display: flex;
gap: 40rpx;
.info-item {
flex: 1;
.info-label {
display: block;
font-size: 24rpx;
color: #999999;
margin-bottom: 8rpx;
}
.junfen{
.info-value {
font-size: 28rpx;
color: #333333;
}
.title_row{
border-bottom: 1rpx solid #ccc;
padding: 20rpx;
}
}
.appointment-info {
display: flex;
align-items: center;
margin-top: 20rpx;
padding: 16rpx 20rpx;
background: rgba(46, 125, 50, 0.05);
border-radius: 12rpx;
.appointment-text {
font-size: 26rpx;
color: #2E7D32;
margin-left: 8rpx;
}
}
}
.item-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 28rpx;
border-top: 1rpx solid #F0F0F0;
.detail-btn {
display: flex;
align-items: center;
font-size: 26rpx;
color: #666666;
text {
margin-left: 6rpx;
}
}
.detail_button{
.action-btns {
display: flex;
gap: 16rpx;
.action-btn {
display: flex;
align-items: center;
padding: 14rpx 28rpx;
border-radius: 32rpx;
font-size: 26rpx;
color: #666;
border: 1px solid #ccc;
border-radius: 8rpx;
padding: 0rpx 10rpx;
margin-left: 10rpx;
width: 56rpx;
height: 40rpx;
color: #33cdc9;
}
.title{
font-weight: 700;
color:#fff;
}
.date{
text-align: center;
font-size: 30rpx;
background-color: #fff;
padding: 20rpx 60rpx;
border-radius: 30rpx;
box-shadow: 0rpx 10rpx 10rpx #add2d1;
color: #333;
/* transform: translateY(40rpx); */
position: relative;
top: 50rpx;
white-space: nowrap;
text {
margin-left: 6rpx;
}
.datetime{
&.primary {
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
color: #FFFFFF;
}
&.secondary {
background: linear-gradient(135deg, #1976D2 0%, #42A5F5 100%);
color: #FFFFFF;
}
&.danger {
background: linear-gradient(135deg, #F44336 0%, #EF5350 100%);
color: #FFFFFF;
}
}
}
}
.list{
padding: 20rpx;
}
.info{
margin-top: 60rpx;
padding: 20rpx;
background-color: #fff;
border-radius: 20rpx;
margin-bottom: -20rpx;
}
.item_title{
color:#999;
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 40rpx;
.empty-icon {
margin-bottom: 24rpx;
}
.item_info{
padding: 30rpx 50rpx;
color: #333;
.empty-text {
font-size: 32rpx;
color: #CCCCCC;
margin-bottom: 12rpx;
}
.item_info view{
margin-top: 20rpx;
.empty-desc {
font-size: 26rpx;
color: #DDDDDD;
}
.item_value{
font-weight: 700;
}
.button{
width: 100%;
height: 60rpx;
line-height: 60rpx;
border-radius: 20rpx;
background-color: #33cdc9;
text-align: center;
color: #fff;
margin-top: 20rpx;
margin-left: 10px;
margin-right: 10px;
.detail-popup {
width: 640rpx;
background: #FFFFFF;
border-radius: 24rpx;
overflow: hidden;
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28rpx 32rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
.popup-title {
font-size: 34rpx;
font-weight: 600;
color: #FFFFFF;
}
.red{
background-color: coral;
.popup-close {
padding: 8rpx;
}
.blue{
background-color: #39a6cd;
}
.button_row{
.popup-body {
padding: 28rpx 32rpx;
max-height: 600rpx;
overflow-y: auto;
.detail-item {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 16rpx 0;
border-bottom: 1rpx solid #F5F5F5;
&:last-child {
border-bottom: none;
}
.nodata{
.detail-label {
font-size: 28rpx;
color: #999999;
flex-shrink: 0;
width: 160rpx;
}
.detail-value {
font-size: 28rpx;
color: #333333;
text-align: right;
flex: 1;
&.highlight {
color: #2E7D32;
font-weight: 500;
}
}
.status-tag {
padding: 6rpx 16rpx;
border-radius: 16rpx;
font-size: 24rpx;
&.status-pending {
background: rgba(255, 152, 0, 0.1);
color: #FF9800;
}
&.status-success {
background: rgba(76, 175, 80, 0.1);
color: #4CAF50;
}
&.status-info {
background: rgba(33, 150, 243, 0.1);
color: #2196F3;
}
&.status-done {
background: rgba(158, 158, 158, 0.1);
color: #9E9E9E;
}
}
.pay-tag {
padding: 6rpx 16rpx;
border-radius: 16rpx;
font-size: 24rpx;
&.paid {
background: rgba(76, 175, 80, 0.1);
color: #4CAF50;
}
&.unpaid {
background: rgba(255, 152, 0, 0.1);
color: #FF9800;
}
}
}
}
.popup-footer {
padding: 20rpx 32rpx;
border-top: 1rpx solid #F0F0F0;
.popup-btn {
text-align: center;
margin-top: 100rpx;
color: #ccc;
}
.detail_main{
background-color: #fff;
padding: 40rpx 30rpx 20rpx 30rpx;
width:600rpx;
border-radius: 40rpx;
padding: 20rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
border-radius: 16rpx;
font-size: 30rpx;
color: #FFFFFF;
}
}
}
</style>

@ -1,8 +1,66 @@
<template>
<view class="LoginMain">
<view style="padding-top: 30%;">
<uni-easyinput type="text" v-model="regnum" placeholder="请输入患者id" />
<button style="margin-top: 20rpx;background-color: #33cdc9;color: #fff;" @click="LoginFunc()"> </button>
<view class="login-page">
<view class="login-header">
<view class="header-bg"></view>
<view class="hospital-logo">
<view class="logo-icon">
<text class="icon-hospital">+</text>
</view>
</view>
<view class="hospital-info">
<text class="hospital-name">秦皇岛中医院</text>
<text class="hospital-subtitle">医技预约系统</text>
</view>
</view>
<view class="login-content">
<view class="welcome-section">
<text class="welcome-title">欢迎使用</text>
<text class="welcome-desc">请输入患者登记号进行登录</text>
</view>
<view class="login-form">
<view class="form-item">
<view class="input-wrapper">
<uni-icons type="person" size="20" color="#2E7D32"></uni-icons>
<input
class="input-field"
type="text"
v-model="regnum"
placeholder="请输入患者登记号"
placeholder-class="placeholder-text"
@confirm="LoginFunc"
/>
</view>
</view>
<view class="login-tips">
<uni-icons type="info" size="14" color="#999"></uni-icons>
<text class="tips-text">登记号可在就诊卡或挂号单上找到</text>
</view>
<button class="login-btn" :disabled="regnum === ''" @click="LoginFunc()">
<text v-if="!loading"> </text>
<text v-else>...</text>
</button>
</view>
<view class="login-footer">
<view class="footer-item">
<uni-icons type="medal" size="16" color="#2E7D32"></uni-icons>
<text>三甲医院</text>
</view>
<view class="footer-divider"></view>
<view class="footer-item">
<uni-icons type="heart" size="16" color="#2E7D32"></uni-icons>
<text>用心服务</text>
</view>
<view class="footer-divider"></view>
<view class="footer-item">
<uni-icons type="staff" size="16" color="#2E7D32"></uni-icons>
<text>专业医疗</text>
</view>
</view>
</view>
</view>
</template>
@ -11,30 +69,234 @@
import { ref, onMounted } from "vue"
import { Login } from "@/api"
import { onLoad } from "@dcloudio/uni-app"
let regnum = ref('');
let loading = ref(false);
const LoginFunc = () => {
if(regnum.value==''){
if (regnum.value === '') {
uni.showToast({
title: '请输入患者登记号',
icon: 'none'
});
return false;
}
loading.value = true;
Login({ regnum: regnum.value }).then(res => {
console.log(res)
loading.value = false;
if (res.status) {
sessionStorage.setItem("access_token",res.data.token)
sessionStorage.setItem("refresh_token",res.data.refresh_token)
uni.setStorageSync("access_token", res.data.token);
uni.setStorageSync("refresh_token", res.data.refresh_token);
uni.showToast({
title: '登录成功',
icon: 'success'
});
setTimeout(() => {
uni.reLaunch({
url: '/pages/CheckItemMainList'
})
});
}, 500);
}
})
}).catch(() => {
loading.value = false;
});
}
onMounted(() => {
//LoginFunc()
})
const token = uni.getStorageSync("access_token");
if (token) {
uni.reLaunch({
url: '/pages/CheckItemMainList'
});
}
});
</script>
<style scoped>
.LoginMain{
padding: 20rpx;
<style lang="scss" scoped>
.login-page {
min-height: 100vh;
background: linear-gradient(180deg, #F5F7FA 0%, #FFFFFF 100%);
}
.login-header {
position: relative;
padding: 80rpx 40rpx 60rpx;
text-align: center;
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 280rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 50%, #81C784 100%);
border-radius: 0 0 60rpx 60rpx;
}
.hospital-logo {
position: relative;
z-index: 1;
margin-bottom: 24rpx;
.logo-icon {
width: 120rpx;
height: 120rpx;
background: #FFFFFF;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 32rpx rgba(46, 125, 50, 0.3);
.icon-hospital {
font-size: 60rpx;
font-weight: bold;
color: #2E7D32;
}
}
}
.hospital-info {
position: relative;
z-index: 1;
.hospital-name {
display: block;
font-size: 40rpx;
font-weight: 600;
color: #FFFFFF;
letter-spacing: 4rpx;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.hospital-subtitle {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
margin-top: 12rpx;
}
}
}
.login-content {
padding: 40rpx 48rpx;
.welcome-section {
text-align: center;
margin-bottom: 60rpx;
.welcome-title {
display: block;
font-size: 44rpx;
font-weight: 600;
color: #333333;
margin-bottom: 16rpx;
}
.welcome-desc {
display: block;
font-size: 28rpx;
color: #999999;
}
}
.login-form {
.form-item {
margin-bottom: 24rpx;
.input-wrapper {
display: flex;
align-items: center;
background: #FFFFFF;
border: 2rpx solid #E8E8E8;
border-radius: 24rpx;
padding: 0 32rpx;
height: 100rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #2E7D32;
box-shadow: 0 0 0 4rpx rgba(46, 125, 50, 0.1);
}
.input-field {
flex: 1;
font-size: 32rpx;
color: #333333;
margin-left: 16rpx;
}
}
}
.login-tips {
display: flex;
align-items: center;
justify-content: center;
margin: 32rpx 0;
.tips-text {
font-size: 24rpx;
color: #999999;
margin-left: 8rpx;
}
}
.login-btn {
width: 100%;
height: 100rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
border-radius: 24rpx;
font-size: 34rpx;
font-weight: 500;
color: #FFFFFF;
border: none;
letter-spacing: 8rpx;
box-shadow: 0 8rpx 24rpx rgba(46, 125, 50, 0.3);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
opacity: 0.9;
}
&[disabled] {
background: #CCCCCC;
box-shadow: none;
}
}
}
.login-footer {
display: flex;
align-items: center;
justify-content: center;
margin-top: 80rpx;
padding: 40rpx 0;
.footer-item {
display: flex;
align-items: center;
font-size: 24rpx;
color: #666666;
text {
margin-left: 8rpx;
}
}
.footer-divider {
width: 2rpx;
height: 24rpx;
background: #E0E0E0;
margin: 0 24rpx;
}
}
}
.placeholder-text {
color: #CCCCCC;
font-size: 32rpx;
}
</style>

@ -1,210 +1,516 @@
<template>
<view class="PlanListMain">
<view class="head"></view>
<view class="userInfo" v-if="MianInfo">
<view class="title">选择预约日期及时段</view>
<view class="row">
<view class="label">登记号</view>
<view class="value">{{MianInfo.reg_num}}</view>
<view class="page-container">
<view class="page-header">
<view class="header-bg"></view>
<view class="header-content">
<view class="back-btn" @click="goBack">
<uni-icons type="left" size="20" color="#FFFFFF"></uni-icons>
</view>
<view class="row">
<view class="label">医嘱</view>
<view class="value">{{MianInfo.entrust}}</view>
<view class="header-title">选择预约时段</view>
<view class="header-placeholder"></view>
</view>
<view class="date">
<view class="datetime">
<uni-datetime-picker v-model="SearchInfo.date" :clear-icon="false" type="date" @change="dateSelecteFunc" />
</view>
<view class="info-card" v-if="MianInfo">
<view class="info-header">
<uni-icons type="medal" size="20" color="#2E7D32"></uni-icons>
<text class="info-title">{{ MianInfo.entrust }}</text>
</view>
<view class="info-body">
<view class="info-row">
<text class="info-label">登记号</text>
<text class="info-value">{{ MianInfo.reg_num }}</text>
</view>
<view class="info-row">
<text class="info-label">执行科室</text>
<text class="info-value">{{ MianInfo.implement_department || '-' }}</text>
</view>
</view>
<view class="list">
<view class="info" v-for="(item,index) in List">
<view>
<view class="row">
<view class="label">执行科室</view>
<view class="value">{{MianInfo.implement_department}}</view>
</view>
<view class="row">
<view class="label">资源</view>
<view class="value">{{item.department_resources_name}}</view>
<view class="date-section">
<view class="date-picker-card">
<view class="date-label">选择日期</view>
<uni-datetime-picker
v-model="SearchInfo.date"
:clear-icon="false"
type="date"
@change="dateSelecteFunc"
/>
</view>
</view>
<view class="time-section" v-if="List.length > 0">
<view class="section-header">
<text class="section-title">可预约时段</text>
<text class="section-tip">点击时段进行预约</text>
</view>
<view class="time-grid">
<view
class="time-card"
v-for="(item, index) in List"
:key="item.id"
@click="StartYuYue(item)"
>
<view class="time-main">
<view class="time-range">
<text class="time-start">{{ item.begin_time ? item.begin_time.substring(0, 5) : '' }}</text>
<text class="time-separator">-</text>
<text class="time-end">{{ item.end_time ? item.end_time.substring(0, 5) : '' }}</text>
</view>
<view class="row">
<view class="label">时间段</view>
<view class="value" v-if="item.begin_time">{{item.begin_time.substring(0,5)}}~{{item.end_time.substring(0,5)}}</view>
<view class="time-progress">
<view class="progress-bar">
<view
class="progress-fill"
:style="{ width: getProgressWidth(item) + '%' }"
:class="{ 'progress-warning': getProgressWidth(item) >= 80 }"
></view>
</view>
<text class="progress-text" :class="{ 'text-warning': getProgressWidth(item) >= 80 }">
{{ item.used_count || 0 }}/{{ item.count || 0 }}
</text>
</view>
</view>
<view class="time-footer">
<view class="resource-name">
<uni-icons type="location" size="12" color="#999"></uni-icons>
<text>{{ item.department_resources_name }}</text>
</view>
<view class="book-btn">预约</view>
</view>
</view>
</view>
</view>
<view class="empty-state" v-else-if="SearchInfo.date">
<view class="empty-icon">
<uni-icons type="calendar" size="80" color="#CCCCCC"></uni-icons>
</view>
<view class="right">
<view class="right_top">
<view class="button" @click="StartYuYue(item)"></view>
<text class="empty-text">该日期暂无可约时段</text>
<text class="empty-desc">请尝试选择其他日期</text>
</view>
<view class="right_bottom">已约/总数<span style="color: darkturquoise;">{{item.used_count}}</span>/{{item.count}}</view>
<view class="tips-section">
<view class="tips-title">
<uni-icons type="info" size="16" color="#FF9800"></uni-icons>
<text>温馨提示</text>
</view>
<view class="tips-list">
<text class="tips-item">1. 请按时到达逾期可能需要重新预约</text>
<text class="tips-item">2. 如需取消或改约请提前操作</text>
<text class="tips-item">3. 如有疑问请咨询导诊台</text>
</view>
</view>
</view>
</template>
<script setup>
import{ref,onMounted} from "vue"
import { ref, computed } from "vue"
import { GetEnablePlan, H5_YuYue } from "@/api"
import { onLoad, onShow } from "@dcloudio/uni-app"
let SearchInfo = ref({
date: '',
})
do_type: 1,
appointment_type: 2,
mainlistid: []
});
let List = ref([]);
let MianInfo=ref(null); //
let MianInfo = ref(null);
const getProgressWidth = (item) => {
if (!item.count || item.count == 0) return 0;
return Math.min(100, Math.round((item.used_count || 0) / item.count * 100));
};
const GetList = () => {
uni.showLoading({ title: '加载中' });
GetEnablePlan({ ...SearchInfo.value }).then(res => {
uni.hideLoading();
if (res.status) {
List.value=res.data.plan_list
MianInfo.value=res.data.mainInfo
SearchInfo.value.mainlistid=[MianInfo.value.id]
List.value = res.data.plan_list || [];
MianInfo.value = res.data.mainInfo;
if (MianInfo.value) {
SearchInfo.value.mainlistid = [MianInfo.value.id];
}
})
}
}).catch(() => {
uni.hideLoading();
});
};
const dateSelecteFunc = (e) => {
SearchInfo.value.date=e
GetList()
}
SearchInfo.value.date = e;
GetList();
};
const StartYuYue = (item) => {
if ((item.used_count || 0) >= (item.count || 0)) {
uni.showToast({
title: '该时段已约满',
icon: 'none'
});
return;
}
const timeStr = `${item.begin_time ? item.begin_time.substring(0, 5) : ''}-${item.end_time ? item.end_time.substring(0, 5) : ''}`;
uni.showModal({
cancelText: "取消",
confirmText:"确定",
title: '提示',
content: '确定预约 '+SearchInfo.value.date+' '+item.begin_time.substring(0,5)+'~'+item.end_time.substring(0,5)+' 时段吗?',
confirmText: "确认预约",
title: '预约确认',
content: `确定预约 ${SearchInfo.value.date} ${timeStr} 时段吗?`,
confirmColor: '#2E7D32',
success: function(res) {
if (res.confirm) {
SearchInfo.value.planid=item.id
uni.showLoading({ title: '预约中' });
SearchInfo.value.planid = item.id;
H5_YuYue({ ...SearchInfo.value }).then(res => {
uni.hideLoading();
if (res.status) {
uni.showToast({
title: '预约成功',
icon: 'success'
});
setTimeout(function(){
setTimeout(() => {
uni.redirectTo({
url: '/pages/CheckItemMainList'
})
},1000)
});
}, 1000);
}
})
}).catch(() => {
uni.hideLoading();
});
}
}
});
};
const goBack = () => {
uni.navigateBack();
};
const getTodayDate = () => {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
}
onLoad((option) => {
SearchInfo.value = JSON.parse(decodeURIComponent(option.data))
var today = new Date();
// YYYY-MM-DD
function formatDate(date) {
var year = date.getFullYear();
var month = ("0" + (date.getMonth() + 1)).slice(-2); // 0+1
var day = ("0" + date.getDate()).slice(-2);
return year + "-" + month + "-" + day;
}
SearchInfo.value.date = formatDate(today);
GetList()
})
if (option.data) {
const data = JSON.parse(decodeURIComponent(option.data));
SearchInfo.value = { ...SearchInfo.value, ...data };
}
SearchInfo.value.date = getTodayDate();
GetList();
});
</script>
<style scoped>
.PlanListMain {
height: calc(100vh - 120rpx);
background: radial-gradient(circle at top center, #dcdcdc 30%, #e3e3e3, transparent 2%);
padding-top: 30rpx;
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background: #F5F7FA;
padding-bottom: 40rpx;
}
.userInfo {
background-color: #33cdc9;
margin-left: 20rpx;
margin-right: 20rpx;
border-radius: 30rpx;
padding: 40rpx 40rpx 0rpx 40rpx;
border: 1rpx solid #fff;
.page-header {
position: relative;
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 180rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
border-radius: 0 0 48rpx 48rpx;
}
.userInfo .row {
margin-top: 20rpx;
font-size: 32rpx;
.header-content {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 60rpx 32rpx 40rpx;
.back-btn {
width: 64rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
}
color: #fff;
.header-title {
font-size: 36rpx;
font-weight: 600;
color: #FFFFFF;
}
.userInfo .value {
margin-left: 20rpx;
.header-placeholder {
width: 64rpx;
}
}
}
.userInfo .label {
text-align: right;
.info-card {
margin: -40rpx 32rpx 24rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 28rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
position: relative;
z-index: 2;
width: 30%;
.info-header {
display: flex;
align-items: center;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #F0F0F0;
.info-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-left: 12rpx;
}
}
.row {
.info-body {
padding-top: 20rpx;
.info-row {
display: flex;
justify-content: space-between;
padding: 8rpx 0;
.info-label {
font-size: 28rpx;
color: #999999;
}
.date{
text-align: center;
font-size: 30rpx;
background-color: #fff;
padding: 20rpx 60rpx;
border-radius: 30rpx;
box-shadow: 0rpx 10rpx 10rpx #add2d1;
color: #333;
/* transform: translateY(40rpx); */
position: relative;
top: 50rpx;
white-space: nowrap;
.info-value {
font-size: 28rpx;
color: #333333;
font-weight: 500;
}
}
.title{
font-weight: 700;
color:#fff;
font-size: 32rpx;
}
.list{
margin-top: 60rpx;
padding: 20rpx;
}
.info{
background-color: #fff;
padding: 40rpx 40rpx 20rpx 40rpx;
.date-section {
padding: 0 32rpx;
margin-bottom: 24rpx;
.date-picker-card {
display: flex;
align-items: center;
justify-content: space-between;
background: #FFFFFF;
border-radius: 20rpx;
color: #333;
padding: 24rpx 28rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
.date-label {
font-size: 30rpx;
color: #333333;
font-weight: 500;
}
}
}
.info .row{
.time-section {
padding: 0 32rpx;
box-sizing: border-box;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
.section-tip {
font-size: 24rpx;
color: #999999;
}
.info .row .value{
font-weight: 700;
}
.info .right{
.time-grid {
display: flex;
flex-direction: column;
gap: 20rpx;
.time-card {
width: 100%;
background: #FFFFFF;
border-radius: 20rpx;
padding: 28rpx 32rpx;
box-sizing: border-box;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
&:active {
transform: scale(0.99);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.info .right .right_top{
.time-main {
display: flex;
justify-content: center;
justify-content: space-between;
align-items: center;
.time-range {
display: flex;
align-items: center;
.time-start, .time-end {
font-size: 44rpx;
font-weight: 600;
color: #2E7D32;
}
.time-separator {
margin: 0 12rpx;
color: #CCCCCC;
font-size: 36rpx;
}
.info .right .right_bottom{
}
.time-progress {
display: flex;
justify-content: flex-end;
flex-direction: column;
align-items: flex-end;
.progress-bar {
width: 160rpx;
height: 12rpx;
background: #F0F0F0;
border-radius: 6rpx;
overflow: hidden;
margin-bottom: 8rpx;
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #4CAF50 0%, #81C784 100%);
border-radius: 6rpx;
transition: width 0.3s ease;
&.progress-warning {
background: linear-gradient(90deg, #FF9800 0%, #FFB74D 100%);
}
}
}
.progress-text {
font-size: 26rpx;
color: #4CAF50;
font-weight: 500;
&.text-warning {
color: #FF9800;
}
}
}
}
.time-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20rpx;
padding-top: 20rpx;
border-top: 1rpx solid #F5F5F5;
.resource-name {
display: flex;
align-items: center;
font-size: 26rpx;
color: #666666;
text {
margin-left: 8rpx;
}
}
.book-btn {
padding: 14rpx 48rpx;
background: linear-gradient(135deg, #2E7D32 0%, #4CAF50 100%);
border-radius: 32rpx;
font-size: 28rpx;
color: #FFFFFF;
font-weight: 500;
}
.button{
width: 70rpx;
height: 60rpx;
text-align: center;
line-height: 60rpx;
background-color: #33cdc9;
padding: 20rpx;
}
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 40rpx;
background: #FFFFFF;
margin: 0 32rpx;
border-radius: 24rpx;
.empty-icon {
margin-bottom: 24rpx;
}
.empty-text {
font-size: 32rpx;
color: #CCCCCC;
margin-bottom: 12rpx;
}
.empty-desc {
font-size: 26rpx;
color: #DDDDDD;
}
}
.tips-section {
margin: 32rpx 32rpx 0;
background: rgba(255, 152, 0, 0.08);
border-radius: 20rpx;
color: #fff;
padding: 24rpx 28rpx;
border-left: 6rpx solid #FF9800;
.tips-title {
display: flex;
align-items: center;
font-size: 28rpx;
font-weight: 600;
color: #FF9800;
margin-bottom: 16rpx;
text {
margin-left: 8rpx;
}
}
.tips-list {
.tips-item {
display: block;
font-size: 24rpx;
color: #666666;
line-height: 2;
}
}
}
</style>

@ -1,29 +1,40 @@
<template>
<view class="container">
<view class="intro">本项目已包含uni ui组件无需import和注册可直接使用在代码区键入字母u即可通过代码助手列出所有可用组件光标置于组件名称处按F1即可查看组件文档</view>
<text class="intro">详见</text>
<uni-link :href="href" :text="href"></uni-link>
<view class="loading">正在跳转...</view>
</view>
</template>
<script>
export default {
data() {
return {
href: 'https://uniapp.dcloud.io/component/README?id=uniui'
}
return {}
},
methods: {
onLoad() {
const token = uni.getStorageSync("access_token");
if (token) {
uni.reLaunch({
url: '/pages/CheckItemMainList'
});
} else {
uni.reLaunch({
url: '/pages/Login'
});
}
}
}
</script>
<style>
.container {
padding: 20px;
font-size: 14px;
line-height: 24px;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #F5F7FA;
}
.loading {
color: #999999;
font-size: 28rpx;
}
</style>

@ -0,0 +1,86 @@
$primary-color: #2E7D32;
$primary-light: #4CAF50;
$primary-dark: #1B5E20;
$secondary-color: #1976D2;
$warning-color: #FF9800;
$danger-color: #F44336;
$success-color: #4CAF50;
$info-color: #2196F3;
$text-primary: #333333;
$text-secondary: #666666;
$text-hint: #999999;
$text-white: #FFFFFF;
$bg-primary: #F5F7FA;
$bg-card: #FFFFFF;
$bg-header: linear-gradient(135deg, $primary-color 0%, $primary-light 100%);
$border-radius: 16rpx;
$border-radius-lg: 24rpx;
$border-radius-xl: 32rpx;
$shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
$shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.12);
$shadow-lg: 0 8rpx 24rpx rgba(0, 0, 0, 0.16);
$spacing-xs: 8rpx;
$spacing-sm: 16rpx;
$spacing-md: 24rpx;
$spacing-lg: 32rpx;
$spacing-xl: 48rpx;
@mixin card-style {
background-color: $bg-card;
border-radius: $border-radius-lg;
box-shadow: $shadow-sm;
}
@mixin button-primary {
background: linear-gradient(135deg, $primary-color 0%, $primary-light 100%);
color: $text-white;
border-radius: $border-radius-lg;
font-weight: 500;
transition: all 0.3s ease;
&:active {
opacity: 0.9;
transform: scale(0.98);
}
}
@mixin button-secondary {
background: linear-gradient(135deg, $secondary-color 0%, #42A5F5 100%);
color: $text-white;
border-radius: $border-radius-lg;
font-weight: 500;
transition: all 0.3s ease;
}
@mixin button-danger {
background: linear-gradient(135deg, $danger-color 0%, #EF5350 100%);
color: $text-white;
border-radius: $border-radius-lg;
font-weight: 500;
}
@mixin status-badge($color) {
display: inline-flex;
align-items: center;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 500;
background-color: rgba($color, 0.1);
color: $color;
}
@mixin page-container {
min-height: 100vh;
background-color: $bg-primary;
}
@mixin header-gradient {
background: $bg-header;
border-radius: 0 0 48rpx 48rpx;
}

@ -1,34 +1,45 @@
// http.js
import { ref } from 'vue';
// 封装请求拦截器
function requestInterceptor(options) {
const token = uni.getStorageSync("access_token");
// 在请求发送之前做一些处理
// 比如添加请求头、修改请求参数等
options.header = {
'Authorization': 'Bearer ' + sessionStorage.getItem("access_token"), // 假设需要添加 token
'Content-Type': 'application/json' // 设置请求头
'Authorization': token ? 'Bearer ' + token : '',
'Content-Type': 'application/json'
};
return options;
}
// 封装响应拦截器
function responseInterceptor(response) {
// 对响应数据进行处理
// 比如根据响应状态码进行不同的操作
if (response.statusCode === 200) {
// 请求成功
if(response.data.status==false){
const data = response.data;
if (data.status === 'Toke_Error' || data.code === 10001) {
uni.removeStorageSync("access_token");
uni.removeStorageSync("refresh_token");
uni.showModal({
title: '提示',
content: '登录已过期,请重新登录',
showCancel: false,
success: () => {
uni.reLaunch({
url: '/pages/Login'
});
}
});
return Promise.reject(data);
}
if (data.status === false) {
uni.showToast({
title: response.data.msg ,
title: data.msg || data.meg || '操作失败',
icon: 'none'
});
}
return response.data;
return data;
} else {
// 请求失败
uni.showToast({
title: '请求失败,请稍后重试',
icon: 'none'
@ -37,7 +48,6 @@ function responseInterceptor(response) {
}
}
// 发送请求的方法,内部使用拦截器
export function useHttp() {
const isLoading = ref(false);
@ -46,25 +56,25 @@ export function useHttp() {
uni.showLoading({
title: '加载中'
});
// 请求发送之前,先经过请求拦截器处理
let processedOptions = requestInterceptor(options);
let processedOptions = requestInterceptor(options);
return new Promise((resolve, reject) => {
uni.request({
...processedOptions,
success: (res) => {
// 请求成功后,经过响应拦截器处理
let processedResponse = responseInterceptor(res);
isLoading.value = false;
uni.hideLoading();
resolve(processedResponse);
},
fail: (err) => {
// 请求失败
isLoading.value = false;
uni.hideLoading();
uni.showToast({
title: '网络异常,请检查网络',
icon: 'none'
});
reject(err);
}
});

Loading…
Cancel
Save