From 81cfd720961e4f483de70719c6f122dc9295c4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B2=A9=E4=BB=9488?= <> Date: Tue, 7 Apr 2026 09:57:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0h5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/API/H5/EntrustController.php | 2 +- h5/App.vue | 156 ++- h5/api/index.js | 8 +- h5/config/index.js | 18 + h5/pages.json | 28 +- h5/pages/CheckItemMainList.vue | 1000 ++++++++++++----- h5/pages/Login.vue | 318 +++++- h5/pages/PlanList.vue | 660 ++++++++--- h5/pages/index/index.vue | 37 +- h5/static/styles/theme.scss | 86 ++ h5/tools/http.js | 140 +-- 11 files changed, 1849 insertions(+), 604 deletions(-) create mode 100644 h5/config/index.js create mode 100644 h5/static/styles/theme.scss diff --git a/Laravel/app/Http/Controllers/API/H5/EntrustController.php b/Laravel/app/Http/Controllers/API/H5/EntrustController.php index 0f0acd3..da56e65 100644 --- a/Laravel/app/Http/Controllers/API/H5/EntrustController.php +++ b/Laravel/app/Http/Controllers/API/H5/EntrustController.php @@ -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') diff --git a/h5/App.vue b/h5/App.vue index ee288b1..38a3db1 100644 --- a/h5/App.vue +++ b/h5/App.vue @@ -1,7 +1,6 @@ diff --git a/h5/api/index.js b/h5/api/index.js index 07b8491..a8f6f91 100644 --- a/h5/api/index.js +++ b/h5/api/index.js @@ -1,13 +1,15 @@ 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 BaseUrl=Url+'/api/' + + let Url = getBaseUrl(); + let BaseUrl = Url + '/api/' export const BaseFileUrl=()=>{ return Url; diff --git a/h5/config/index.js b/h5/config/index.js new file mode 100644 index 0000000..da4cd4f --- /dev/null +++ b/h5/config/index.js @@ -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 +} \ No newline at end of file diff --git a/h5/pages.json b/h5/pages.json index d5fce23..51005b6 100644 --- a/h5/pages.json +++ b/h5/pages.json @@ -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" + "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" } } } diff --git a/h5/pages/CheckItemMainList.vue b/h5/pages/CheckItemMainList.vue index b498cd7..4423620 100644 --- a/h5/pages/CheckItemMainList.vue +++ b/h5/pages/CheckItemMainList.vue @@ -1,347 +1,757 @@ - + \ No newline at end of file diff --git a/h5/pages/Login.vue b/h5/pages/Login.vue index 93f32e8..916ec6d 100644 --- a/h5/pages/Login.vue +++ b/h5/pages/Login.vue @@ -1,40 +1,302 @@ - + + .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; + } + \ No newline at end of file diff --git a/h5/pages/PlanList.vue b/h5/pages/PlanList.vue index f041690..a0ebc78 100644 --- a/h5/pages/PlanList.vue +++ b/h5/pages/PlanList.vue @@ -1,210 +1,516 @@ - \ No newline at end of file diff --git a/h5/pages/index/index.vue b/h5/pages/index/index.vue index 7697316..f32647f 100644 --- a/h5/pages/index/index.vue +++ b/h5/pages/index/index.vue @@ -1,29 +1,40 @@ + \ No newline at end of file diff --git a/h5/static/styles/theme.scss b/h5/static/styles/theme.scss new file mode 100644 index 0000000..5a5166b --- /dev/null +++ b/h5/static/styles/theme.scss @@ -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; +} \ No newline at end of file diff --git a/h5/tools/http.js b/h5/tools/http.js index e709d10..5244ceb 100644 --- a/h5/tools/http.js +++ b/h5/tools/http.js @@ -1,78 +1,88 @@ -// http.js - import { ref } from 'vue'; -// 封装请求拦截器 function requestInterceptor(options) { - - // 在请求发送之前做一些处理 - // 比如添加请求头、修改请求参数等 - options.header = { - 'Authorization': 'Bearer ' + sessionStorage.getItem("access_token"), // 假设需要添加 token - 'Content-Type': 'application/json' // 设置请求头 - }; - return options; + const token = uni.getStorageSync("access_token"); + + options.header = { + 'Authorization': token ? 'Bearer ' + token : '', + 'Content-Type': 'application/json' + }; + return options; } -// 封装响应拦截器 function responseInterceptor(response) { - // 对响应数据进行处理 - // 比如根据响应状态码进行不同的操作 - if (response.statusCode === 200) { - // 请求成功 - if(response.data.status==false){ - uni.showToast({ - title: response.data.msg , - icon: 'none' - }); - } - return response.data; - } else { - // 请求失败 - uni.showToast({ - title: '请求失败,请稍后重试', - icon: 'none' - }); - return Promise.reject(response.data); - } + if (response.statusCode === 200) { + 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: data.msg || data.meg || '操作失败', + icon: 'none' + }); + } + + return data; + } else { + uni.showToast({ + title: '请求失败,请稍后重试', + icon: 'none' + }); + return Promise.reject(response.data); + } } -// 发送请求的方法,内部使用拦截器 export function useHttp() { - const isLoading = ref(false); + const isLoading = ref(false); - function sendRequest(options) { - isLoading.value = true; - uni.showLoading({ - title: '加载中' - }); - // 请求发送之前,先经过请求拦截器处理 - let processedOptions = requestInterceptor(options); + function sendRequest(options) { + isLoading.value = true; + uni.showLoading({ + title: '加载中' + }); + + 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(); - reject(err); - } - }); - }); - } + 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); + } + }); + }); + } - return { - isLoading, - sendRequest - }; + return { + isLoading, + sendRequest + }; } \ No newline at end of file