From 4648a3bee638e9a99d2d80b66f8833b261a2db91 Mon Sep 17 00:00:00 2001 From: wlzboy <66905212@qq.com> Date: 星期四, 25 九月 2025 22:39:24 +0800 Subject: [PATCH] feat:设计 app ui --- app/plugins/modal.js | 20 app/static/icons/tasks.svg | 6 app/static/icons/create.svg | 4 app/static/icons/home.svg | 3 app/pages.json | 63 app/static/images/qrcode.png | 222 ++ app/static/icons/create.png | 0 app/README.md | 80 app/store/modules/user.js | 16 app/pages/mine/index.vue | 170 + app/api/wechat.js | 36 app/static/images/tabbar/add_.png | 5 app/static/images/wechat.png | 5 app/static/images/tabbar/message_.png | 4 app/pages/bind-vehicle.vue | 214 ++ app/pages/task/settlement.vue | 747 ++++++++ app/pages/task/detail.vue | 600 ++++++ app/pages/task/create.vue | 856 +++++++++ app/static/icons/messages.svg | 5 app/static/icons/profile.svg | 4 app/.gitignore | 2 app/static/icons/profile-active.svg | 4 app/pages/index.vue | 605 ++++++ app/static/icons/messages.png | 0 app/static/icons/messages-active.png | 0 app/static/icons/profile-active.png | 0 app/static/icons/home-active.png | 0 app/pages/message/index.vue | 239 ++ app/pages/mine/info/index.vue | 56 app/static/icons/messages-active.svg | 5 app/static/icons/profile.png | 0 app/pages/task/index.vue | 798 ++++++++ app/static/icons/home-active.svg | 3 app/static/images/tabbar/message.png | 4 app/static/images/tabbar/task.png | 4 app/static/scss/global.scss | 33 app/static/images/tabbar/add.png | 5 app/pages/login.vue | 178 + app/static/icons/tasks-active.svg | 6 app/static/icons/create-active.png | 0 app/static/icons/create-active.svg | 4 app/static/icons/README.md | 23 app/static/icons/tasks.png | 0 app/pages/login/wechat.vue | 258 ++ app/static/icons/home.png | 0 app/static/icons/tasks-active.png | 0 app/static/images/tabbar/task_.png | 4 47 files changed, 5,169 insertions(+), 122 deletions(-) diff --git a/app/.gitignore b/app/.gitignore index 59c9154..40acdf6 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -3,7 +3,7 @@ /unpackage/* /node_modules/* - +/uni_modules/* ###################################################################### # Development Tools diff --git a/app/README.md b/app/README.md index d396dc7..48faa2f 100644 --- a/app/README.md +++ b/app/README.md @@ -1,51 +1,47 @@ -<p align="center"> - <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-43e3941654fa3054c9684bf53d1b1d356a1.png"> -</p> -<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v1.1.0</h1> -<h4 align="center">鍩轰簬UniApp寮�鍙戠殑杞婚噺绾хЩ鍔ㄧ妗嗘灦</h4> -<p align="center"> - <a href="https://gitee.com/y_project/RuoYi-App/stargazers"><img src="https://gitee.com/y_project/RuoYi-App/badge/star.svg?theme=dark"></a> - <a href="https://gitee.com/y_project/RuoYi-App"><img src="https://img.shields.io/badge/RuoYi-v1.1.0-brightgreen.svg"></a> - <a href="https://gitee.com/y_project/RuoYi-App/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> -</p> +# 鑻ヤ緷浠诲姟璋冨害绉诲姩搴旂敤 -## 骞冲彴绠�浠� +## 椤圭洰浠嬬粛 +杩欐槸涓�涓熀浜巙ni-app寮�鍙戠殑浠诲姟璋冨害绉诲姩搴旂敤锛屽寘鍚换鍔$鐞嗐�佹秷鎭�氱煡銆佸井淇$櫥褰曠瓑鍔熻兘銆� -RuoYi App 绉诲姩瑙e喅鏂规锛岄噰鐢╱niapp妗嗘灦锛屼竴浠戒唬鐮佸缁堢閫傞厤锛屽悓鏃舵敮鎸丄PP銆佸皬绋嬪簭銆丠5锛佸疄鐜颁簡涓嶽RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)銆乕RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)瀹岀編瀵规帴鐨勭Щ鍔ㄨВ鍐虫柟妗堬紒鐩墠宸茬粡瀹炵幇鐧诲綍銆佹垜鐨勩�佸伐浣滃彴銆佺紪杈戣祫鏂欍�佸ご鍍忎慨鏀广�佸瘑鐮佷慨鏀广�佸父瑙侀棶棰樸�佸叧浜庢垜浠瓑鍩虹鍔熻兘銆� +## 鍔熻兘妯″潡 +1. **棣栭〉** - 搴旂敤鍏ュ彛鍜屾瑙� +2. **浠诲姟** - 浠诲姟鍒楄〃鏌ョ湅鍜岀鐞� +3. **鍒涘缓浠诲姟** - 鏂板缓浠诲姟 +4. **娑堟伅** - 绯荤粺娑堟伅鍜岄�氱煡 +5. **鎴戠殑** - 涓汉涓績鍜岃缃� -* 閰嶅鍚庣浠g爜浠撳簱鍦板潃[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) 鎴� [RuoYi-Cloud](https://github.com/yangzongzhuan/RuoYi-Cloud) 鐗堟湰銆� -* 搴旂敤妗嗘灦鍩轰簬[uniapp](https://uniapp.dcloud.net.cn/)锛屾敮鎸佸皬绋嬪簭銆丠5銆丄ndroid鍜孖OS銆� -* 鍓嶇缁勪欢閲囩敤[uni-ui](https://github.com/dcloudio/uni-ui)锛屽叏绔吋瀹圭殑楂樻�ц兘UI妗嗘灦銆� -* 闃块噷浜戞姌鎵e満锛歔鐐规垜杩涘叆](http://aly.ruoyi.vip)锛岃吘璁簯绉掓潃鍦猴細[鐐规垜杩涘叆](http://txy.ruoyi.vip) +## 鐧诲綍鍔熻兘 +- 璐﹀彿瀵嗙爜鐧诲綍 +- 寰俊涓�閿櫥褰曪紙鏀寔寰俊灏忕▼搴忥級 +## 杩愯鏂瑰紡 +```bash +# 瀹夎渚濊禆 +npm install -## 鎶�鏈枃妗� +# 杩愯鍒癏5 +npm run dev:h5 -- 瀹樼綉缃戠珯锛歔http://ruoyi.vip](http://ruoyi.vip) -- 鏂囨。鍦板潃锛歔http://doc.ruoyi.vip](http://doc.ruoyi.vip) -- H5椤典綋楠岋細[http://h5.ruoyi.vip](http://h5.ruoyi.vip) -- QQ浜ゆ祦缇わ細 鈶�133713780(婊�)銆佲憽146013835(婊�)銆佲憿189091635 -- 灏忕▼搴忎綋楠� +# 杩愯鍒板井淇″皬绋嬪簭 +npm run dev:mp-weixin -<img src="https://oscimg.oschina.net/oscnet/up-26c76dc90b92acdbd9ac8cd5252f07c8ad9.jpg" alt="灏忕▼搴忔紨绀�"/> - +# 鏋勫缓鐢熶骇鐗堟湰 +npm run build +``` -## 婕旂ず鍥� +## 鐩綍缁撴瀯 +``` +app/ +鈹溾攢鈹� api/ # 鎺ュ彛璇锋眰 +鈹溾攢鈹� components/ # 缁勪欢 +鈹溾攢鈹� pages/ # 椤甸潰 +鈹溾攢鈹� static/ # 闈欐�佽祫婧� +鈹溾攢鈹� store/ # 鐘舵�佺鐞� +鈹溾攢鈹� utils/ # 宸ュ叿鍑芥暟 +鈹斺攢鈹� ... +``` -<table> - <tr> - <td><img src="https://oscimg.oschina.net/oscnet/up-21f6f842fdc94540469b4eb43fdadbaf7f8.png"/></td> - <td><img src="https://oscimg.oschina.net/oscnet/up-a6f23cf9a371a30165e135eff6d9ae89a9d.png"/></td> - <td><img src="https://oscimg.oschina.net/oscnet/up-ff5f62016bf6624c1ff27eee57499dccd44.png"/></td> - </tr> - <tr> - <td><img src="https://oscimg.oschina.net/oscnet/up-b9a582fdb26ec69d407fabd044d2c8494df.png"/></td> - <td><img src="https://oscimg.oschina.net/oscnet/up-96427ee08fca29d77934cfc8d1b1a637cef.png"/></td> - <td><img src="https://oscimg.oschina.net/oscnet/up-5fdadc582d24cccd7727030d397b63185a3.png"/></td> - </tr> - <tr> - <td><img src="https://oscimg.oschina.net/oscnet/up-0a36797b6bcc50c36d40c3c782665b89efc.png"/></td> - <td><img src="https://oscimg.oschina.net/oscnet/up-d77995cc00687cedd00d5ac7d68a07ea276.png"/></td> - <td><img src="https://oscimg.oschina.net/oscnet/up-fa8f5ab20becf59b4b38c1b92a9989e7109.png"/></td> - </tr> -</table> +## 娉ㄦ剰浜嬮」 +1. 寰俊鐧诲綍鍔熻兘闇�瑕佸湪寰俊寮�鍙戣�呭伐鍏蜂腑娴嬭瘯 +2. 鍚庣鎺ュ彛闇�瑕佹牴鎹疄闄呮儏鍐佃皟鏁� +3. 鍥炬爣璧勬簮宸插寘鍚湪static/icons鐩綍涓� \ No newline at end of file diff --git a/app/api/wechat.js b/app/api/wechat.js new file mode 100644 index 0000000..4f1e3e1 --- /dev/null +++ b/app/api/wechat.js @@ -0,0 +1,36 @@ +import request from '@/utils/request' + +// 寰俊鐧诲綍 +export function wechatLogin(data) { + return request({ + url: '/wechat/login', + method: 'post', + data: data + }) +} + +// 鑾峰彇寰俊鐢ㄦ埛淇℃伅 +export function getWechatUserInfo(openid) { + return request({ + url: '/wechat/user/' + openid, + method: 'get' + }) +} + +// 缁戝畾寰俊璐﹀彿 +export function bindWechat(data) { + return request({ + url: '/wechat/bind', + method: 'post', + data: data + }) +} + +// 瑙g粦寰俊璐﹀彿 +export function unbindWechat(data) { + return request({ + url: '/wechat/unbind', + method: 'post', + data: data + }) +} \ No newline at end of file diff --git a/app/pages.json b/app/pages.json index 333251c..ee9557c 100644 --- a/app/pages.json +++ b/app/pages.json @@ -5,6 +5,11 @@ "navigationBarTitleText": "鐧诲綍" } }, { + "path": "pages/login/wechat", + "style": { + "navigationBarTitleText": "寰俊鐧诲綍" + } + }, { "path": "pages/register", "style": { "navigationBarTitleText": "娉ㄥ唽" @@ -14,6 +19,11 @@ "style": { "navigationBarTitleText": "鑻ヤ緷绉诲姩绔鏋�", "navigationStyle": "custom" + } + }, { + "path": "pages/bind-vehicle", + "style": { + "navigationBarTitleText": "缁戝畾杞﹁締" } }, { "path": "pages/work/index", @@ -70,6 +80,31 @@ "style": { "navigationBarTitleText": "娴忚鏂囨湰" } + }, { + "path": "pages/task/index", + "style": { + "navigationBarTitleText": "浠诲姟鍒楄〃" + } + }, { + "path": "pages/task/create", + "style": { + "navigationBarTitleText": "鍒涘缓浠诲姟" + } + }, { + "path": "pages/task/detail", + "style": { + "navigationBarTitleText": "浠诲姟璇︽儏" + } + }, { + "path": "pages/task/settlement", + "style": { + "navigationBarTitleText": "浠诲姟缁撶畻" + } + }, { + "path": "pages/message/index", + "style": { + "navigationBarTitleText": "娑堟伅涓績" + } }], "tabBar": { "color": "#000000", @@ -78,18 +113,28 @@ "backgroundColor": "#ffffff", "list": [{ "pagePath": "pages/index", - "iconPath": "static/images/tabbar/home.png", - "selectedIconPath": "static/images/tabbar/home_.png", + "iconPath": "static/icons/home.png", + "selectedIconPath": "static/icons/home-active.png", "text": "棣栭〉" }, { - "pagePath": "pages/work/index", - "iconPath": "static/images/tabbar/work.png", - "selectedIconPath": "static/images/tabbar/work_.png", - "text": "宸ヤ綔鍙�" + "pagePath": "pages/task/index", + "iconPath": "static/icons/tasks.png", + "selectedIconPath": "static/icons/tasks-active.png", + "text": "浠诲姟" + }, { + "pagePath": "pages/task/create", + "iconPath": "static/icons/create.png", + "selectedIconPath": "static/icons/create-active.png", + "text": "鍒涘缓浠诲姟" + }, { + "pagePath": "pages/message/index", + "iconPath": "static/icons/messages.png", + "selectedIconPath": "static/icons/messages-active.png", + "text": "娑堟伅" }, { "pagePath": "pages/mine/index", - "iconPath": "static/images/tabbar/mine.png", - "selectedIconPath": "static/images/tabbar/mine_.png", + "iconPath": "static/icons/profile.png", + "selectedIconPath": "static/icons/profile-active.png", "text": "鎴戠殑" } ] @@ -99,4 +144,4 @@ "navigationBarTitleText": "RuoYi", "navigationBarBackgroundColor": "#FFFFFF" } -} +} \ No newline at end of file diff --git a/app/pages/bind-vehicle.vue b/app/pages/bind-vehicle.vue new file mode 100644 index 0000000..4897419 --- /dev/null +++ b/app/pages/bind-vehicle.vue @@ -0,0 +1,214 @@ +<template> + <view class="bind-vehicle-container"> + <view class="header"> + <text class="title">缁戝畾杞﹁締</text> + </view> + + <!-- 鎵爜缁戝畾 --> + <view class="scan-section"> + <view class="section-title">鎵竴鎵粦瀹�</view> + <view class="scan-content"> + <view class="scan-icon" @click="scanQRCode"> + <uni-icons type="scan" size="40" color="#007AFF"></uni-icons> + <text class="scan-text">鐐瑰嚮鎵爜缁戝畾杞﹁締</text> + </view> + </view> + </view> + + <!-- 涓嬫媺閫夋嫨缁戝畾 --> + <view class="form-section"> + <view class="section-title">閫夋嫨杞︾墝鍙风粦瀹�</view> + <view class="form-item"> + <view class="form-label">杞︾墝鍙�</view> + <picker mode="selector" :range="vehiclePlates" @change="onVehiclePlateChange"> + <view class="form-input picker-input"> + {{ selectedVehiclePlate || '璇烽�夋嫨杞︾墝鍙�' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-actions"> + <button class="submit-btn" @click="bindVehicle" :disabled="!selectedVehiclePlate">纭缁戝畾</button> + <button class="cancel-btn" @click="goBack">鍙栨秷</button> + </view> + </view> + </view> +</template> + +<script> + export default { + data() { + return { + selectedVehiclePlate: '', + // 妯℃嫙杞﹁締鍒楄〃鏁版嵁 + vehiclePlates: ['绮12345', '绮67890', '绮11111', '绮22222', '绮33333'] + } + }, + methods: { + // 鎵爜缁戝畾杞﹁締 + scanQRCode() { + // #ifdef H5 + this.$modal.showToast('H5鐜鏆備笉鏀寔鎵爜鍔熻兘') + // #endif + + // #ifndef H5 + uni.scanCode({ + success: (res) => { + console.log('鎵爜缁撴灉锛�', res) + // 瑙f瀽鎵爜缁撴灉锛岃繖閲屽亣璁炬壂鐮佺粨鏋滄槸杞︾墝鍙� + this.selectedVehiclePlate = res.result + this.$modal.showToast('鎵爜鎴愬姛锛屾鍦ㄧ粦瀹氳溅杈�...') + // 鎵爜鎴愬姛鍚庤嚜鍔ㄧ粦瀹� + this.bindVehicle() + }, + fail: (err) => { + console.log('鎵爜澶辫触锛�', err) + this.$modal.showToast('鎵爜澶辫触锛岃閲嶈瘯') + } + }) + // #endif + }, + + // 杞︾墝鍙烽�夋嫨 + onVehiclePlateChange(e) { + this.selectedVehiclePlate = this.vehiclePlates[e.detail.value] + }, + + // 缁戝畾杞﹁締 + bindVehicle() { + if (!this.selectedVehiclePlate) { + this.$modal.showToast('璇烽�夋嫨杞︾墝鍙�') + return + } + + // 杩欓噷鍙互璋冪敤API杩涜杞﹁締缁戝畾 + this.$modal.confirm('纭缁戝畾杞﹁締 ' + this.selectedVehiclePlate + ' 鍚楋紵').then(() => { + this.$modal.showToast('杞﹁締缁戝畾鎴愬姛') + // 杩斿洖涓婁竴椤� + this.$tab.navigateBack() + }).catch(() => { + // 鐢ㄦ埛鍙栨秷鎿嶄綔 + }) + }, + + goBack() { + this.$tab.navigateBack() + } + } + } +</script> + +<style lang="scss"> + .bind-vehicle-container { + padding: 20rpx; + background-color: #f5f5f5; + min-height: 100vh; + } + + .header { + text-align: center; + padding: 40rpx 0; + + .title { + font-size: 40rpx; + font-weight: bold; + color: #333; + } + } + + .section-title { + font-size: 32rpx; + font-weight: bold; + margin: 30rpx 0 20rpx 0; + color: #333; + } + + .scan-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .scan-content { + text-align: center; + padding: 40rpx 0; + + .scan-icon { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + .scan-text { + margin-top: 20rpx; + font-size: 28rpx; + color: #007AFF; + } + } + } + } + + .form-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .form-item { + margin-bottom: 40rpx; + + &:last-child { + margin-bottom: 0; + } + + .form-label { + font-size: 28rpx; + margin-bottom: 15rpx; + color: #333; + } + + .form-input { + height: 70rpx; + padding: 0 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + + &.picker-input { + display: flex; + align-items: center; + justify-content: space-between; + } + } + } + + .form-actions { + display: flex; + margin-top: 50rpx; + + .submit-btn, .cancel-btn { + flex: 1; + height: 80rpx; + border-radius: 10rpx; + font-size: 32rpx; + margin: 0 10rpx; + } + + .submit-btn { + background-color: #007AFF; + color: white; + + &[disabled] { + background-color: #cccccc; + } + } + + .cancel-btn { + background-color: #f0f0f0; + color: #333; + } + } + } +</style> \ No newline at end of file diff --git a/app/pages/index.vue b/app/pages/index.vue index 4646807..5539ffa 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -1,43 +1,598 @@ <template> - <view class="content"> - <image class="logo" src="@/static/logo.png"></image> - <view class="text-area"> - <text class="title">Hello RuoYi</text> + <view class="home-container"> + <!-- 椤堕儴鐢ㄦ埛淇℃伅鍖哄煙 --> + <view class="user-info-section"> + <view class="user-info-content"> + <view class="user-details"> + <view class="user-name">{{ userName || '鏈櫥褰�' }}</view> + <view class="vehicle-info"> + <text v-if="boundVehicle">鍏宠仈杞︾墝鍙凤細{{ boundVehicle }}</text> + <text v-else>鏈粦瀹氳溅鐗屽彿</text> + </view> + </view> + <button + class="bind-vehicle-btn" + @click="goToBindVehicle" + > + {{ boundVehicle ? '鏇存崲杞﹁締' : '缁戝畾杞﹁締' }} + </button> + </view> </view> + + <!-- 娑堟伅鍏ュ彛 --> + <view class="message-entry" @click="goToMessages"> + <view class="message-icon"> + <uni-icons type="chat" size="24" color="#007AFF"></uni-icons> + </view> + <view class="message-text">娑堟伅涓績</view> + <view class="unread-dot" v-if="unreadMessageCount > 0">{{ unreadMessageCount }}</view> + <view class="arrow"> + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <!-- 姝e湪杩愯鐨勪换鍔℃爣棰� --> + <view class="running-tasks-header"> + <text class="header-title">姝e湪杩愯鐨勪换鍔�</text> + </view> + + <!-- 姝e湪杩愯鐨勪换鍔″垪琛� --> + <scroll-view class="running-tasks-section" scroll-y="true"> + <view class="task-list"> + <view class="task-item" v-for="task in runningTasks" :key="task.id"> + <view class="task-main" @click="viewTaskDetail(task)"> + <view class="task-title">{{ getTaskTypeText(task.type) }} - {{ task.vehicle }}</view> + <view class="task-info"> + <view class="info-row"> + <view class="info-item"> + <view class="label">浠诲姟缂栧彿:</view> + <view class="value">{{ task.taskNo }}</view> + </view> + <view class="info-item"> + <view class="label">浠诲姟鐘舵��:</view> + <view class="value">{{ getStatusText(task.status) }}</view> + </view> + </view> + <view class="info-row"> + <view class="info-item"> + <view class="label">鍑哄彂鍦�:</view> + <view class="value">{{ task.startLocation }}</view> + </view> + <view class="info-item"> + <view class="label">鐩殑鍦�:</view> + <view class="value">{{ task.endLocation }}</view> + </view> + </view> + <view class="info-row"> + <view class="info-item"> + <view class="label">鍑哄彂鏃堕棿:</view> + <view class="value">{{ task.startTime }}</view> + </view> + <view class="info-item"> + <view class="label">鎵ц浜哄憳:</view> + <view class="value">{{ task.assignee }}</view> + </view> + </view> + </view> + </view> + + <!-- 鎿嶄綔鎸夐挳 --> + <view class="task-actions"> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'depart') }" + @click="handleTaskAction(task, 'depart')" + v-if="task.status !== 'completed'" + > + 鍑哄彂 + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'arrive') }" + @click="handleTaskAction(task, 'arrive')" + v-if="task.status !== 'completed'" + > + 宸插埌杈� + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'return') }" + @click="handleTaskAction(task, 'return')" + v-if="task.status !== 'completed'" + > + 杩旂▼ + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'settle') }" + @click="handleTaskAction(task, 'settle')" + v-if="task.status !== 'completed'" + > + 缁撶畻 + </button> + <button + class="action-btn primary" + :class="{ disabled: isActionDisabled(task, 'complete') }" + @click="handleTaskAction(task, 'complete')" + v-if="task.status !== 'completed'" + > + 宸插畬鎴� + </button> + </view> + </view> + + <view class="no-data" v-if="runningTasks.length === 0"> + <uni-icons type="info" size="40" color="#ccc"></uni-icons> + <text>鏆傛棤姝e湪杩愯鐨勪换鍔�</text> + </view> + </view> + </scroll-view> </view> </template> <script> + import { mapState } from 'vuex' + export default { - onLoad: function() { + data() { + return { + // 妯℃嫙鐢ㄦ埛缁戝畾鐨勮溅杈嗕俊鎭� + boundVehicle: '绮12345', // 妯℃嫙宸茬粦瀹氳溅杈� + + // 妯℃嫙娑堟伅鏁版嵁 + messages: [ + { + id: 1, + type: 'create', // 鍒涘缓鎴愬姛 + content: 'TD 1011 骞垮窞澶╂渤->骞垮窞涓滅珯锛屾椂闂达細13锛�20 浠诲姟鍒涘缓鎴愬姛', + time: '2023-05-15 13:20', + read: false, + taskId: 1 + }, + { + id: 2, + type: 'push', // 浠诲姟鎺ㄩ�� + content: 'TD1021 骞垮窞澶╂渤->骞垮窞涓滅珯锛屾椂闂达細13锛�20 鍑哄彂锛岃鍙婃椂澶勭悊', + time: '2023-05-15 13:25', + read: false, + taskId: 2 + }, + { + id: 3, + type: 'status', // 浠诲姟鐘舵�佸彉鏇� + content: 'TD1021 骞垮窞澶╂渤->骞垮窞涓滅珯锛屾椂闂达細13锛�20锛屼换鍔℃鍦ㄨ浆杩愪腑', + time: '2023-05-15 14:30', + read: true, + taskId: 2 + }, + { + id: 4, + type: 'create', // 鍒涘缓鎴愬姛 + content: 'TD 1022 娣卞湷鍗楀北->娣卞湷绂忕敯锛屾椂闂达細15锛�10 浠诲姟鍒涘缓鎴愬姛', + time: '2023-05-15 15:10', + read: false, + taskId: 3 + }, + { + id: 5, + type: 'push', // 浠诲姟鎺ㄩ�� + content: 'TD1023 娣卞湷鍗楀北->娣卞湷绂忕敯锛屾椂闂达細16锛�00 鍑哄彂锛岃鍙婃椂澶勭悊', + time: '2023-05-15 16:00', + read: true, + taskId: 4 + } + ], + + // 妯℃嫙姝e湪杩愯鐨勪换鍔″垪琛� + taskList: [ + { + id: 1, + title: '绱ф�ョ淮淇换鍔�', + type: 'maintenance', // 缁翠慨淇濆吇 + startLocation: '骞垮窞甯傚ぉ娌冲尯XX璺�123鍙�', + endLocation: '骞垮窞甯傜櫧浜戝尯YY璺�456鍙�', + startTime: '2023-05-15 15:00', + assignee: '寮犱笁', + status: 'pending', + vehicle: '绮12345', + taskNo: 'RW20230515001' + }, + { + id: 2, + title: '瀹氭湡淇濆吇浠诲姟', + type: 'maintenance', // 缁翠慨淇濆吇 + startLocation: '娣卞湷甯傚崡灞卞尯XX璺�789鍙�', + endLocation: '娣卞湷甯傜鐢板尯YY璺�999鍙�', + startTime: '2023-05-14 10:00', + assignee: '鏉庡洓', + status: 'processing', + vehicle: '绮67890', + taskNo: 'RW20230514002' + }, + { + id: 5, + title: '鎬ユ晳杞繍浠诲姟', + type: 'emergency', // 鎬ユ晳杞繍 + startLocation: '骞垮窞甯傝秺绉�鍖哄尰闄㈣矾1鍙�', + endLocation: '骞垮窞甯傛捣鐝犲尯鍖婚櫌璺�2鍙�', + startTime: '2023-05-16 14:00', + assignee: '寮犲尰鐢�,鏉庢姢澹�', + status: 'pending', + vehicle: '绮33333', + taskNo: 'RW20230516005' + }, + { + id: 6, + title: '绂忕杞︿换鍔�', + type: 'welfare', // 绂忕杞� + startLocation: '骞垮窞甯傝崝婀惧尯绀惧尯璺�10鍙�', + endLocation: '骞垮窞甯傚ぉ娌冲尯鍏昏�侀櫌璺�20鍙�', + startTime: '2023-05-17 08:00', + assignee: '鐜嬪徃鏈�', + status: 'processing', + vehicle: '绮44444', + taskNo: 'RW20230517006' + } + ] + } + }, + computed: { + ...mapState({ + userName: state => state.user.name + }), + + // 姝e湪杩愯鐨勪换鍔★紙寰呭鐞嗗拰澶勭悊涓殑浠诲姟锛� + runningTasks() { + return this.taskList.filter(task => + task.status === 'pending' || task.status === 'processing' + ); + }, + + // 鏈娑堟伅鏁伴噺 + unreadMessageCount() { + return this.messages.filter(message => !message.read).length; + } + }, + methods: { + // 璺宠浆鍒扮粦瀹氳溅杈嗛〉闈� + goToBindVehicle() { + // 璺宠浆鍒扮粦瀹氳溅杈嗙殑椤甸潰 + this.$tab.navigateTo('/pages/bind-vehicle'); + }, + + // 璺宠浆鍒版秷鎭〉闈� + goToMessages() { + this.$tab.switchTab('/pages/message/index'); + }, + + // 鏌ョ湅浠诲姟璇︽儏 + viewTaskDetail(task) { + // 璺宠浆鍒颁换鍔¤鎯呴〉闈� + this.$tab.navigateTo(`/pages/task/detail?id=${task.id}`); + }, + + // 鍒ゆ柇鎿嶄綔鎸夐挳鏄惁绂佺敤 + isActionDisabled(task, action) { + // 鏍规嵁浠诲姟鐘舵�佸拰鎿嶄綔绫诲瀷鍒ゆ柇鏄惁绂佺敤 + switch (action) { + case 'depart': + return task.status !== 'pending'; + case 'arrive': + return task.status !== 'processing'; + case 'return': + return task.status !== 'processing'; + case 'settle': + return task.status !== 'processing'; + case 'complete': + return task.status !== 'processing'; + default: + return false; + } + }, + + // 澶勭悊浠诲姟鎿嶄綔 + handleTaskAction(task, action) { + if (this.isActionDisabled(task, action)) { + return; + } + + switch (action) { + case 'depart': + // 鍑哄彂鎿嶄綔锛屾牴鎹换鍔$被鍨嬫樉绀轰笉鍚岀殑纭淇℃伅 + let departMessage = '纭畾瑕佹爣璁颁负宸插嚭鍙戝悧锛�'; + if (task.type !== 'maintenance' && task.type !== 'refuel' && task.type !== 'inspection') { + departMessage = '鍙戝嚭鍘荤洰鐨勫湴,纭锛�'; + } + this.$modal.confirm(departMessage).then(() => { + task.status = 'processing'; + this.$modal.showToast('宸插嚭鍙�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'arrive': + // 宸插埌杈炬搷浣� + this.$modal.confirm('宸茬粡鍒拌揪鐩殑鍦帮紝纭锛�').then(() => { + this.$modal.showToast('宸插埌杈�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'return': + // 杩旂▼鎿嶄綔 + this.$modal.confirm('鐜板湪宸茬粡杩旂▼涓紝纭锛�').then(() => { + this.$modal.showToast('杩旂▼涓�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'settle': + // 缁撶畻鎿嶄綔锛岃烦杞埌缁撶畻椤甸潰 + this.$tab.navigateTo(`/pages/task/settlement?id=${task.id}`); + break; + case 'complete': + // 宸插畬鎴愭搷浣� + this.$modal.confirm('浠诲姟鏄惁宸茬粡鍏ㄩ儴瀹屾垚锛岀‘璁わ紵').then(() => { + task.status = 'completed'; + this.$modal.showToast('浠诲姟宸插畬鎴�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + } + }, + + getStatusText(status) { + const statusMap = { + 'pending': '寰呭鐞�', + 'processing': '澶勭悊涓�', + 'completed': '宸插畬鎴�' + } + return statusMap[status] || '鏈煡' + }, + + getTaskTypeText(type) { + const typeMap = { + 'maintenance': '缁翠慨淇濆吇', + 'refuel': '鍔犳补', + 'inspection': '宸℃', + 'emergency': '鎬ユ晳杞繍', + 'welfare': '绂忕杞�' + } + return typeMap[type] || '鏈煡绫诲瀷' + } } } </script> -<style> - .content { +<style lang="scss"> + .home-container { + padding: 20rpx; + background-color: #f5f5f5; + height: 100vh; display: flex; flex-direction: column; - align-items: center; - justify-content: center; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } } - - .logo { - height: 200rpx; - width: 200rpx; - margin-top: 200rpx; - margin-left: auto; - margin-right: auto; - margin-bottom: 50rpx; + + // 鐢ㄦ埛淇℃伅鍖哄煙 + .user-info-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + flex-shrink: 0; // 闃叉鏀剁缉 + + .user-info-content { + display: flex; + justify-content: space-between; + align-items: center; + + .user-details { + .user-name { + font-size: 36rpx; + font-weight: bold; + margin-bottom: 10rpx; + color: #333; + } + + .vehicle-info { + font-size: 28rpx; + color: #666; + } + } + + .bind-vehicle-btn { + background-color: #007AFF; + color: white; + border-radius: 10rpx; + padding: 15rpx 30rpx; + font-size: 28rpx; + } + } } - - .text-area { + + // 娑堟伅鍏ュ彛 + .message-entry { display: flex; - justify-content: center; + align-items: center; + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + position: relative; + + .message-icon { + margin-right: 20rpx; + } + + .message-text { + flex: 1; + font-size: 32rpx; + color: #333; + } + + .unread-dot { + position: absolute; + top: 15rpx; + right: 60rpx; + background-color: #ff4d4f; + color: white; + border-radius: 50%; + width: 32rpx; + height: 32rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 20rpx; + } + + .arrow { + margin-left: 20rpx; + } } - - .title { - font-size: 36rpx; - color: #8f8f94; + + // 姝e湪杩愯鐨勪换鍔℃爣棰� + .running-tasks-header { + margin-bottom: 20rpx; + flex-shrink: 0; // 闃叉鏀剁缉 + + .header-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + } } -</style> + + // 姝e湪杩愯鐨勪换鍔″垪琛� + .running-tasks-section { + flex: 1; + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + + .task-list { + .task-item { + background-color: #fafafa; + border-radius: 15rpx; + margin-bottom: 30rpx; + overflow: hidden; + + .task-main { + padding: 30rpx; + border-bottom: 1rpx solid #f0f0f0; + + .task-title { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 20rpx; + } + + .task-info { + .info-row { + display: flex; + margin-bottom: 15rpx; + + &:last-child { + margin-bottom: 0; + } + + .info-item { + flex: 1; + display: flex; + + .label { + font-size: 26rpx; + color: #666; + margin-right: 10rpx; + white-space: nowrap; + } + + .value { + font-size: 26rpx; + flex: 1; + word-break: break-all; + } + } + } + } + } + + .task-actions { + display: flex; + padding: 20rpx; + + .action-btn { + flex: 1; + height: 70rpx; + border-radius: 10rpx; + font-size: 26rpx; + margin: 0 5rpx; + background-color: #f0f0f0; + color: #333; + + &.primary { + background-color: #007AFF; + color: white; + } + + &.disabled { + opacity: 0.5; + } + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + } + } + } + + .no-data { + text-align: center; + padding: 100rpx 0; + color: #999; + + text { + display: block; + margin-top: 20rpx; + } + } + } + } +</style> \ No newline at end of file diff --git a/app/pages/login.vue b/app/pages/login.vue index 7f0e8c8..f440b1e 100644 --- a/app/pages/login.vue +++ b/app/pages/login.vue @@ -1,5 +1,5 @@ <template> - <view class="normal-login-container"> + <scroll-view class="normal-login-container" scroll-y="true"> <view class="logo-content align-center justify-center flex"> <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix"> </image> @@ -14,15 +14,21 @@ <view class="iconfont icon-password icon"></view> <input v-model="loginForm.password" type="password" class="input" placeholder="璇疯緭鍏ュ瘑鐮�" maxlength="20" /> </view> - <view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled"> + <view class="input-item flex align-center captcha-container" v-if="captchaEnabled"> <view class="iconfont icon-code icon"></view> <input v-model="loginForm.code" type="number" class="input" placeholder="璇疯緭鍏ラ獙璇佺爜" maxlength="4" /> <view class="login-code"> - <image :src="codeUrl" @click="getCode" class="login-code-img"></image> + <image :src="codeUrl" @click="getCode" class="login-code-img" mode="aspectFit"></image> </view> </view> <view class="action-btn"> <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">鐧诲綍</button> + </view> + <view class="wechat-login" @click="handleWechatLogin"> + <view class="wechat-btn"> + <image class="wechat-icon" src="/static/icons/profile.png"></image> + <text class="wechat-text">寰俊涓�閿櫥褰�</text> + </view> </view> <view class="reg text-center" v-if="register"> <text class="text-grey1">娌℃湁璐﹀彿锛�</text> @@ -34,8 +40,7 @@ <text @click="handlePrivacy" class="text-blue">銆婇殣绉佸崗璁��</text> </view> </view> - - </view> + </scroll-view> </template> <script> @@ -98,6 +103,40 @@ this.pwdLogin() } }, + // 寰俊鐧诲綍鏂规硶 + async handleWechatLogin() { + // #ifdef MP-WEIXIN + // 寰俊灏忕▼搴忕櫥褰� + uni.login({ + provider: 'weixin', + success: (loginRes) => { + console.log('寰俊鐧诲綍鎴愬姛', loginRes); + // 鑾峰彇鐢ㄦ埛淇℃伅 + uni.getUserInfo({ + provider: 'weixin', + success: (infoRes) => { + console.log('鐢ㄦ埛淇℃伅鑾峰彇鎴愬姛', infoRes); + // 璺宠浆鍒板井淇$櫥褰曠‘璁ら〉闈� + this.$tab.navigateTo(`/pages/login/wechat?userInfo=${encodeURIComponent(JSON.stringify(infoRes.userInfo))}`); + }, + fail: (error) => { + console.error('鑾峰彇鐢ㄦ埛淇℃伅澶辫触', error); + this.$modal.msgError("鑾峰彇寰俊鐢ㄦ埛淇℃伅澶辫触"); + } + }); + }, + fail: (error) => { + console.error('寰俊鐧诲綍澶辫触', error); + this.$modal.msgError("寰俊鐧诲綍澶辫触"); + } + }); + // #endif + + // #ifndef MP-WEIXIN + // H5鎴栧叾浠栧钩鍙版彁绀� + this.$modal.msgError("璇峰湪寰俊瀹㈡埛绔腑浣跨敤寰俊鐧诲綍鍔熻兘"); + // #endif + }, // 瀵嗙爜鐧诲綍 async pwdLogin() { this.$store.dispatch('Login', this.loginForm).then(() => { @@ -127,6 +166,24 @@ .normal-login-container { width: 100%; + min-height: 100vh; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } .logo-content { width: 100%; @@ -158,45 +215,100 @@ .icon { font-size: 38rpx; margin-left: 10px; - color: #999; } .input { + margin-left: 20rpx; width: 100%; - font-size: 14px; - line-height: 20px; - text-align: left; - padding-left: 15px; + height: 45px; + background: none; + } + } + + .captcha-container { + width: 100%; + margin: 20px auto; + background-color: #f5f6f7; + height: 45px; + border-radius: 20px; + padding-right: 10rpx; + box-sizing: border-box; + + .icon { + font-size: 38rpx; + margin-left: 10px; } + .input { + margin-left: 20rpx; + width: 60%; + height: 45px; + background: none; + } + + .login-code { + width: 30%; + height: 45px; + margin-left: 10rpx; + border-left: 1px solid #e0e0e0; + display: flex; + align-items: center; + justify-content: center; + + .login-code-img { + max-width: 100%; + max-height: 45px; + object-fit: contain; + cursor: pointer; + } + } } - .login-btn { - margin-top: 40px; - height: 45px; + .action-btn { + margin: 40rpx 0; + + .login-btn { + height: 90rpx; + font-size: 32rpx; + } } - - .reg { - margin-top: 15px; + + .wechat-login { + margin: 20rpx 0; + + .wechat-btn { + display: flex; + align-items: center; + justify-content: center; + background-color: #07c160; + height: 90rpx; + border-radius: 20px; + + .wechat-icon { + width: 40rpx; + height: 40rpx; + margin-right: 10rpx; + } + + .wechat-text { + color: white; + font-size: 32rpx; + } + } } - - .xieyi { - color: #333; - margin-top: 20px; - } - - .login-code { - height: 38px; - float: right; - - .login-code-img { - height: 38px; - position: absolute; - margin-left: 10px; - width: 200rpx; + + .reg, .xieyi { + margin: 20rpx 0; + + .text-grey1 { + color: #888; + } + + .text-blue { + margin: 0 10rpx; + color: #007AFF; } } } } - -</style> +</style> \ No newline at end of file diff --git a/app/pages/login/wechat.vue b/app/pages/login/wechat.vue new file mode 100644 index 0000000..c38f8f8 --- /dev/null +++ b/app/pages/login/wechat.vue @@ -0,0 +1,258 @@ +<template> + <view class="wechat-login-container"> + <view class="header"> + <view class="title">寰俊鎺堟潈鐧诲綍</view> + <view class="subtitle">鍗冲皢鐧诲綍鍒拌嫢渚濈鐞嗙郴缁�</view> + </view> + + <view class="user-info-card"> + <view class="avatar-section"> + <image + class="user-avatar" + :src="wechatUserInfo.avatarUrl || '/static/images/profile.jpg'" + mode="aspectFill" + ></image> + </view> + + <view class="info-section"> + <view class="info-item"> + <view class="label">鏄电О</view> + <view class="value">{{ wechatUserInfo.nickName || '鏈煡鐢ㄦ埛' }}</view> + </view> + + <view class="info-item"> + <view class="label">鎬у埆</view> + <view class="value">{{ genderText }}</view> + </view> + + <view class="info-item"> + <view class="label">鍦板尯</view> + <view class="value">{{ wechatUserInfo.country }} {{ wechatUserInfo.province }} {{ wechatUserInfo.city }}</view> + </view> + </view> + </view> + + <view class="agreement-section"> + <label class="checkbox"> + <checkbox :checked="agreed" @click="toggleAgreement" /> + <text class="agreement-text">鎴戝凡闃呰骞跺悓鎰�</text> + <text class="link" @click="handleUserAgrement">銆婄敤鎴峰崗璁��</text> + <text>鍜�</text> + <text class="link" @click="handlePrivacy">銆婇殣绉佸崗璁��</text> + </label> + </view> + + <view class="action-buttons"> + <button + class="confirm-btn" + :class="{ disabled: !agreed }" + :disabled="!agreed" + @click="confirmLogin" + > + 纭鐧诲綍 + </button> + <button class="cancel-btn" @click="cancelLogin">鍙栨秷</button> + </view> + </view> +</template> + +<script> + export default { + data() { + return { + agreed: false, + wechatUserInfo: {}, + globalConfig: getApp().globalData.config + } + }, + onLoad(options) { + // 鎺ユ敹浠庣櫥褰曢〉闈紶閫掔殑寰俊鐢ㄦ埛淇℃伅 + if (options.userInfo) { + this.wechatUserInfo = JSON.parse(decodeURIComponent(options.userInfo)) + console.log('寰俊鐢ㄦ埛淇℃伅:', this.wechatUserInfo) + } + }, + computed: { + genderText() { + const genderMap = { + 0: '鏈煡', + 1: '鐢�', + 2: '濂�' + } + return genderMap[this.wechatUserInfo.gender] || '鏈煡' + } + }, + methods: { + toggleAgreement() { + this.agreed = !this.agreed + }, + // 闅愮鍗忚 + handlePrivacy() { + let site = this.globalConfig.appInfo.agreements[0] + this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`) + }, + // 鐢ㄦ埛鍗忚 + handleUserAgrement() { + let site = this.globalConfig.appInfo.agreements[1] + this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`) + }, + // 纭鐧诲綍 + async confirmLogin() { + if (!this.agreed) { + this.$modal.msgError("璇峰厛鍚屾剰鐢ㄦ埛鍗忚鍜岄殣绉佸崗璁�") + return + } + + this.$modal.loading("鐧诲綍涓�...") + + // 杩欓噷搴旇璋冪敤鍚庣寰俊鐧诲綍鎺ュ彛 + // 绀轰緥浠g爜锛屽疄闄呴渶瑕佹牴鎹悗绔帴鍙h皟鏁� + /* + this.$store.dispatch('WechatLogin', { + openid: this.wechatUserInfo.openId, + userInfo: this.wechatUserInfo + }).then(() => { + this.$modal.closeLoading() + this.loginSuccess() + }).catch(() => { + this.$modal.closeLoading() + this.$modal.msgError("寰俊鐧诲綍澶辫触") + }) + */ + + // 涓存椂婕旂ず鐢� + setTimeout(() => { + this.$modal.closeLoading() + this.$modal.showToast("寰俊鐧诲綍鎴愬姛") + this.$tab.reLaunch('/pages/index') + }, 1000) + }, + // 鍙栨秷鐧诲綍 + cancelLogin() { + this.$modal.confirm('纭畾瑕佸彇娑堢櫥褰曞悧锛�').then(() => { + this.$tab.reLaunch('/pages/login') + }).catch(() => { + // 鍙栨秷鎿嶄綔 + }) + }, + // 鐧诲綍鎴愬姛鍚庯紝澶勭悊鍑芥暟 + loginSuccess(result) { + // 璁剧疆鐢ㄦ埛淇℃伅 + this.$store.dispatch('GetInfo').then(res => { + this.$tab.reLaunch('/pages/index') + }) + } + } + } +</script> + +<style lang="scss"> + .wechat-login-container { + padding: 40rpx; + background-color: #f5f5f5; + min-height: 100vh; + + .header { + text-align: center; + margin-bottom: 60rpx; + + .title { + font-size: 36rpx; + font-weight: bold; + margin-bottom: 20rpx; + } + + .subtitle { + font-size: 28rpx; + color: #666; + } + } + + .user-info-card { + background-color: white; + border-radius: 20rpx; + padding: 40rpx; + margin-bottom: 40rpx; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); + + .avatar-section { + text-align: center; + margin-bottom: 40rpx; + + .user-avatar { + width: 120rpx; + height: 120rpx; + border-radius: 50%; + border: 4rpx solid #f0f0f0; + } + } + + .info-section { + .info-item { + display: flex; + justify-content: space-between; + padding: 20rpx 0; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + border-bottom: none; + } + + .label { + font-size: 28rpx; + color: #666; + } + + .value { + font-size: 28rpx; + font-weight: bold; + } + } + } + } + + .agreement-section { + margin-bottom: 60rpx; + + .checkbox { + display: flex; + align-items: center; + + .agreement-text { + margin: 0 10rpx; + } + + .link { + color: #007AFF; + margin: 0 5rpx; + } + } + } + + .action-buttons { + .confirm-btn { + width: 100%; + height: 80rpx; + background-color: #07c160; + color: white; + border-radius: 10rpx; + font-size: 32rpx; + margin-bottom: 20rpx; + + &.disabled { + background-color: #cccccc; + } + } + + .cancel-btn { + width: 100%; + height: 80rpx; + background-color: white; + color: #333; + border: 1rpx solid #ddd; + border-radius: 10rpx; + font-size: 32rpx; + } + } + } +</style> \ No newline at end of file diff --git a/app/pages/message/index.vue b/app/pages/message/index.vue new file mode 100644 index 0000000..2aaa9e5 --- /dev/null +++ b/app/pages/message/index.vue @@ -0,0 +1,239 @@ +<template> + <view class="message-container"> + <view class="message-header"> + <view class="header-title">娑堟伅涓績</view> + </view> + + <scroll-view class="message-list-scroll" scroll-y="true"> + <view class="message-list"> + <!-- 鏈娑堟伅鍦ㄥ墠 --> + <view + class="message-item" + v-for="message in sortedMessages" + :key="message.id" + @click="viewMessageDetail(message)" + > + <view class="message-main"> + <view class="message-title"> + <text class="title-text">{{ getMessageTypeText(message.type) }}</text> + <view class="unread-dot" v-if="!message.read"></view> + </view> + <view class="message-content">{{ message.content }}</view> + <view class="message-time">{{ message.time }}</view> + </view> + </view> + + <view class="no-data" v-if="sortedMessages.length === 0"> + <uni-icons type="info" size="40" color="#ccc"></uni-icons> + <text>鏆傛棤娑堟伅</text> + </view> + </view> + </scroll-view> + </view> +</template> + +<script> + export default { + data() { + return { + // 娑堟伅鍒楄〃 + messages: [ + { + id: 1, + type: 'create', // 鍒涘缓鎴愬姛 + content: 'TD 1011 骞垮窞澶╂渤->骞垮窞涓滅珯锛屾椂闂达細13锛�20 浠诲姟鍒涘缓鎴愬姛', + time: '2023-05-15 13:20', + read: false, + taskId: 1 + }, + { + id: 2, + type: 'push', // 浠诲姟鎺ㄩ�� + content: 'TD1021 骞垮窞澶╂渤->骞垮窞涓滅珯锛屾椂闂达細13锛�20 鍑哄彂锛岃鍙婃椂澶勭悊', + time: '2023-05-15 13:25', + read: false, + taskId: 2 + }, + { + id: 3, + type: 'status', // 浠诲姟鐘舵�佸彉鏇� + content: 'TD1021 骞垮窞澶╂渤->骞垮窞涓滅珯锛屾椂闂达細13锛�20锛屼换鍔℃鍦ㄨ浆杩愪腑', + time: '2023-05-15 14:30', + read: true, + taskId: 2 + }, + { + id: 4, + type: 'create', // 鍒涘缓鎴愬姛 + content: 'TD 1022 娣卞湷鍗楀北->娣卞湷绂忕敯锛屾椂闂达細15锛�10 浠诲姟鍒涘缓鎴愬姛', + time: '2023-05-15 15:10', + read: false, + taskId: 3 + }, + { + id: 5, + type: 'push', // 浠诲姟鎺ㄩ�� + content: 'TD1023 娣卞湷鍗楀北->娣卞湷绂忕敯锛屾椂闂达細16锛�00 鍑哄彂锛岃鍙婃椂澶勭悊', + time: '2023-05-15 16:00', + read: true, + taskId: 4 + } + ] + } + }, + computed: { + // 鎸夋湭璇�/宸茶鎺掑簭锛屾湭璇荤殑鍦ㄥ墠闈� + sortedMessages() { + return [...this.messages].sort((a, b) => { + if (a.read === b.read) { + // 鐩稿悓鐘舵�佹寜鏃堕棿鍊掑簭 + return new Date(b.time) - new Date(a.time); + } + // 鏈鐨勬帓鍦ㄥ墠闈� + return a.read ? 1 : -1; + }); + } + }, + methods: { + // 鑾峰彇娑堟伅绫诲瀷鏂囨湰 + getMessageTypeText(type) { + const typeMap = { + 'create': '鍒涘缓鎴愬姛', + 'push': '浠诲姟鎺ㄩ��', + 'status': '浠诲姟鐘舵��' + } + return typeMap[type] || '绯荤粺娑堟伅'; + }, + + // 鏌ョ湅娑堟伅璇︽儏锛堣烦杞埌浠诲姟璇︽儏锛� + viewMessageDetail(message) { + // 鏍囪涓哄凡璇� + message.read = true; + + // 璺宠浆鍒颁换鍔¤鎯呴〉闈� + if (message.taskId) { + this.$tab.navigateTo(`/pages/task/detail?id=${message.taskId}`); + } else { + this.$modal.showToast('鏃犳硶鎵惧埌鍏宠仈浠诲姟'); + } + } + } + } +</script> + +<style lang="scss"> + .message-container { + padding: 20rpx; + background-color: #f5f5f5; + height: 100vh; + display: flex; + flex-direction: column; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + } + + .message-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20rpx 0; + flex-shrink: 0; // 闃叉鏀剁缉 + + .header-title { + font-size: 36rpx; + font-weight: bold; + } + } + + .message-list-scroll { + flex: 1; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + } + + .message-list { + .message-item { + background-color: white; + border-radius: 15rpx; + margin-bottom: 20rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .message-main { + .message-title { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20rpx; + + .title-text { + font-size: 32rpx; + font-weight: bold; + color: #333; + } + + .unread-dot { + width: 16rpx; + height: 16rpx; + border-radius: 50%; + background-color: #ff4d4f; + } + } + + .message-content { + font-size: 28rpx; + color: #666; + margin-bottom: 20rpx; + line-height: 1.5; + } + + .message-time { + font-size: 24rpx; + color: #999; + text-align: right; + } + } + } + + .no-data { + text-align: center; + padding: 100rpx 0; + color: #999; + + text { + display: block; + margin-top: 20rpx; + } + } + } +</style> \ No newline at end of file diff --git a/app/pages/mine/index.vue b/app/pages/mine/index.vue index 33c3a6e..e936762 100644 --- a/app/pages/mine/index.vue +++ b/app/pages/mine/index.vue @@ -1,5 +1,5 @@ <template> - <view class="mine-container" :style="{height: `${windowHeight}px`}"> + <view class="mine-container"> <!--椤堕儴涓汉淇℃伅鏍�--> <view class="header-section"> <view class="flex padding justify-between"> @@ -25,7 +25,7 @@ </view> </view> - <view class="content-section"> + <scroll-view class="content-section" scroll-y="true"> <view class="mine-actions grid col-4 text-center"> <view class="action-item" @click="handleJiaoLiuQun"> <view class="iconfont icon-friendfill text-pink icon"></view> @@ -42,6 +42,34 @@ <view class="action-item" @click="handleBuilding"> <view class="iconfont icon-dianzan text-green icon"></view> <text class="text">鐐硅禐鎴戜滑</text> + </view> + </view> + + <!-- 鐢ㄦ埛淇℃伅灞曠ず --> + <view class="user-info-section"> + <view class="info-item"> + <view class="info-label">鐢ㄦ埛鍚嶏細</view> + <view class="info-value">{{ name || '鏈櫥褰�' }}</view> + </view> + <view class="info-item"> + <view class="info-label">鎵嬫満鍙风爜锛�</view> + <view class="info-value">{{ phonenumber || '鏈粦瀹�' }}</view> + </view> + <view class="info-item"> + <view class="info-label">缁戝畾杞﹁締锛�</view> + <view class="info-value">{{ boundVehicle || '鏈粦瀹�' }}</view> + </view> + <view class="info-item"> + <view class="info-label">App鐗堟湰鍙凤細</view> + <view class="info-value">{{ version || '1.0.0' }}</view> + </view> + + <!-- 缁戝畾/瑙g粦杞﹁締鎿嶄綔 --> + <view class="vehicle-actions" v-if="boundVehicle && boundVehicle !== '鏈粦瀹�'"> + <button class="unbind-btn" @click="unbindVehicle">鍙栨秷缁戝畾杞﹁締</button> + </view> + <view class="vehicle-actions" v-else> + <button class="bind-btn" @click="goToBindVehicle">缁戝畾杞﹁締</button> </view> </view> @@ -71,18 +99,20 @@ </view> </view> </view> - - </view> + </scroll-view> </view> </template> <script> import storage from '@/utils/storage' + import { getUserProfile } from "@/api/system/user" export default { data() { return { name: this.$store.state.user.name, + phonenumber: '', + boundVehicle: '', // 妯℃嫙缁戝畾鐨勮溅杈嗕俊鎭� version: getApp().globalData.config.appInfo.version } }, @@ -94,7 +124,42 @@ return uni.getSystemInfoSync().windowHeight - 50 } }, + onLoad() { + this.getUserInfo() + }, methods: { + // 鑾峰彇鐢ㄦ埛淇℃伅 + getUserInfo() { + getUserProfile().then(response => { + const user = response.data + this.name = user.userName + this.phonenumber = user.phonenumber + // 妯℃嫙缁戝畾杞﹁締淇℃伅锛屽疄闄呴」鐩腑搴斾粠鐢ㄦ埛淇℃伅鎴栬溅杈嗘帴鍙h幏鍙� + this.boundVehicle = '绮12345' + }).catch(() => { + // 鑾峰彇鐢ㄦ埛淇℃伅澶辫触鏃朵娇鐢ㄩ粯璁ゅ�� + this.name = this.$store.state.user.name || '鏈櫥褰�' + this.phonenumber = '鏈粦瀹�' + this.boundVehicle = '鏈粦瀹�' + }) + }, + + // 璺宠浆鍒扮粦瀹氳溅杈嗛〉闈� + goToBindVehicle() { + this.$tab.navigateTo('/pages/bind-vehicle') + }, + + // 鍙栨秷缁戝畾杞﹁締 + unbindVehicle() { + this.$modal.confirm('鏄惁鍙栨秷缁戝畾杞﹁締锛�').then(() => { + // 杩欓噷鍙互璋冪敤API鍙栨秷缁戝畾杞﹁締 + this.boundVehicle = '鏈粦瀹�' + this.$modal.showToast('鍙栨秷缁戝畾鎴愬姛') + }).catch(() => { + // 鐢ㄦ埛鍙栨秷鎿嶄綔 + }) + }, + handleToInfo() { this.$tab.navigateTo('/pages/mine/info/index') }, @@ -140,13 +205,32 @@ .mine-container { width: 100%; - height: 100%; - + height: 100vh; + display: flex; + flex-direction: column; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } .header-section { padding: 15px 15px 45px 15px; background-color: #3c96f3; color: white; + flex-shrink: 0; // 闃叉鏀剁缉 .login-tip { font-size: 18px; @@ -172,8 +256,26 @@ } .content-section { + flex: 1; position: relative; top: -50px; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } .mine-actions { margin: 15px 15px; @@ -193,6 +295,60 @@ } } } + + // 鐢ㄦ埛淇℃伅灞曠ず鍖哄煙 + .user-info-section { + background-color: white; + border-radius: 8px; + padding: 20rpx 30rpx; + margin: 15rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .info-item { + display: flex; + padding: 15rpx 0; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + border-bottom: none; + } + + .info-label { + font-size: 28rpx; + color: #666; + width: 180rpx; + flex-shrink: 0; + } + + .info-value { + font-size: 28rpx; + color: #333; + flex: 1; + } + } + + .vehicle-actions { + padding: 30rpx 0 10rpx 0; + text-align: center; + + .bind-btn, .unbind-btn { + width: 80%; + height: 80rpx; + border-radius: 10rpx; + font-size: 32rpx; + } + + .bind-btn { + background-color: #007AFF; + color: white; + } + + .unbind-btn { + background-color: #ff4d4f; + color: white; + } + } + } } } -</style> +</style> \ No newline at end of file diff --git a/app/pages/mine/info/index.vue b/app/pages/mine/info/index.vue index 65c861a..3a1b9de 100644 --- a/app/pages/mine/info/index.vue +++ b/app/pages/mine/info/index.vue @@ -1,13 +1,23 @@ <template> <view class="container"> <uni-list> - <uni-list-item showExtraIcon="true" :extraIcon="{type: 'person-filled'}" title="鏄电О" :rightText="user.nickName" /> + <uni-list-item showExtraIcon="true" :extraIcon="{type: 'person-filled'}" title="鐢ㄦ埛鍚�" :rightText="user.userName" /> <uni-list-item showExtraIcon="true" :extraIcon="{type: 'phone-filled'}" title="鎵嬫満鍙风爜" :rightText="user.phonenumber" /> + <uni-list-item showExtraIcon="true" :extraIcon="{type: 'location-filled'}" title="缁戝畾杞﹁締" :rightText="boundVehicle || '鏈粦瀹�'" /> + <uni-list-item showExtraIcon="true" :extraIcon="{type: 'info-filled'}" title="App鐗堟湰鍙�" :rightText="version" /> <uni-list-item showExtraIcon="true" :extraIcon="{type: 'email-filled'}" title="閭" :rightText="user.email" /> <uni-list-item showExtraIcon="true" :extraIcon="{type: 'auth-filled'}" title="宀椾綅" :rightText="postGroup" /> <uni-list-item showExtraIcon="true" :extraIcon="{type: 'staff-filled'}" title="瑙掕壊" :rightText="roleGroup" /> <uni-list-item showExtraIcon="true" :extraIcon="{type: 'calendar-filled'}" title="鍒涘缓鏃ユ湡" :rightText="user.createTime" /> </uni-list> + + <!-- 缁戝畾/瑙g粦杞﹁締鎿嶄綔 --> + <view class="vehicle-actions" v-if="boundVehicle"> + <button class="unbind-btn" @click="unbindVehicle">鍙栨秷缁戝畾杞﹁締</button> + </view> + <view class="vehicle-actions" v-else> + <button class="bind-btn" @click="goToBindVehicle">缁戝畾杞﹁締</button> + </view> </view> </template> @@ -19,7 +29,9 @@ return { user: {}, roleGroup: "", - postGroup: "" + postGroup: "", + boundVehicle: "", // 妯℃嫙缁戝畾鐨勮溅杈嗕俊鎭� + version: getApp().globalData.config.appInfo.version || "1.0.0" // App鐗堟湰鍙� } }, onLoad() { @@ -32,6 +44,22 @@ this.roleGroup = response.roleGroup this.postGroup = response.postGroup }) + }, + + // 璺宠浆鍒扮粦瀹氳溅杈嗛〉闈� + goToBindVehicle() { + this.$tab.navigateTo('/pages/bind-vehicle') + }, + + // 鍙栨秷缁戝畾杞﹁締 + unbindVehicle() { + this.$modal.confirm('鏄惁鍙栨秷缁戝畾杞﹁締锛�').then(() => { + // 杩欓噷鍙互璋冪敤API鍙栨秷缁戝畾杞﹁締 + this.boundVehicle = "" + this.$modal.showToast('鍙栨秷缁戝畾鎴愬姛') + }).catch(() => { + // 鐢ㄦ埛鍙栨秷鎿嶄綔 + }) } } } @@ -41,4 +69,26 @@ page { background-color: #ffffff; } -</style> + + .vehicle-actions { + padding: 30rpx; + text-align: center; + + .bind-btn, .unbind-btn { + width: 80%; + height: 80rpx; + border-radius: 10rpx; + font-size: 32rpx; + } + + .bind-btn { + background-color: #007AFF; + color: white; + } + + .unbind-btn { + background-color: #ff4d4f; + color: white; + } + } +</style> \ No newline at end of file diff --git a/app/pages/task/create.vue b/app/pages/task/create.vue new file mode 100644 index 0000000..1cf4741 --- /dev/null +++ b/app/pages/task/create.vue @@ -0,0 +1,856 @@ +<template> + <scroll-view class="create-task-container" scroll-y="true"> + <!-- 浠诲姟绫诲瀷閫夋嫨鐣岄潰 --> + <view v-if="!selectedTaskCategory" class="task-category-container"> + <view class="header"> + <view class="title">閫夋嫨浠诲姟绫诲瀷</view> + <view class="subtitle">璇烽�夋嫨鎮ㄨ鍒涘缓鐨勪换鍔$被鍨�</view> + </view> + + <view class="category-list"> + <view + class="category-item" + v-for="(category, index) in taskCategories" + :key="index" + @click="selectTaskCategory(category)" + > + <view class="icon"> + <uni-icons :type="category.icon" size="30" :color="category.color"></uni-icons> + </view> + <view class="info"> + <view class="name">{{ category.name }}</view> + <view class="desc">{{ category.description }}</view> + </view> + <view class="arrow"> + <uni-icons type="arrowright" size="20" color="#999"></uni-icons> + </view> + </view> + </view> + </view> + + <!-- 浠诲姟鍒涘缓琛ㄥ崟 --> + <view v-else class="task-form-container"> + <view class="form-header"> + <view class="back-btn" @click="backToCategory"> + <uni-icons type="arrowleft" size="20"></uni-icons> + </view> + <view class="title">鍒涘缓{{ selectedTaskCategory.name }}浠诲姟</view> + </view> + + <view class="form-section"> + <!-- 鏅�氫换鍔¤〃鍗� --> + <view v-if="selectedTaskCategory.type === 'normal'"> + <view class="form-item"> + <view class="form-label">浠诲姟杞﹁締</view> + <picker mode="selector" :range="vehicles" @change="onVehicleChange"> + <view class="form-input picker-input"> + {{ selectedVehicle || '璇烽�夋嫨浠诲姟杞﹁締' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟绫诲瀷</view> + <input + class="form-input" + :value="selectedTaskCategory.name" + disabled + /> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟鎻忚堪</view> + <textarea + class="form-textarea" + placeholder="璇疯緭鍏ヤ换鍔℃弿杩�" + v-model="taskForm.description" + /> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟鍑哄彂鍦�</view> + <view class="form-input picker-input" @click="selectStartLocation"> + {{ taskForm.startLocation || '璇烽�夋嫨浠诲姟鍑哄彂鍦�' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟鐩殑鍦�</view> + <view class="form-input picker-input" @click="selectEndLocation"> + {{ taskForm.endLocation || '璇烽�夋嫨浠诲姟鐩殑鍦�' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="form-item"> + <view class="form-label">琛岄┒鍏噷鏁�</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ヨ椹跺叕閲屾暟" + v-model="taskForm.distance" + /> + </view> + + <view class="form-item"> + <view class="form-label">寮�濮嬫椂闂�</view> + <!-- 浣跨敤uni-datetime-picker缁勪欢 --> + <uni-datetime-picker + v-model="taskForm.startTime" + type="datetime" + :placeholder="'璇烽�夋嫨寮�濮嬫椂闂�'" + class="form-input" + /> + </view> + + <view class="form-item"> + <view class="form-label">缁撴潫鏃堕棿</view> + <!-- 浣跨敤uni-datetime-picker缁勪欢 --> + <uni-datetime-picker + v-model="taskForm.endTime" + type="datetime" + :placeholder="'璇烽�夋嫨缁撴潫鏃堕棿'" + class="form-input" + /> + </view> + + <view class="form-item"> + <view class="form-label">鎵ц浜�</view> + <input + class="form-input" + :value="currentUser.name" + disabled + /> + </view> + + <view class="form-item"> + <view class="form-label">澶囨敞</view> + <textarea + class="form-textarea" + placeholder="璇疯緭鍏ュ娉ㄤ俊鎭紙鏈�澶�200瀛楋級" + v-model="taskForm.remark" + maxlength="200" + /> + </view> + </view> + + <!-- 鎬ユ晳杞繍浠诲姟琛ㄥ崟 --> + <view v-else-if="selectedTaskCategory.type === 'emergency'"> + <view class="form-item"> + <view class="form-label">浠诲姟杞﹁締</view> + <picker mode="selector" :range="vehicles" @change="onVehicleChange"> + <view class="form-input picker-input"> + {{ selectedVehicle || '璇烽�夋嫨浠诲姟杞﹁締' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">鎵ц浠诲姟浜哄憳</view> + <view class="staff-list"> + <view class="staff-item"> + <text>{{ currentUser.name }} ({{ currentUser.position }})</text> + <uni-icons type="checkmarkempty" size="20" color="#007AFF"></uni-icons> + </view> + <view + class="staff-item" + v-for="(staff, index) in additionalStaff" + :key="index" + @click="removeStaff(index)" + > + <text>{{ staff.name }} ({{ staff.position }})</text> + <uni-icons type="closeempty" size="20" color="#ff4d4f"></uni-icons> + </view> + <view class="add-staff" @click="addStaff"> + <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons> + <text>娣诲姞浜哄憳</text> + </view> + </view> + </view> + + <view class="form-item"> + <view class="form-label">褰掑睘鏈烘瀯</view> + <picker mode="selector" :range="organizations" @change="onOrganizationChange"> + <view class="form-input picker-input"> + {{ selectedOrganization || '璇烽�夋嫨褰掑睘鏈烘瀯' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟绫诲瀷</view> + <picker mode="selector" :range="emergencyTaskTypes" @change="onEmergencyTaskTypeChange"> + <view class="form-input picker-input"> + {{ selectedEmergencyTaskType || '璇烽�夋嫨浠诲姟绫诲瀷' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">杞繍鏃堕棿</view> + <!-- 浣跨敤uni-datetime-picker缁勪欢 --> + <uni-datetime-picker + v-model="taskForm.transferTime" + type="datetime" + :placeholder="'璇烽�夋嫨杞繍鏃堕棿'" + class="form-input" + /> + </view> + + <view class="form-section-title">鎮h�呬俊鎭�</view> + <view class="form-item"> + <view class="form-label">鑱旂郴浜�</view> + <input + class="form-input" + placeholder="璇疯緭鍏ヨ仈绯讳汉" + v-model="taskForm.patient.contact" + /> + </view> + + <view class="form-item"> + <view class="form-label">鑱旂郴鐢佃瘽</view> + <input + class="form-input" + type="number" + placeholder="璇疯緭鍏ヨ仈绯荤數璇�" + v-model="taskForm.patient.phone" + /> + </view> + + <view class="form-item"> + <view class="form-label">鎮h�呭鍚�</view> + <input + class="form-input" + placeholder="璇疯緭鍏ユ偅鑰呭鍚�" + v-model="taskForm.patient.name" + /> + </view> + + <view class="form-item"> + <view class="form-label">鎬у埆</view> + <view class="radio-group"> + <label class="radio-item"> + <radio value="male" :checked="taskForm.patient.gender === 'male'" @click="taskForm.patient.gender = 'male'" /> + <text>鐢�</text> + </label> + <label class="radio-item"> + <radio value="female" :checked="taskForm.patient.gender === 'female'" @click="taskForm.patient.gender = 'female'" /> + <text>濂�</text> + </label> + </view> + </view> + + <view class="form-item"> + <view class="form-label">鎮h�呰韩浠借瘉</view> + <input + class="form-input" + type="idcard" + placeholder="璇疯緭鍏ユ偅鑰呰韩浠借瘉鍙�" + v-model="taskForm.patient.idCard" + /> + </view> + + <view class="form-item"> + <view class="form-label">鐥呮儏</view> + <textarea + class="form-textarea" + placeholder="璇疯緭鍏ユ偅鑰呯梾鎯呮弿杩�" + v-model="taskForm.patient.condition" + /> + </view> + + <view class="form-section-title">杞嚭鍖婚櫌淇℃伅</view> + <view class="form-item"> + <view class="form-label">鍖婚櫌鍚嶇О</view> + <input + class="form-input" + placeholder="璇疯緭鍏ヨ浆鍑哄尰闄㈠悕绉�" + v-model="taskForm.hospitalOut.name" + /> + </view> + + <view class="form-item"> + <view class="form-label">绉戝</view> + <input + class="form-input" + placeholder="璇疯緭鍏ョ瀹�" + v-model="taskForm.hospitalOut.department" + /> + </view> + + <view class="form-item"> + <view class="form-label">搴婂彿</view> + <input + class="form-input" + placeholder="璇疯緭鍏ュ簥鍙�" + v-model="taskForm.hospitalOut.bedNumber" + /> + </view> + + <view class="form-item"> + <view class="form-label">杞嚭鍦板潃</view> + <view class="form-input picker-input" @click="selectHospitalOutAddress"> + {{ taskForm.hospitalOut.address || '璇烽�夋嫨杞嚭鍦板潃' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="form-section-title">杞叆鍖婚櫌淇℃伅</view> + <view class="form-item"> + <view class="form-label">鍖婚櫌鍚嶇О</view> + <input + class="form-input" + placeholder="璇疯緭鍏ヨ浆鍏ュ尰闄㈠悕绉�" + v-model="taskForm.hospitalIn.name" + /> + </view> + + <view class="form-item"> + <view class="form-label">绉戝</view> + <input + class="form-input" + placeholder="璇疯緭鍏ョ瀹�" + v-model="taskForm.hospitalIn.department" + /> + </view> + + <view class="form-item"> + <view class="form-label">搴婂彿</view> + <input + class="form-input" + placeholder="璇疯緭鍏ュ簥鍙�" + v-model="taskForm.hospitalIn.bedNumber" + /> + </view> + + <view class="form-item"> + <view class="form-label">杞叆鍦板潃</view> + <view class="form-input picker-input" @click="selectHospitalInAddress"> + {{ taskForm.hospitalIn.address || '璇烽�夋嫨杞叆鍦板潃' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="form-item"> + <view class="form-label">杞繍鍏噷鏁�</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ヨ浆杩愬叕閲屾暟" + v-model="taskForm.transferDistance" + /> + </view> + + <view class="form-item"> + <view class="form-label">鎴愪氦浠�</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ユ垚浜や环" + v-model="taskForm.price" + /> + </view> + </view> + + <!-- 绂忕杞︿换鍔¤〃鍗� --> + <view v-else-if="selectedTaskCategory.type === 'welfare'"> + <view class="form-item"> + <view class="form-label">浠诲姟杞﹁締</view> + <picker mode="selector" :range="vehicles" @change="onVehicleChange"> + <view class="form-input picker-input"> + {{ selectedVehicle || '璇烽�夋嫨浠诲姟杞﹁締' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">鎵ц浠诲姟浜哄憳</view> + <view class="staff-list"> + <view class="staff-item"> + <text>{{ currentUser.name }} ({{ currentUser.position }})</text> + <uni-icons type="checkmarkempty" size="20" color="#007AFF"></uni-icons> + </view> + <view + class="staff-item" + v-for="(staff, index) in additionalStaff" + :key="index" + @click="removeStaff(index)" + > + <text>{{ staff.name }} ({{ staff.position }})</text> + <uni-icons type="closeempty" size="20" color="#ff4d4f"></uni-icons> + </view> + <view class="add-staff" @click="addStaff"> + <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons> + <text>娣诲姞浜哄憳</text> + </view> + </view> + </view> + + <view class="form-item"> + <view class="form-label">褰掑睘鏈烘瀯</view> + <picker mode="selector" :range="organizations" @change="onOrganizationChange"> + <view class="form-input picker-input"> + {{ selectedOrganization || '璇烽�夋嫨褰掑睘鏈烘瀯' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">鏈嶅姟鏃堕棿</view> + <!-- 浣跨敤uni-datetime-picker缁勪欢 --> + <uni-datetime-picker + v-model="taskForm.serviceTime" + type="datetime" + :placeholder="'璇烽�夋嫨鏈嶅姟鏃堕棿'" + class="form-input" + /> + </view> + + <view class="form-section-title">涔樺淇℃伅</view> + <view class="form-item"> + <view class="form-label">鑱旂郴浜�</view> + <input + class="form-input" + placeholder="璇疯緭鍏ヨ仈绯讳汉" + v-model="taskForm.passenger.contact" + /> + </view> + + <view class="form-item"> + <view class="form-label">鑱旂郴鐢佃瘽</view> + <input + class="form-input" + type="number" + placeholder="璇疯緭鍏ヨ仈绯荤數璇�" + v-model="taskForm.passenger.phone" + /> + </view> + + <view class="form-item"> + <view class="form-label">鍑哄彂鍦板潃</view> + <view class="form-input picker-input" @click="selectStartAddress"> + {{ taskForm.startAddress || '璇烽�夋嫨鍑哄彂鍦板潃' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="form-item"> + <view class="form-label">鐩殑鍦板潃</view> + <view class="form-input picker-input" @click="selectEndAddress"> + {{ taskForm.endAddress || '璇烽�夋嫨鐩殑鍦板潃' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="form-item"> + <view class="form-label">鍏噷鏁�</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ュ叕閲屾暟" + v-model="taskForm.distance" + /> + </view> + + <view class="form-item"> + <view class="form-label">鎴愪氦浠�</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ユ垚浜や环" + v-model="taskForm.price" + /> + </view> + </view> + + <view class="form-actions"> + <button class="submit-btn" @click="submitTask">淇濆瓨</button> + </view> + </view> + </view> + </scroll-view> +</template> + +<script> + import { mapState } from 'vuex' + import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue' + + export default { + components: { + uniDatetimePicker + }, + data() { + return { + selectedTaskCategory: null, + selectedVehicle: '', + selectedOrganization: '', + selectedEmergencyTaskType: '', + taskForm: { + description: '', + startLocation: '', + endLocation: '', + distance: '', + startTime: '', + endTime: '', + remark: '', + transferTime: '', + patient: { + contact: '', + phone: '', + name: '', + gender: 'male', + idCard: '', + condition: '' + }, + hospitalOut: { + name: '', + department: '', + bedNumber: '', + address: '' + }, + hospitalIn: { + name: '', + department: '', + bedNumber: '', + address: '' + }, + transferDistance: '', + price: '', + serviceTime: '', + passenger: { + contact: '', + phone: '' + }, + startAddress: '', + endAddress: '' + }, + taskCategories: [ + { + type: 'normal', + name: '缁翠慨淇濆吇', + icon: 'repair', + color: '#007AFF', + description: '璁惧缁翠慨銆佷繚鍏荤瓑鏃ュ父浠诲姟' + }, + { + type: 'normal', + name: '鍔犳补', + icon: 'fuel', + color: '#1AAD19', + description: '杞﹁締鍔犳补绛変换鍔�' + }, + { + type: 'emergency', + name: '鎬ユ晳杞繍', + icon: 'hospital', + color: '#E54D42', + description: '绱ф�ュ尰鐤楄浆杩愪换鍔�' + }, + { + type: 'welfare', + name: '绂忕杞�', + icon: 'car', + color: '#F37B1D', + description: '鑰佸勾浜恒�佹畫鐤句汉绛夌壒娈婄兢浣撶敤杞︽湇鍔�' + } + ], + vehicles: ['绮12345', '绮67890', '绮11111', '绮22222', '绮33333'], + organizations: ['骞垮窞鍒嗗叕鍙�', '娣卞湷鍒嗗叕鍙�', '鐝犳捣鍒嗗叕鍙�', '浣涘北鍒嗗叕鍙�'], + emergencyTaskTypes: ['鎬ユ晳杞繍', '鑸┖杞繍'], + additionalStaff: [] + } + }, + computed: { + ...mapState({ + currentUser: state => ({ + name: state.user.name || '寮犱笁', + position: '鍙告満' + }) + }) + }, + methods: { + selectTaskCategory(category) { + this.selectedTaskCategory = category + }, + + backToCategory() { + this.selectedTaskCategory = null + }, + + onVehicleChange(e) { + this.selectedVehicle = this.vehicles[e.detail.value] + }, + + onOrganizationChange(e) { + this.selectedOrganization = this.organizations[e.detail.value] + }, + + onEmergencyTaskTypeChange(e) { + this.selectedEmergencyTaskType = this.emergencyTaskTypes[e.detail.value] + }, + + selectStartLocation() { + this.$modal.showToast('閫夋嫨鍑哄彂鍦板姛鑳藉紑鍙戜腑') + }, + + selectEndLocation() { + this.$modal.showToast('閫夋嫨鐩殑鍦板姛鑳藉紑鍙戜腑') + }, + + selectHospitalOutAddress() { + this.$modal.showToast('閫夋嫨杞嚭鍖婚櫌鍦板潃鍔熻兘寮�鍙戜腑') + }, + + selectHospitalInAddress() { + this.$modal.showToast('閫夋嫨杞叆鍖婚櫌鍦板潃鍔熻兘寮�鍙戜腑') + }, + + selectStartAddress() { + this.$modal.showToast('閫夋嫨鍑哄彂鍦板潃鍔熻兘寮�鍙戜腑') + }, + + selectEndAddress() { + this.$modal.showToast('閫夋嫨鐩殑鍦板潃鍔熻兘寮�鍙戜腑') + }, + + addStaff() { + this.$modal.showToast('娣诲姞浜哄憳鍔熻兘寮�鍙戜腑') + }, + + removeStaff(index) { + this.additionalStaff.splice(index, 1) + }, + + submitTask() { + this.$modal.confirm('纭畾瑕佷繚瀛樹换鍔″悧锛�').then(() => { + this.$modal.showToast('浠诲姟淇濆瓨鎴愬姛') + // 杩欓噷鍙互璋冪敤API淇濆瓨浠诲姟 + // 淇濆瓨鎴愬姛鍚庤烦杞埌浠诲姟鍒楄〃 + this.$tab.navigateTo('/pages/task/index') + }).catch(() => { + // 鍙栨秷鎿嶄綔 + }) + } + } + } +</script> + +<style lang="scss"> + .create-task-container { + padding: 20rpx; + background-color: #f5f5f5; + min-height: 100vh; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + + .task-category-container { + .header { + text-align: center; + padding: 40rpx 0; + + .title { + font-size: 40rpx; + font-weight: bold; + color: #333; + margin-bottom: 20rpx; + } + + .subtitle { + font-size: 28rpx; + color: #666; + } + } + + .category-list { + .category-item { + display: flex; + align-items: center; + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .icon { + margin-right: 20rpx; + } + + .info { + flex: 1; + + .name { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 10rpx; + } + + .desc { + font-size: 26rpx; + color: #666; + } + } + + .arrow { + margin-left: 20rpx; + } + } + } + } + + .task-form-container { + .form-header { + display: flex; + align-items: center; + padding: 20rpx 0; + margin-bottom: 30rpx; + + .back-btn { + width: 60rpx; + height: 60rpx; + border-radius: 50%; + background-color: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + margin-right: 20rpx; + } + + .title { + font-size: 36rpx; + font-weight: bold; + color: #333; + } + } + + .form-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .form-section-title { + font-size: 32rpx; + font-weight: bold; + margin: 40rpx 0 20rpx 0; + padding-bottom: 10rpx; + border-bottom: 1rpx solid #f0f0f0; + } + + .form-item { + margin-bottom: 40rpx; + + &:last-child { + margin-bottom: 0; + } + + .form-label { + font-size: 28rpx; + margin-bottom: 15rpx; + color: #333; + } + + .form-input { + height: 70rpx; + padding: 0 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + + &.picker-input { + display: flex; + align-items: center; + justify-content: space-between; + } + + &[disabled] { + background-color: #f5f5f5; + color: #999; + } + } + + .form-textarea { + width: 100%; + min-height: 150rpx; + padding: 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + resize: none; + } + + .radio-group { + display: flex; + + .radio-item { + display: flex; + align-items: center; + margin-right: 30rpx; + + radio { + margin-right: 10rpx; + } + } + } + + .staff-list { + .staff-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20rpx; + background-color: #f9f9f9; + border-radius: 10rpx; + margin-bottom: 20rpx; + } + + .add-staff { + display: flex; + align-items: center; + justify-content: center; + padding: 20rpx; + border: 1rpx dashed #007AFF; + border-radius: 10rpx; + color: #007AFF; + } + } + } + + .form-actions { + margin-top: 50rpx; + text-align: center; + + .submit-btn { + width: 80%; + height: 80rpx; + background-color: #007AFF; + color: white; + border-radius: 10rpx; + font-size: 32rpx; + } + } + } + } + } +</style> \ No newline at end of file diff --git a/app/pages/task/detail.vue b/app/pages/task/detail.vue new file mode 100644 index 0000000..e23ecff --- /dev/null +++ b/app/pages/task/detail.vue @@ -0,0 +1,600 @@ +<template> + <view class="task-detail-container"> + <view class="task-header"> + <text class="task-title">{{ task.title }}</text> + <view class="task-status" :class="'status-' + task.status"> + {{ getStatusText(task.status) }} + </view> + </view> + + <!-- 鏅�氫换鍔¤鎯� --> + <view class="task-info-section" v-if="isNormalTask"> + <view class="info-item"> + <view class="label">浠诲姟缂栧彿:</view> + <view class="value">{{ task.taskNo }}</view> + </view> + + <view class="info-item"> + <view class="label">浠诲姟绫诲瀷:</view> + <view class="value">{{ getTaskTypeText(task.type) }}</view> + </view> + + <view class="info-item"> + <view class="label">杞﹁締淇℃伅:</view> + <view class="value">{{ task.vehicle }}</view> + </view> + + <view class="info-item"> + <view class="label">鍑哄彂鍦�:</view> + <view class="value">{{ task.startLocation }}</view> + </view> + + <view class="info-item"> + <view class="label">鐩殑鍦�:</view> + <view class="value">{{ task.endLocation }}</view> + </view> + + <view class="info-item"> + <view class="label">鍑哄彂鏃堕棿:</view> + <view class="value">{{ task.startTime }}</view> + </view> + + <view class="info-item"> + <view class="label">鎵ц浜哄憳:</view> + <view class="value">{{ task.assignee }}</view> + </view> + + <view class="info-item"> + <view class="label">浠诲姟鎻忚堪:</view> + <view class="value">{{ task.description || '鏃犳弿杩颁俊鎭�' }}</view> + </view> + + <view class="info-item"> + <view class="label">琛岄┒鍏噷鏁�:</view> + <view class="value">{{ task.distance || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">缁撴潫鏃堕棿:</view> + <view class="value">{{ task.endTime || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">澶囨敞:</view> + <view class="value">{{ task.remark || '鏃犲娉�' }}</view> + </view> + </view> + + <!-- 鎬ユ晳杞繍浠诲姟璇︽儏 --> + <view class="task-info-section" v-else-if="task.type === 'emergency'"> + <view class="info-item"> + <view class="label">浠诲姟缂栧彿:</view> + <view class="value">{{ task.taskNo }}</view> + </view> + + <view class="info-item"> + <view class="label">浠诲姟绫诲瀷:</view> + <view class="value">{{ getTaskTypeText(task.type) }}</view> + </view> + + <view class="info-item"> + <view class="label">杞﹁締淇℃伅:</view> + <view class="value">{{ task.vehicle }}</view> + </view> + + <view class="info-item"> + <view class="label">鎵ц浜哄憳:</view> + <view class="value">{{ task.assignee }}</view> + </view> + + <view class="info-item"> + <view class="label">褰掑睘鏈烘瀯:</view> + <view class="value">{{ task.organization || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">浠诲姟绫诲瀷:</view> + <view class="value">{{ task.emergencyTaskType || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">杞繍鏃堕棿:</view> + <view class="value">{{ task.transferTime || '鏈~鍐�' }}</view> + </view> + + <view class="section-title">鎮h�呬俊鎭�</view> + <view class="info-item"> + <view class="label">鑱旂郴浜�:</view> + <view class="value">{{ task.patient.contact || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鑱旂郴鐢佃瘽:</view> + <view class="value">{{ task.patient.phone || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鎮h�呭鍚�:</view> + <view class="value">{{ task.patient.name || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鎬у埆:</view> + <view class="value">{{ task.patient.gender === 'male' ? '鐢�' : '濂�' }}</view> + </view> + + <view class="info-item"> + <view class="label">韬唤璇�:</view> + <view class="value">{{ task.patient.idCard || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鐥呮儏:</view> + <view class="value">{{ task.patient.condition || '鏈~鍐�' }}</view> + </view> + + <view class="section-title">杞嚭鍖婚櫌淇℃伅</view> + <view class="info-item"> + <view class="label">鍖婚櫌鍚嶇О:</view> + <view class="value">{{ task.hospitalOut.name || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">绉戝:</view> + <view class="value">{{ task.hospitalOut.department || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">搴婂彿:</view> + <view class="value">{{ task.hospitalOut.bedNumber || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鍦板潃:</view> + <view class="value">{{ task.hospitalOut.address || '鏈~鍐�' }}</view> + </view> + + <view class="section-title">杞叆鍖婚櫌淇℃伅</view> + <view class="info-item"> + <view class="label">鍖婚櫌鍚嶇О:</view> + <view class="value">{{ task.hospitalIn.name || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">绉戝:</view> + <view class="value">{{ task.hospitalIn.department || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">搴婂彿:</view> + <view class="value">{{ task.hospitalIn.bedNumber || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鍦板潃:</view> + <view class="value">{{ task.hospitalIn.address || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">杞繍鍏噷鏁�:</view> + <view class="value">{{ task.transferDistance || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鎴愪氦浠�:</view> + <view class="value">楼{{ task.price || '鏈~鍐�' }}</view> + </view> + </view> + + <!-- 绂忕杞︿换鍔¤鎯� --> + <view class="task-info-section" v-else-if="task.type === 'welfare'"> + <view class="info-item"> + <view class="label">浠诲姟缂栧彿:</view> + <view class="value">{{ task.taskNo }}</view> + </view> + + <view class="info-item"> + <view class="label">浠诲姟绫诲瀷:</view> + <view class="value">{{ getTaskTypeText(task.type) }}</view> + </view> + + <view class="info-item"> + <view class="label">杞﹁締淇℃伅:</view> + <view class="value">{{ task.vehicle }}</view> + </view> + + <view class="info-item"> + <view class="label">鎵ц浜哄憳:</view> + <view class="value">{{ task.assignee }}</view> + </view> + + <view class="info-item"> + <view class="label">褰掑睘鏈烘瀯:</view> + <view class="value">{{ task.organization || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鏈嶅姟鏃堕棿:</view> + <view class="value">{{ task.serviceTime || '鏈~鍐�' }}</view> + </view> + + <view class="section-title">涔樺淇℃伅</view> + <view class="info-item"> + <view class="label">鑱旂郴浜�:</view> + <view class="value">{{ task.passenger.contact || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鑱旂郴鐢佃瘽:</view> + <view class="value">{{ task.passenger.phone || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鍑哄彂鍦板潃:</view> + <view class="value">{{ task.startAddress || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鐩殑鍦板潃:</view> + <view class="value">{{ task.endAddress || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鍏噷鏁�:</view> + <view class="value">{{ task.distance || '鏈~鍐�' }}</view> + </view> + + <view class="info-item"> + <view class="label">鎴愪氦浠�:</view> + <view class="value">楼{{ task.price || '鏈~鍐�' }}</view> + </view> + </view> + + <!-- 浠诲姟鎿嶄綔鎸夐挳 (浠诲姟鏈畬鎴愭椂鏄剧ず) --> + <view class="task-actions" v-if="task.status !== 'completed'"> + <button + class="action-btn" + :class="{ disabled: isActionDisabled('depart') }" + @click="handleTaskAction('depart')" + > + 鍑哄彂 + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled('arrive') }" + @click="handleTaskAction('arrive')" + > + 宸插埌杈� + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled('return') }" + @click="handleTaskAction('return')" + > + 杩旂▼ + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled('settle') }" + @click="handleTaskAction('settle')" + > + 缁撶畻 + </button> + <button + class="action-btn primary" + :class="{ disabled: isActionDisabled('complete') }" + @click="handleTaskAction('complete')" + > + 宸插畬鎴� + </button> + </view> + + <view class="action-section"> + <button class="back-btn" @click="goBack">杩斿洖</button> + </view> + </view> +</template> + +<script> + export default { + data() { + return { + task: { + id: 1, + title: '绱ф�ョ淮淇换鍔�', + type: 'maintenance', + startLocation: '骞垮窞甯傚ぉ娌冲尯XX璺�123鍙�', + endLocation: '骞垮窞甯傜櫧浜戝尯YY璺�456鍙�', + startTime: '2023-05-15 15:00', + assignee: '寮犱笁', + status: 'pending', + vehicle: '绮12345', + taskNo: 'RW20230515001', + description: '璁惧鏁呴殰锛岄渶瑕佺揣鎬ョ淮淇�', + // 鏅�氫换鍔″瓧娈� + distance: '25', + endTime: '2023-05-15 17:00', + remark: '缁翠慨瀹屾垚鍚庨渶瑕佹祴璇�', + // 鎬ユ晳杞繍浠诲姟瀛楁 + organization: '骞垮窞鎬ユ晳涓績', + emergencyTaskType: '鎬ユ晳杞繍', + transferTime: '2023-05-15 16:00', + patient: { + contact: '鏉庡洓', + phone: '13800138000', + name: '鐜嬩簲', + gender: 'male', + idCard: '440100198001011234', + condition: '绐佸彂蹇冭剰鐥�' + }, + hospitalOut: { + name: '骞垮窞甯傜涓�浜烘皯鍖婚櫌', + department: '蹇冨唴绉�', + bedNumber: '101', + address: '骞垮窞甯傝秺绉�鍖哄尰闄㈣矾1鍙�' + }, + hospitalIn: { + name: '骞夸笢鐪佷汉姘戝尰闄�', + department: '蹇冨唴绉�', + bedNumber: '205', + address: '骞垮窞甯傚ぉ娌冲尯鍖婚櫌璺�2鍙�' + }, + transferDistance: '15', + price: '800', + // 绂忕杞︿换鍔″瓧娈� + serviceTime: '2023-05-16 09:00', + passenger: { + contact: '璧靛叚', + phone: '13900139000' + }, + startAddress: '骞垮窞甯傝崝婀惧尯绀惧尯璺�10鍙�', + endAddress: '骞垮窞甯傚ぉ娌冲尯鍏昏�侀櫌璺�20鍙�' + } + } + }, + computed: { + // 鍒ゆ柇鏄惁涓烘櫘閫氫换鍔� + isNormalTask() { + return this.task.type === 'maintenance' || this.task.type === 'refuel' || this.task.type === 'inspection'; + } + }, + onLoad(options) { + // 瀹為檯椤圭洰涓繖閲屼細閫氳繃API鑾峰彇浠诲姟璇︽儏 + // const taskId = options.id; + // this.getTaskDetail(taskId); + }, + methods: { + goBack() { + this.$tab.navigateBack(); + }, + + getStatusText(status) { + const statusMap = { + 'pending': '寰呭鐞�', + 'processing': '澶勭悊涓�', + 'completed': '宸插畬鎴�' + } + return statusMap[status] || '鏈煡' + }, + + getTaskTypeText(type) { + const typeMap = { + 'maintenance': '缁翠慨淇濆吇', + 'refuel': '鍔犳补', + 'inspection': '宸℃', + 'emergency': '鎬ユ晳杞繍', + 'welfare': '绂忕杞�' + } + return typeMap[type] || '鏈煡绫诲瀷' + }, + + // 鍒ゆ柇鎿嶄綔鎸夐挳鏄惁绂佺敤 + isActionDisabled(action) { + // 鏍规嵁浠诲姟鐘舵�佸拰鎿嶄綔绫诲瀷鍒ゆ柇鏄惁绂佺敤 + switch (action) { + case 'depart': + return this.task.status !== 'pending'; + case 'arrive': + return this.task.status !== 'processing'; + case 'return': + return this.task.status !== 'processing'; + case 'settle': + return this.task.status !== 'processing'; + case 'complete': + return this.task.status !== 'processing'; + default: + return false; + } + }, + + // 澶勭悊浠诲姟鎿嶄綔 + handleTaskAction(action) { + if (this.isActionDisabled(action)) { + return; + } + + switch (action) { + case 'depart': + // 鍑哄彂鎿嶄綔锛屾牴鎹换鍔$被鍨嬫樉绀轰笉鍚岀殑纭淇℃伅 + let departMessage = '纭畾瑕佹爣璁颁负宸插嚭鍙戝悧锛�'; + if (this.task.type !== 'maintenance' && this.task.type !== 'refuel' && this.task.type !== 'inspection') { + departMessage = '鍙戝嚭鍘荤洰鐨勫湴,纭锛�'; + } + this.$modal.confirm(departMessage).then(() => { + this.task.status = 'processing'; + this.$modal.showToast('宸插嚭鍙�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'arrive': + // 宸插埌杈炬搷浣� + this.$modal.confirm('宸茬粡鍒拌揪鐩殑鍦帮紝纭锛�').then(() => { + this.$modal.showToast('宸插埌杈�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'return': + // 杩旂▼鎿嶄綔 + this.$modal.confirm('鐜板湪宸茬粡杩旂▼涓紝纭锛�').then(() => { + this.$modal.showToast('杩旂▼涓�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'settle': + // 缁撶畻鎿嶄綔锛岃烦杞埌缁撶畻椤甸潰 + this.$tab.navigateTo(`/pages/task/settlement?id=${this.task.id}`); + break; + case 'complete': + // 宸插畬鎴愭搷浣� + this.$modal.confirm('浠诲姟鏄惁宸茬粡鍏ㄩ儴瀹屾垚锛岀‘璁わ紵').then(() => { + this.task.status = 'completed'; + this.$modal.showToast('浠诲姟宸插畬鎴�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + } + }, + + // 妯℃嫙鑾峰彇浠诲姟璇︽儏 + getTaskDetail(taskId) { + // 杩欓噷搴旇璋冪敤API鑾峰彇浠诲姟璇︽儏 + // 鏆傛椂浣跨敤妯℃嫙鏁版嵁 + } + } + } +</script> + +<style lang="scss"> + .task-detail-container { + padding: 20rpx; + background-color: #f5f5f5; + min-height: 100vh; + } + + .task-header { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + display: flex; + justify-content: space-between; + align-items: center; + + .task-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + } + + .task-status { + padding: 10rpx 20rpx; + border-radius: 10rpx; + font-size: 24rpx; + font-weight: bold; + + &.status-pending { + background-color: #fff3cd; + color: #856404; + } + + &.status-processing { + background-color: #cce5ff; + color: #004085; + } + + &.status-completed { + background-color: #d4edda; + color: #155724; + } + } + } + + .task-info-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .section-title { + font-size: 32rpx; + font-weight: bold; + margin: 30rpx 0 20rpx 0; + padding-bottom: 10rpx; + border-bottom: 1rpx solid #f0f0f0; + color: #333; + } + + .info-item { + display: flex; + margin-bottom: 20rpx; + padding-bottom: 20rpx; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; + } + + .label { + font-size: 28rpx; + color: #666; + margin-right: 20rpx; + white-space: nowrap; + width: 150rpx; + } + + .value { + font-size: 28rpx; + flex: 1; + word-break: break-all; + } + } + } + + .task-actions { + display: flex; + flex-wrap: wrap; + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .action-btn { + flex: 1; + min-width: 30%; + height: 70rpx; + border-radius: 10rpx; + font-size: 26rpx; + margin: 10rpx 5rpx; + background-color: #f0f0f0; + color: #333; + + &.primary { + background-color: #007AFF; + color: white; + } + + &.disabled { + opacity: 0.5; + } + } + } + + .action-section { + margin-top: 40rpx; + text-align: center; + + .back-btn { + width: 80%; + height: 80rpx; + background-color: #007AFF; + color: white; + border-radius: 10rpx; + font-size: 32rpx; + } + } +</style> \ No newline at end of file diff --git a/app/pages/task/index.vue b/app/pages/task/index.vue new file mode 100644 index 0000000..ff9746c --- /dev/null +++ b/app/pages/task/index.vue @@ -0,0 +1,798 @@ +<template> + <view class="task-container"> + <!-- 浠诲姟鍒楄〃澶撮儴 --> + <view class="task-list-section"> + <view class="task-header"> + <view class="header-title">浠诲姟鍒楄〃</view> + <view class="header-actions"> + <button class="search-toggle-btn" @click="toggleSearch"> + <uni-icons :type="showSearch ? 'close' : 'search'" size="20"></uni-icons> + </button> + <button class="refresh-btn" @click="refreshList"> + <uni-icons type="refresh" size="20"></uni-icons> + </button> + </view> + </view> + + <!-- 鏌ヨ鏉′欢鍖哄煙 --> + <view class="search-section" v-show="showSearch"> + <view class="search-form"> + <view class="form-item"> + <view class="form-label">浠诲姟鐘舵��</view> + <picker mode="selector" :range="statusOptions" @change="onStatusChange"> + <view class="form-input picker-input"> + {{ selectedStatusText || '鍏ㄩ儴鐘舵��' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟鏃堕棿</view> + <view class="date-range"> + <!-- 浣跨敤uni-datetime-picker缁勪欢 --> + <uni-datetime-picker + v-model="startDate" + type="date" + :placeholder="'寮�濮嬫椂闂�'" + class="date-input" + /> + <text class="divider">鑷�</text> + <!-- 浣跨敤uni-datetime-picker缁勪欢 --> + <uni-datetime-picker + v-model="endDate" + type="date" + :placeholder="'缁撴潫鏃堕棿'" + class="date-input" + /> + </view> + </view> + + <view class="form-item"> + <view class="form-label">杞︾墝鍙�</view> + <input + class="form-input" + placeholder="璇疯緭鍏ヨ溅鐗屽彿" + v-model="searchForm.vehicle" + /> + </view> + + <view class="form-item"> + <view class="form-label">浠诲姟缂栧彿</view> + <input + class="form-input" + placeholder="璇疯緭鍏ヤ换鍔$紪鍙�" + v-model="searchForm.taskNo" + /> + </view> + + <view class="form-actions"> + <button class="search-btn" @click="handleSearch">鏌ヨ</button> + <button class="reset-btn" @click="resetSearch">閲嶇疆</button> + </view> + </view> + </view> + + <view class="task-filter"> + <scroll-view class="filter-tabs" scroll-x="true"> + <view + class="filter-item" + :class="{ active: currentFilter === 'all' }" + @click="changeFilter('all')" + > + 鍏ㄩ儴 + </view> + <view + class="filter-item" + :class="{ active: currentFilter === 'pending' }" + @click="changeFilter('pending')" + > + 寰呭鐞� + </view> + <view + class="filter-item" + :class="{ active: currentFilter === 'processing' }" + @click="changeFilter('processing')" + > + 澶勭悊涓� + </view> + <view + class="filter-item" + :class="{ active: currentFilter === 'completed' }" + @click="changeFilter('completed')" + > + 宸插畬鎴� + </view> + </scroll-view> + </view> + + <scroll-view class="task-list-scroll" scroll-y="true"> + <view class="task-list"> + <view class="task-item" v-for="task in filteredTaskList" :key="task.id"> + <view class="task-main" @click="viewTaskDetail(task)"> + <view class="task-title">{{ getTaskTypeText(task.type) }} - {{ task.vehicle }}</view> + <view class="task-info"> + <view class="info-row"> + <view class="info-item"> + <view class="label">浠诲姟缂栧彿:</view> + <view class="value">{{ task.taskNo }}</view> + </view> + <view class="info-item"> + <view class="label">浠诲姟鐘舵��:</view> + <view class="value">{{ getStatusText(task.status) }}</view> + </view> + </view> + <view class="info-row"> + <view class="info-item"> + <view class="label">鍑哄彂鍦�:</view> + <view class="value">{{ task.startLocation }}</view> + </view> + <view class="info-item"> + <view class="label">鐩殑鍦�:</view> + <view class="value">{{ task.endLocation }}</view> + </view> + </view> + <view class="info-row"> + <view class="info-item"> + <view class="label">鍑哄彂鏃堕棿:</view> + <view class="value">{{ task.startTime }}</view> + </view> + <view class="info-item"> + <view class="label">鎵ц浜哄憳:</view> + <view class="value">{{ task.assignee }}</view> + </view> + </view> + </view> + </view> + + <!-- 鎿嶄綔鎸夐挳 --> + <view class="task-actions"> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'depart') }" + @click="handleTaskAction(task, 'depart')" + v-if="task.status !== 'completed'" + > + 鍑哄彂 + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'arrive') }" + @click="handleTaskAction(task, 'arrive')" + v-if="task.status !== 'completed'" + > + 宸插埌杈� + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'return') }" + @click="handleTaskAction(task, 'return')" + v-if="task.status !== 'completed'" + > + 杩旂▼ + </button> + <button + class="action-btn" + :class="{ disabled: isActionDisabled(task, 'settle') }" + @click="handleTaskAction(task, 'settle')" + v-if="task.status !== 'completed'" + > + 缁撶畻 + </button> + <button + class="action-btn primary" + :class="{ disabled: isActionDisabled(task, 'complete') }" + @click="handleTaskAction(task, 'complete')" + v-if="task.status !== 'completed'" + > + 宸插畬鎴� + </button> + </view> + </view> + + <view class="no-data" v-if="filteredTaskList.length === 0"> + <uni-icons type="info" size="40" color="#ccc"></uni-icons> + <text>鏆傛棤浠诲姟鏁版嵁</text> + </view> + </view> + </scroll-view> + </view> + </view> +</template> + +<script> + import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue' + + export default { + components: { + uniDatetimePicker + }, + data() { + return { + // 鎺у埗鏌ヨ鐣岄潰鏄剧ず/闅愯棌 + showSearch: false, + + // 鏌ヨ鏉′欢 + searchForm: { + vehicle: '', + taskNo: '' + }, + statusOptions: ['鍏ㄩ儴鐘舵��', '寰呭鐞�', '澶勭悊涓�', '宸插畬鎴�'], + statusValues: ['', 'pending', 'processing', 'completed'], + selectedStatus: '', + selectedStatusText: '', + startDate: '', + endDate: '', + currentFilter: 'all', + + // 浠诲姟鍒楄〃 + taskList: [ + { + id: 1, + title: '绱ф�ョ淮淇换鍔�', + type: 'maintenance', // 缁翠慨淇濆吇 + startLocation: '骞垮窞甯傚ぉ娌冲尯XX璺�123鍙�', + endLocation: '骞垮窞甯傜櫧浜戝尯YY璺�456鍙�', + startTime: '2023-05-15 15:00', + assignee: '寮犱笁', + status: 'pending', + vehicle: '绮12345', + taskNo: 'RW20230515001' + }, + { + id: 2, + title: '瀹氭湡淇濆吇浠诲姟', + type: 'maintenance', // 缁翠慨淇濆吇 + startLocation: '娣卞湷甯傚崡灞卞尯XX璺�789鍙�', + endLocation: '娣卞湷甯傜鐢板尯YY璺�999鍙�', + startTime: '2023-05-14 10:00', + assignee: '鏉庡洓', + status: 'processing', + vehicle: '绮67890', + taskNo: 'RW20230514002' + }, + { + id: 3, + title: '璁惧宸℃浠诲姟', + type: 'inspection', // 宸℃浠诲姟 + startLocation: '鐝犳捣甯傞娲插尯XX璺�321鍙�', + endLocation: '鐝犳捣甯傞噾婀惧尯YY璺�654鍙�', + startTime: '2023-05-13 17:00', + assignee: '鐜嬩簲', + status: 'completed', + vehicle: '绮11111', + taskNo: 'RW20230513003' + }, + { + id: 4, + title: '鍔犳补浠诲姟', + type: 'refuel', // 鍔犳补 + startLocation: '浣涘北甯傜鍩庡尯AA璺�555鍙�', + endLocation: '浣涘北甯傚崡娴峰尯BB璺�888鍙�', + startTime: '2023-05-12 09:00', + assignee: '璧靛叚', + status: 'completed', + vehicle: '绮22222', + taskNo: 'RW20230512004' + }, + { + id: 5, + title: '鎬ユ晳杞繍浠诲姟', + type: 'emergency', // 鎬ユ晳杞繍 + startLocation: '骞垮窞甯傝秺绉�鍖哄尰闄㈣矾1鍙�', + endLocation: '骞垮窞甯傛捣鐝犲尯鍖婚櫌璺�2鍙�', + startTime: '2023-05-16 14:00', + assignee: '寮犲尰鐢�,鏉庢姢澹�', + status: 'pending', + vehicle: '绮33333', + taskNo: 'RW20230516005' + }, + { + id: 6, + title: '绂忕杞︿换鍔�', + type: 'welfare', // 绂忕杞� + startLocation: '骞垮窞甯傝崝婀惧尯绀惧尯璺�10鍙�', + endLocation: '骞垮窞甯傚ぉ娌冲尯鍏昏�侀櫌璺�20鍙�', + startTime: '2023-05-17 08:00', + assignee: '鐜嬪徃鏈�', + status: 'processing', + vehicle: '绮44444', + taskNo: 'RW20230517006' + } + ] + } + }, + computed: { + filteredTaskList() { + let filtered = this.taskList; + + // 搴旂敤绛涢�夊櫒 + if (this.currentFilter !== 'all') { + filtered = filtered.filter(task => { + if (this.currentFilter === 'pending') return task.status === 'pending'; + if (this.currentFilter === 'processing') return task.status === 'processing'; + if (this.currentFilter === 'completed') return task.status === 'completed'; + return true; + }); + } + + // 搴旂敤鐘舵�佺瓫閫� + if (this.selectedStatus) { + filtered = filtered.filter(task => task.status === this.selectedStatus); + } + + // 搴旂敤杞︾墝鍙风瓫閫� + if (this.searchForm.vehicle) { + filtered = filtered.filter(task => + task.vehicle.includes(this.searchForm.vehicle) + ); + } + + // 搴旂敤浠诲姟缂栧彿绛涢�� + if (this.searchForm.taskNo) { + filtered = filtered.filter(task => + task.taskNo.includes(this.searchForm.taskNo) + ); + } + + // 搴旂敤鏃堕棿鑼冨洿绛涢�� + if (this.startDate) { + filtered = filtered.filter(task => + task.startTime >= this.startDate + ); + } + + if (this.endDate) { + // 缁撴潫鏃ユ湡鍔犱竴澶╋紝浠ヤ究鍖呭惈褰撳ぉ鐨勬暟鎹� + const end = new Date(this.endDate); + end.setDate(end.getDate() + 1); + const endDateStr = end.toISOString().split('T')[0]; + + filtered = filtered.filter(task => + task.startTime < endDateStr + ); + } + + return filtered; + } + }, + methods: { + // 鍒囨崲鏌ヨ鐣岄潰鏄剧ず/闅愯棌 + toggleSearch() { + this.showSearch = !this.showSearch; + }, + + // 鐘舵�侀�夋嫨 + onStatusChange(e) { + this.selectedStatus = this.statusValues[e.detail.value]; + this.selectedStatusText = this.statusOptions[e.detail.value]; + }, + + // 鏌ヨ + handleSearch() { + this.$modal.showToast('鏌ヨ鎴愬姛'); + console.log('鏌ヨ鏉′欢:', { + status: this.selectedStatus, + startDate: this.startDate, + endDate: this.endDate, + vehicle: this.searchForm.vehicle, + taskNo: this.searchForm.taskNo + }); + // 鏌ヨ瀹屾垚鍚庨殣钘忔煡璇㈢晫闈� + this.showSearch = false; + // 杩欓噷鍙互璋冪敤API杩涜鏌ヨ + }, + + // 閲嶇疆鏌ヨ鏉′欢 + resetSearch() { + this.selectedStatus = ''; + this.selectedStatusText = ''; + this.startDate = ''; + this.endDate = ''; + this.searchForm.vehicle = ''; + this.searchForm.taskNo = ''; + }, + + // 鍒锋柊鍒楄〃 + refreshList() { + this.$modal.showToast('鍒楄〃宸插埛鏂�'); + // 杩欓噷鍙互閲嶆柊鍔犺浇鏁版嵁 + }, + + // 绛涢�� + changeFilter(filter) { + this.currentFilter = filter; + }, + + // 鏌ョ湅浠诲姟璇︽儏 + viewTaskDetail(task) { + // 璺宠浆鍒颁换鍔¤鎯呴〉闈� + this.$tab.navigateTo(`/pages/task/detail?id=${task.id}`); + }, + + // 鍒ゆ柇鎿嶄綔鎸夐挳鏄惁绂佺敤 + isActionDisabled(task, action) { + // 鏍规嵁浠诲姟鐘舵�佸拰鎿嶄綔绫诲瀷鍒ゆ柇鏄惁绂佺敤 + switch (action) { + case 'depart': + return task.status !== 'pending'; + case 'arrive': + return task.status !== 'processing'; + case 'return': + return task.status !== 'processing'; + case 'settle': + return task.status !== 'processing'; + case 'complete': + return task.status !== 'processing'; + default: + return false; + } + }, + + // 澶勭悊浠诲姟鎿嶄綔 + handleTaskAction(task, action) { + if (this.isActionDisabled(task, action)) { + return; + } + + switch (action) { + case 'depart': + // 鍑哄彂鎿嶄綔锛屾牴鎹换鍔$被鍨嬫樉绀轰笉鍚岀殑纭淇℃伅 + let departMessage = '纭畾瑕佹爣璁颁负宸插嚭鍙戝悧锛�'; + if (task.type !== 'maintenance' && task.type !== 'refuel' && task.type !== 'inspection') { + departMessage = '鍙戝嚭鍘荤洰鐨勫湴,纭锛�'; + } + this.$modal.confirm(departMessage).then(() => { + task.status = 'processing'; + this.$modal.showToast('宸插嚭鍙�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'arrive': + // 宸插埌杈炬搷浣� + this.$modal.confirm('宸茬粡鍒拌揪鐩殑鍦帮紝纭锛�').then(() => { + this.$modal.showToast('宸插埌杈�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'return': + // 杩旂▼鎿嶄綔 + this.$modal.confirm('鐜板湪宸茬粡杩旂▼涓紝纭锛�').then(() => { + this.$modal.showToast('杩旂▼涓�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + case 'settle': + // 缁撶畻鎿嶄綔锛岃烦杞埌缁撶畻椤甸潰 + this.$tab.navigateTo(`/pages/task/settlement?id=${task.id}`); + break; + case 'complete': + // 宸插畬鎴愭搷浣� + this.$modal.confirm('浠诲姟鏄惁宸茬粡鍏ㄩ儴瀹屾垚锛岀‘璁わ紵').then(() => { + task.status = 'completed'; + this.$modal.showToast('浠诲姟宸插畬鎴�'); + // 杩欓噷鍙互璋冪敤API鏇存柊浠诲姟鐘舵�� + }).catch(() => {}); + break; + } + }, + + getStatusText(status) { + const statusMap = { + 'pending': '寰呭鐞�', + 'processing': '澶勭悊涓�', + 'completed': '宸插畬鎴�' + } + return statusMap[status] || '鏈煡' + }, + + getTaskTypeText(type) { + const typeMap = { + 'maintenance': '缁翠慨淇濆吇', + 'refuel': '鍔犳补', + 'inspection': '宸℃', + 'emergency': '鎬ユ晳杞繍', + 'welfare': '绂忕杞�' + } + return typeMap[type] || '鏈煡绫诲瀷' + } + } + } +</script> + +<style lang="scss"> + .task-container { + padding: 20rpx; + background-color: #f5f5f5; + height: 100vh; + display: flex; + flex-direction: column; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + } + + // 浠诲姟鍒楄〃鍖哄煙 + .task-list-section { + flex: 1; + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + } + + .task-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20rpx 0; + flex-shrink: 0; // 闃叉鏀剁缉 + + .header-title { + font-size: 36rpx; + font-weight: bold; + } + + .header-actions { + display: flex; + + .search-toggle-btn, .refresh-btn { + width: 60rpx; + height: 60rpx; + border-radius: 50%; + background-color: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + margin-left: 20rpx; + } + } + } + + // 鏌ヨ鏉′欢鍖哄煙 + .search-section { + background-color: #f9f9f9; + border-radius: 15rpx; + padding: 30rpx; + margin: 20rpx 0; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + flex-shrink: 0; // 闃叉鏀剁缉 + + .form-item { + margin-bottom: 30rpx; + + &:last-child { + margin-bottom: 0; + } + + .form-label { + font-size: 28rpx; + margin-bottom: 15rpx; + color: #333; + } + + .form-input { + height: 70rpx; + padding: 0 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + + &.picker-input { + display: flex; + align-items: center; + justify-content: space-between; + } + } + + .date-range { + display: flex; + align-items: center; + + .date-input { + flex: 1; + height: 70rpx; + padding: 0 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + display: flex; + align-items: center; + } + + .divider { + margin: 0 20rpx; + color: #999; + } + } + } + + .form-actions { + display: flex; + margin-top: 20rpx; + + .search-btn, .reset-btn { + flex: 1; + height: 70rpx; + border-radius: 10rpx; + font-size: 28rpx; + margin: 0 10rpx; + } + + .search-btn { + background-color: #007AFF; + color: white; + } + } + } + + .task-filter { + margin-bottom: 30rpx; + flex-shrink: 0; // 闃叉鏀剁缉 + + .filter-tabs { + white-space: nowrap; + padding: 10rpx 0; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + + .filter-item { + display: inline-block; + padding: 15rpx 30rpx; + margin-right: 20rpx; + background-color: #f5f5f5; + border-radius: 30rpx; + font-size: 28rpx; + + &.active { + background-color: #007AFF; + color: white; + } + } + } + } + + .task-list-scroll { + flex: 1; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + } + + .task-list { + .task-item { + background-color: #fafafa; + border-radius: 15rpx; + margin-bottom: 30rpx; + overflow: hidden; + + .task-main { + padding: 30rpx; + border-bottom: 1rpx solid #f0f0f0; + + .task-title { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 20rpx; + } + + .task-info { + .info-row { + display: flex; + margin-bottom: 15rpx; + + &:last-child { + margin-bottom: 0; + } + + .info-item { + flex: 1; + display: flex; + + .label { + font-size: 26rpx; + color: #666; + margin-right: 10rpx; + white-space: nowrap; + } + + .value { + font-size: 26rpx; + flex: 1; + word-break: break-all; + } + } + } + } + } + + .task-actions { + display: flex; + padding: 20rpx; + + .action-btn { + flex: 1; + height: 70rpx; + border-radius: 10rpx; + font-size: 26rpx; + margin: 0 5rpx; + background-color: #f0f0f0; + color: #333; + + &.primary { + background-color: #007AFF; + color: white; + } + + &.disabled { + opacity: 0.5; + } + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + } + } + } + + .no-data { + text-align: center; + padding: 100rpx 0; + color: #999; + + text { + display: block; + margin-top: 20rpx; + } + } + } +</style> \ No newline at end of file diff --git a/app/pages/task/settlement.vue b/app/pages/task/settlement.vue new file mode 100644 index 0000000..865269b --- /dev/null +++ b/app/pages/task/settlement.vue @@ -0,0 +1,747 @@ +<template> + <view class="settlement-container"> + <view class="settlement-header"> + <text class="header-title">浠诲姟缁撶畻</text> + </view> + + <scroll-view class="settlement-content" scroll-y="true"> + <view class="task-info-section"> + <view class="info-item"> + <view class="label">浠诲姟缂栧彿:</view> + <view class="value">{{ task.taskNo }}</view> + </view> + + <view class="info-item"> + <view class="label">浠诲姟绫诲瀷:</view> + <view class="value">{{ getTaskTypeText(task.type) }}</view> + </view> + + <view class="info-item"> + <view class="label">杞﹁締淇℃伅:</view> + <view class="value">{{ task.vehicle }}</view> + </view> + + <view class="info-item"> + <view class="label">鍑哄彂鍦�:</view> + <view class="value">{{ task.startLocation }}</view> + </view> + + <view class="info-item"> + <view class="label">鐩殑鍦�:</view> + <view class="value">{{ task.endLocation }}</view> + </view> + </view> + + <view class="amount-section"> + <view class="section-title">璐圭敤淇℃伅</view> + + <view class="amount-item"> + <view class="label">鍩虹璐圭敤:</view> + <view class="value">楼{{ baseAmount }}</view> + </view> + + <view class="amount-item additional-fees" @click="showAdditionalFees"> + <view class="label">闄勫姞璐圭敤:</view> + <view class="value">楼{{ additionalAmount }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </view> + + <view class="amount-item total-amount"> + <view class="label">鎬昏垂鐢�:</view> + <view class="value total">楼{{ totalAmount }}</view> + </view> + </view> + + <view class="settlement-form"> + <view class="form-item"> + <view class="form-label">缁撶畻閲戦</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ョ粨绠楅噾棰�" + v-model="settlementAmount" + /> + </view> + + <view class="form-item"> + <view class="form-label">鏀粯鏂瑰紡</view> + <picker mode="selector" :range="paymentMethods" @change="onPaymentMethodChange"> + <view class="form-input picker-input"> + {{ selectedPaymentMethod || '璇烽�夋嫨鏀粯鏂瑰紡' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">澶囨敞</view> + <textarea + class="form-textarea" + placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" + v-model="remark" + /> + </view> + </view> + + <!-- 鏀粯浜岀淮鐮佸尯鍩� --> + <view v-if="showQRCode" class="qr-code-section"> + <view class="section-title">璇锋壂鐮佹敮浠�</view> + <view class="qr-code-container"> + <image class="qr-code" :src="qrCodeImage" mode="widthFix"></image> + <view class="qr-tip">璇蜂娇鐢▄{ selectedPaymentMethod }}鎵爜鏀粯</view> + </view> + <view class="payment-status"> + <view v-if="paymentStatus === 'pending'" class="status-pending">绛夊緟鏀粯...</view> + <view v-if="paymentStatus === 'success'" class="status-success"> + <uni-icons type="checkmarkempty" size="24" color="#4cd964"></uni-icons> + 鏀粯鎴愬姛 + </view> + </view> + </view> + </scroll-view> + + <view class="action-section"> + <button + v-if="!showQRCode || paymentStatus === 'success'" + class="submit-btn" + @click="saveSettlement" + :disabled="!canSave" + > + 淇濆瓨缁撶畻 + </button> + </view> + + <!-- 闄勫姞璐圭敤寮圭獥 --> + <uni-popup ref="additionalFeesPopup" type="bottom"> + <view class="popup-content"> + <view class="popup-header"> + <text class="header-title">闄勫姞璐圭敤</text> + <view class="close-btn" @click="closeAdditionalFeesPopup"> + <uni-icons type="close" size="20" color="#999"></uni-icons> + </view> + </view> + + <!-- 绠�鍖栫増璐圭敤娣诲姞 --> + <view class="simple-fee-section"> + <view class="form-item"> + <view class="form-label">璐圭敤绫诲瀷</view> + <picker mode="selector" :range="additionalFeeTypeNames" @change="onFeeTypeChange"> + <view class="form-input picker-input"> + {{ selectedFeeTypeName || '璇烽�夋嫨璐圭敤绫诲瀷' }} + <uni-icons type="arrowright" size="16" color="#999"></uni-icons> + </view> + </picker> + </view> + + <view class="form-item"> + <view class="form-label">璐圭敤閲戦</view> + <input + class="form-input" + type="digit" + placeholder="璇疯緭鍏ヨ垂鐢ㄩ噾棰�" + v-model="newFeePrice" + /> + </view> + + <view class="add-fee-btn"> + <button class="confirm-btn" @click="addCustomFee">娣诲姞璐圭敤</button> + </view> + </view> + + <!-- 宸叉坊鍔犵殑璐圭敤鍒楄〃 --> + <view class="added-fees-list" v-if="selectedAdditionalFees.length > 0"> + <view class="section-title">宸叉坊鍔犺垂鐢�</view> + <view + class="fee-item" + v-for="(fee, index) in selectedAdditionalFees" + :key="index" + > + <view class="fee-info"> + <view class="fee-name">{{ fee.name }}</view> + <view class="fee-price">楼{{ fee.price }} 脳 {{ fee.quantity }}</view> + </view> + <view class="fee-total">楼{{ (fee.price * fee.quantity).toFixed(2) }}</view> + </view> + </view> + + <view class="popup-footer"> + <button class="confirm-btn" @click="confirmAdditionalFees">纭畾</button> + </view> + </view> + </uni-popup> + </view> +</template> + +<script> + export default { + data() { + return { + task: { + id: 1, + taskNo: 'RW20230515001', + type: 'emergency', + vehicle: '绮12345', + startLocation: '骞垮窞甯傚ぉ娌冲尯XX璺�123鍙�', + endLocation: '骞垮窞甯傜櫧浜戝尯YY璺�456鍙�' + }, + baseAmount: 1000, // 鍩虹璐圭敤 + additionalAmount: 0, // 闄勫姞璐圭敤 + settlementAmount: '', // 缁撶畻閲戦 + remark: '', // 澶囨敞 + paymentMethods: ['鐜伴噾', '鏀粯瀹�', '寰俊', '鎸傚笎'], + selectedPaymentMethod: '', + showQRCode: false, + paymentStatus: 'pending', // pending, success + qrCodeImage: '/static/images/qrcode.png', // 浜岀淮鐮佸浘鐗囪矾寰� + additionalFeeTypes: [ + { name: '鎷呮灦璐�', price: 200 }, + { name: '绛夊緟璐�', price: 100 }, + { name: '鍠勫悗璐�', price: 150 }, + { name: '澶滈棿鏈嶅姟璐�', price: 300 }, + { name: '闀块�旇垂', price: 500 } + ], + selectedAdditionalFees: [], // 宸查�夋嫨鐨勯檮鍔犺垂鐢� + selectedFeeTypeName: '', // 閫変腑鐨勮垂鐢ㄧ被鍨嬪悕绉� + newFeePrice: '' // 鏂板璐圭敤浠锋牸 + } + }, + computed: { + totalAmount() { + return this.baseAmount + this.additionalAmount; + }, + canSave() { + // 鐜伴噾鍜屾寕甯愬彲浠ョ洿鎺ヤ繚瀛橈紝鍏朵粬鏀粯鏂瑰紡闇�瑕佹敮浠樻垚鍔熷悗鎵嶈兘淇濆瓨 + if (!this.settlementAmount || !this.selectedPaymentMethod) { + return false; + } + + if (this.selectedPaymentMethod === '鐜伴噾' || this.selectedPaymentMethod === '鎸傚笎') { + return true; + } + + // 鏀粯瀹濄�佸井淇$瓑闇�瑕佹敮浠樻垚鍔� + return this.paymentStatus === 'success'; + }, + // 鑾峰彇璐圭敤绫诲瀷鍚嶇О鏁扮粍 + additionalFeeTypeNames() { + return this.additionalFeeTypes.map(fee => fee.name); + } + }, + onLoad(options) { + // 瀹為檯椤圭洰涓繖閲屼細閫氳繃API鑾峰彇浠诲姟璇︽儏 + // const taskId = options.id; + // this.getTaskDetail(taskId); + }, + methods: { + getTaskTypeText(type) { + const typeMap = { + 'maintenance': '缁翠慨淇濆吇', + 'refuel': '鍔犳补', + 'inspection': '宸℃', + 'emergency': '鎬ユ晳杞繍', + 'welfare': '绂忕杞�' + } + return typeMap[type] || '鏈煡绫诲瀷' + }, + + onPaymentMethodChange(e) { + this.selectedPaymentMethod = this.paymentMethods[e.detail.value]; + + // 濡傛灉閫夋嫨鏀粯瀹濇垨寰俊锛屾樉绀轰簩缁寸爜 + if (this.selectedPaymentMethod === '鏀粯瀹�' || this.selectedPaymentMethod === '寰俊') { + this.showQRCode = true; + this.paymentStatus = 'pending'; + // 妯℃嫙鏀粯鐘舵�佹鏌� + this.checkPaymentStatus(); + } else { + this.showQRCode = false; + this.paymentStatus = 'pending'; + } + }, + + // 璐圭敤绫诲瀷閫夋嫨 + onFeeTypeChange(e) { + this.selectedFeeTypeName = this.additionalFeeTypeNames[e.detail.value]; + }, + + checkPaymentStatus() { + // 妯℃嫙鏀粯鐘舵�佹鏌ワ紝瀹為檯椤圭洰涓簲璇ラ�氳繃API杞妫�鏌ユ敮浠樼姸鎬� + setTimeout(() => { + // 妯℃嫙鏀粯鎴愬姛 + this.paymentStatus = 'success'; + }, 5000); + }, + + showAdditionalFees() { + this.$refs.additionalFeesPopup.open(); + }, + + closeAdditionalFeesPopup() { + this.$refs.additionalFeesPopup.close(); + }, + + // 娣诲姞鑷畾涔夎垂鐢� + addCustomFee() { + if (!this.selectedFeeTypeName) { + this.$modal.showToast('璇烽�夋嫨璐圭敤绫诲瀷'); + return; + } + + if (!this.newFeePrice || isNaN(this.newFeePrice) || parseFloat(this.newFeePrice) <= 0) { + this.$modal.showToast('璇疯緭鍏ユ湁鏁堢殑璐圭敤閲戦'); + return; + } + + // 鏌ユ壘閫変腑鐨勮垂鐢ㄧ被鍨嬩俊鎭� + const selectedFeeType = this.additionalFeeTypes.find(fee => fee.name === this.selectedFeeTypeName); + + // 妫�鏌ユ槸鍚﹀凡瀛樺湪鍚屽悕璐圭敤 + const existingFee = this.selectedAdditionalFees.find(fee => fee.name === this.selectedFeeTypeName); + if (existingFee) { + existingFee.quantity += 1; + } else { + this.selectedAdditionalFees.push({ + name: this.selectedFeeTypeName, + price: parseFloat(this.newFeePrice), + quantity: 1 + }); + } + + // 娓呯┖杈撳叆妗� + this.selectedFeeTypeName = ''; + this.newFeePrice = ''; + + this.calculateAdditionalAmount(); + this.$modal.showToast('璐圭敤娣诲姞鎴愬姛'); + }, + + calculateAdditionalAmount() { + this.additionalAmount = this.selectedAdditionalFees.reduce((total, fee) => { + return total + (fee.price * fee.quantity); + }, 0); + }, + + confirmAdditionalFees() { + this.calculateAdditionalAmount(); + this.closeAdditionalFeesPopup(); + }, + + saveSettlement() { + if (!this.settlementAmount) { + this.$modal.showToast('璇疯緭鍏ョ粨绠楅噾棰�'); + return; + } + + if (!this.selectedPaymentMethod) { + this.$modal.showToast('璇烽�夋嫨鏀粯鏂瑰紡'); + return; + } + + // 妫�鏌ョ粨绠楅噾棰濇槸鍚﹀悎鐞� + if (parseFloat(this.settlementAmount) > this.totalAmount) { + this.$modal.showToast('缁撶畻閲戦涓嶈兘澶т簬鎬昏垂鐢�'); + return; + } + + this.$modal.confirm('纭畾瑕佷繚瀛樼粨绠椾俊鎭悧锛�').then(() => { + // 杩欓噷搴旇璋冪敤API淇濆瓨缁撶畻淇℃伅 + console.log('缁撶畻淇℃伅:', { + taskId: this.task.id, + baseAmount: this.baseAmount, + additionalAmount: this.additionalAmount, + totalAmount: this.totalAmount, + settlementAmount: this.settlementAmount, + paymentMethod: this.selectedPaymentMethod, + remark: this.remark, + additionalFees: this.selectedAdditionalFees + }); + + this.$modal.showToast('缁撶畻淇℃伅淇濆瓨鎴愬姛'); + // 杩斿洖浠诲姟鍒楄〃 + this.$tab.navigateBack(); + }).catch(() => { + // 鍙栨秷鎿嶄綔 + }); + } + } + } +</script> + +<style lang="scss"> + .settlement-container { + padding: 20rpx; + background-color: #f5f5f5; + height: 100vh; + display: flex; + flex-direction: column; + // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 + ::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; + } + + // Firefox婊氬姩鏉¢殣钘� + * { + scrollbar-width: none; /* Firefox */ + } + + // IE/Edge婊氬姩鏉¢殣钘� + * { + -ms-overflow-style: none; /* IE 10+ */ + } + } + + .settlement-header { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + flex-shrink: 0; + + .header-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + text-align: center; + } + } + + .settlement-content { + flex: 1; + + .task-info-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .info-item { + display: flex; + margin-bottom: 20rpx; + padding-bottom: 20rpx; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; + } + + .label { + font-size: 28rpx; + color: #666; + margin-right: 20rpx; + white-space: nowrap; + width: 150rpx; + } + + .value { + font-size: 28rpx; + flex: 1; + word-break: break-all; + } + } + } + + .amount-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .section-title { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 30rpx; + color: #333; + } + + .amount-item { + display: flex; + justify-content: space-between; + margin-bottom: 20rpx; + padding-bottom: 20rpx; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; + } + + &.additional-fees { + .value { + color: #007AFF; + } + } + + &.total-amount { + .label { + font-weight: bold; + } + + .value.total { + font-weight: bold; + font-size: 32rpx; + color: #e54d42; + } + } + + .label { + font-size: 28rpx; + color: #333; + } + + .value { + font-size: 28rpx; + color: #333; + } + } + } + + .settlement-form { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + + .form-item { + margin-bottom: 40rpx; + + &:last-child { + margin-bottom: 0; + } + + .form-label { + font-size: 28rpx; + margin-bottom: 15rpx; + color: #333; + } + + .form-input { + height: 70rpx; + padding: 0 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + + &.picker-input { + display: flex; + align-items: center; + justify-content: space-between; + } + } + + .form-textarea { + width: 100%; + min-height: 150rpx; + padding: 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + resize: none; + } + } + } + + .qr-code-section { + background-color: white; + border-radius: 15rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + text-align: center; + + .section-title { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 30rpx; + color: #333; + } + + .qr-code-container { + margin-bottom: 30rpx; + + .qr-code { + width: 300rpx; + height: 300rpx; + margin: 0 auto 20rpx; + } + + .qr-tip { + font-size: 26rpx; + color: #666; + } + } + + .payment-status { + .status-pending { + font-size: 28rpx; + color: #ff9900; + } + + .status-success { + font-size: 28rpx; + color: #4cd964; + display: flex; + align-items: center; + justify-content: center; + } + } + } + } + + .action-section { + padding: 20rpx 0; + flex-shrink: 0; + + .submit-btn { + width: 80%; + height: 80rpx; + background-color: #007AFF; + color: white; + border-radius: 10rpx; + font-size: 32rpx; + margin: 0 auto; + display: block; + + &[disabled] { + background-color: #ccc; + } + } + } + + .popup-content { + background-color: white; + border-top-left-radius: 20rpx; + border-top-right-radius: 20rpx; + padding: 30rpx; + max-height: 80vh; + + .popup-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 30rpx; + padding-bottom: 20rpx; + border-bottom: 1rpx solid #f0f0f0; + + .header-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + } + + .close-btn { + padding: 10rpx; + } + } + + .simple-fee-section { + padding: 20rpx 0; + border-bottom: 1rpx solid #f0f0f0; + margin-bottom: 20rpx; + + .form-item { + margin-bottom: 30rpx; + + &:last-child { + margin-bottom: 0; + } + + .form-label { + font-size: 28rpx; + margin-bottom: 15rpx; + color: #333; + } + + .form-input { + height: 70rpx; + padding: 0 20rpx; + border: 1rpx solid #eee; + border-radius: 10rpx; + font-size: 28rpx; + + &.picker-input { + display: flex; + align-items: center; + justify-content: space-between; + } + } + } + + .add-fee-btn { + margin-top: 20rpx; + + .confirm-btn { + width: 100%; + height: 70rpx; + background-color: #007AFF; + color: white; + border-radius: 10rpx; + font-size: 28rpx; + } + } + } + + .added-fees-list { + margin-bottom: 30rpx; + + .section-title { + font-size: 32rpx; + font-weight: bold; + margin-bottom: 20rpx; + color: #333; + } + + .fee-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20rpx 0; + border-bottom: 1rpx solid #f0f0f0; + + &:last-child { + border-bottom: none; + } + + .fee-info { + .fee-name { + font-size: 28rpx; + color: #333; + margin-bottom: 10rpx; + } + + .fee-price { + font-size: 26rpx; + color: #666; + } + } + + .fee-total { + font-size: 28rpx; + font-weight: bold; + color: #e54d42; + } + } + } + + .popup-footer { + .confirm-btn { + width: 100%; + height: 80rpx; + background-color: #007AFF; + color: white; + border-radius: 10rpx; + font-size: 32rpx; + } + } + } +</style> \ No newline at end of file diff --git a/app/plugins/modal.js b/app/plugins/modal.js index 99b2215..fa5b4a1 100644 --- a/app/plugins/modal.js +++ b/app/plugins/modal.js @@ -48,6 +48,26 @@ }) }) }, + // 杈撳叆妗� + prompt(content, defaultValue) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: '绯荤粺鎻愮ず', + content: content, + editable: true, + placeholderText: defaultValue || '', + cancelText: '鍙栨秷', + confirmText: '纭畾', + success: function(res) { + if (res.confirm) { + resolve(res.content) + } else { + reject() + } + } + }) + }) + }, // 鎻愮ず淇℃伅 showToast(option) { if (typeof option === "object") { diff --git a/app/static/icons/README.md b/app/static/icons/README.md new file mode 100644 index 0000000..17316a0 --- /dev/null +++ b/app/static/icons/README.md @@ -0,0 +1,23 @@ +# 鍥炬爣璧勬簮 + +姝ょ洰褰曠敤浜庡瓨鏀惧簲鐢ㄦ墍闇�鐨勫浘鏍囪祫婧愩�� + +## 闇�瑕佺殑鍥炬爣 + +### TabBar 鍥炬爣 +- `home.png` / `home-active.png` - 棣栭〉鍥炬爣 +- `tasks.png` / `tasks-active.png` - 浠诲姟鍥炬爣 +- `create.png` / `create-active.png` - 鍒涘缓鍥炬爣 +- `messages.png` / `messages-active.png` - 娑堟伅鍥炬爣 +- `profile.png` / `profile-active.png` - 涓汉涓績鍥炬爣 + +## 鍥炬爣瑙勬牸 + +- 灏哄: 81px * 81px +- 鏍煎紡: PNG +- 鑳屾櫙: 閫忔槑 +- 棰滆壊: 鏅�氱姸鎬� #666666锛屾縺娲荤姸鎬� #030213 + +## 浣跨敤璇存槑 + +鍥炬爣鏂囦欢闇�瑕佹斁鍦ㄦ鐩綍涓嬶紝骞跺湪 `src/app.config.ts` 涓纭厤缃矾寰勩�� diff --git a/app/static/icons/create-active.png b/app/static/icons/create-active.png new file mode 100644 index 0000000..32a454d --- /dev/null +++ b/app/static/icons/create-active.png Binary files differ diff --git a/app/static/icons/create-active.svg b/app/static/icons/create-active.svg new file mode 100644 index 0000000..4118dcf --- /dev/null +++ b/app/static/icons/create-active.svg @@ -0,0 +1,4 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <circle cx="40.5" cy="40.5" r="33.75" fill="#030213"/> + <path d="M40.5 20.25V60.75M20.25 40.5H60.75" stroke="white" stroke-width="4" stroke-linecap="round"/> +</svg> diff --git a/app/static/icons/create.png b/app/static/icons/create.png new file mode 100644 index 0000000..32a454d --- /dev/null +++ b/app/static/icons/create.png Binary files differ diff --git a/app/static/icons/create.svg b/app/static/icons/create.svg new file mode 100644 index 0000000..f719ee7 --- /dev/null +++ b/app/static/icons/create.svg @@ -0,0 +1,4 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <circle cx="40.5" cy="40.5" r="33.75" fill="#666666"/> + <path d="M40.5 20.25V60.75M20.25 40.5H60.75" stroke="white" stroke-width="4" stroke-linecap="round"/> +</svg> diff --git a/app/static/icons/home-active.png b/app/static/icons/home-active.png new file mode 100644 index 0000000..e2502d9 --- /dev/null +++ b/app/static/icons/home-active.png Binary files differ diff --git a/app/static/icons/home-active.svg b/app/static/icons/home-active.svg new file mode 100644 index 0000000..d315bbc --- /dev/null +++ b/app/static/icons/home-active.svg @@ -0,0 +1,3 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M40.5 6.75L70.875 27.5625V67.5H54V40.5H27V67.5H10.125V27.5625L40.5 6.75Z" fill="#030213"/> +</svg> diff --git a/app/static/icons/home.png b/app/static/icons/home.png new file mode 100644 index 0000000..a46f990 --- /dev/null +++ b/app/static/icons/home.png Binary files differ diff --git a/app/static/icons/home.svg b/app/static/icons/home.svg new file mode 100644 index 0000000..0efe59d --- /dev/null +++ b/app/static/icons/home.svg @@ -0,0 +1,3 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M40.5 6.75L70.875 27.5625V67.5H54V40.5H27V67.5H10.125V27.5625L40.5 6.75Z" fill="#666666"/> +</svg> diff --git a/app/static/icons/messages-active.png b/app/static/icons/messages-active.png new file mode 100644 index 0000000..17b6932 --- /dev/null +++ b/app/static/icons/messages-active.png Binary files differ diff --git a/app/static/icons/messages-active.svg b/app/static/icons/messages-active.svg new file mode 100644 index 0000000..91599e9 --- /dev/null +++ b/app/static/icons/messages-active.svg @@ -0,0 +1,5 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M6.75 20.25H74.25C75.9069 20.25 77.25 21.5931 77.25 23.25V57.75C77.25 59.4069 75.9069 60.75 74.25 60.75H20.25L6.75 74.25V20.25Z" fill="#030213"/> + <path d="M20.25 33.75H60.75V40.5H20.25V33.75Z" fill="white"/> + <path d="M20.25 47.25H47.25V54H20.25V47.25Z" fill="white"/> +</svg> diff --git a/app/static/icons/messages.png b/app/static/icons/messages.png new file mode 100644 index 0000000..a7f70f6 --- /dev/null +++ b/app/static/icons/messages.png Binary files differ diff --git a/app/static/icons/messages.svg b/app/static/icons/messages.svg new file mode 100644 index 0000000..a7f081c --- /dev/null +++ b/app/static/icons/messages.svg @@ -0,0 +1,5 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M6.75 20.25H74.25C75.9069 20.25 77.25 21.5931 77.25 23.25V57.75C77.25 59.4069 75.9069 60.75 74.25 60.75H20.25L6.75 74.25V20.25Z" fill="#666666"/> + <path d="M20.25 33.75H60.75V40.5H20.25V33.75Z" fill="white"/> + <path d="M20.25 47.25H47.25V54H20.25V47.25Z" fill="white"/> +</svg> diff --git a/app/static/icons/profile-active.png b/app/static/icons/profile-active.png new file mode 100644 index 0000000..dd2ed3b --- /dev/null +++ b/app/static/icons/profile-active.png Binary files differ diff --git a/app/static/icons/profile-active.svg b/app/static/icons/profile-active.svg new file mode 100644 index 0000000..46aab33 --- /dev/null +++ b/app/static/icons/profile-active.svg @@ -0,0 +1,4 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <circle cx="40.5" cy="27" r="13.5" fill="#030213"/> + <path d="M13.5 67.5C13.5 54.5 25.5 44.25 40.5 44.25C55.5 44.25 67.5 54.5 67.5 67.5V74.25H13.5V67.5Z" fill="#030213"/> +</svg> diff --git a/app/static/icons/profile.png b/app/static/icons/profile.png new file mode 100644 index 0000000..a88e85a --- /dev/null +++ b/app/static/icons/profile.png Binary files differ diff --git a/app/static/icons/profile.svg b/app/static/icons/profile.svg new file mode 100644 index 0000000..8c5cb00 --- /dev/null +++ b/app/static/icons/profile.svg @@ -0,0 +1,4 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <circle cx="40.5" cy="27" r="13.5" fill="#666666"/> + <path d="M13.5 67.5C13.5 54.5 25.5 44.25 40.5 44.25C55.5 44.25 67.5 54.5 67.5 67.5V74.25H13.5V67.5Z" fill="#666666"/> +</svg> diff --git a/app/static/icons/tasks-active.png b/app/static/icons/tasks-active.png new file mode 100644 index 0000000..57e4ae6 --- /dev/null +++ b/app/static/icons/tasks-active.png Binary files differ diff --git a/app/static/icons/tasks-active.svg b/app/static/icons/tasks-active.svg new file mode 100644 index 0000000..bb5b43d --- /dev/null +++ b/app/static/icons/tasks-active.svg @@ -0,0 +1,6 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M20.25 6.75H60.75C62.4069 6.75 63.75 8.09315 63.75 9.75V71.25C63.75 72.9069 62.4069 74.25 60.75 74.25H20.25C18.5931 74.25 17.25 72.9069 17.25 71.25V9.75C17.25 8.09315 18.5931 6.75 20.25 6.75Z" fill="#030213"/> + <path d="M27 20.25H54V27H27V20.25Z" fill="white"/> + <path d="M27 33.75H54V40.5H27V33.75Z" fill="white"/> + <path d="M27 47.25H40.5V54H27V47.25Z" fill="white"/> +</svg> diff --git a/app/static/icons/tasks.png b/app/static/icons/tasks.png new file mode 100644 index 0000000..26a3a40 --- /dev/null +++ b/app/static/icons/tasks.png Binary files differ diff --git a/app/static/icons/tasks.svg b/app/static/icons/tasks.svg new file mode 100644 index 0000000..1bca6b1 --- /dev/null +++ b/app/static/icons/tasks.svg @@ -0,0 +1,6 @@ +<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M20.25 6.75H60.75C62.4069 6.75 63.75 8.09315 63.75 9.75V71.25C63.75 72.9069 62.4069 74.25 60.75 74.25H20.25C18.5931 74.25 17.25 72.9069 17.25 71.25V9.75C17.25 8.09315 18.5931 6.75 20.25 6.75Z" fill="#666666"/> + <path d="M27 20.25H54V27H27V20.25Z" fill="white"/> + <path d="M27 33.75H54V40.5H27V33.75Z" fill="white"/> + <path d="M27 47.25H40.5V54H27V47.25Z" fill="white"/> +</svg> diff --git a/app/static/images/qrcode.png b/app/static/images/qrcode.png new file mode 100644 index 0000000..825b074 --- /dev/null +++ b/app/static/images/qrcode.png @@ -0,0 +1,222 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 200 200"> + <rect width="200" height="200" fill="#ffffff"/> + <g fill="#000000"> + <rect x="10" y="10" width="10" height="10"/> + <rect x="20" y="10" width="10" height="10"/> + <rect x="30" y="10" width="10" height="10"/> + <rect x="40" y="10" width="10" height="10"/> + <rect x="50" y="10" width="10" height="10"/> + <rect x="60" y="10" width="10" height="10"/> + <rect x="70" y="10" width="10" height="10"/> + <rect x="80" y="10" width="10" height="10"/> + <rect x="90" y="10" width="10" height="10"/> + <rect x="100" y="10" width="10" height="10"/> + <rect x="110" y="10" width="10" height="10"/> + <rect x="120" y="10" width="10" height="10"/> + <rect x="130" y="10" width="10" height="10"/> + <rect x="140" y="10" width="10" height="10"/> + <rect x="150" y="10" width="10" height="10"/> + <rect x="160" y="10" width="10" height="10"/> + <rect x="170" y="10" width="10" height="10"/> + <rect x="180" y="10" width="10" height="10"/> + <rect x="10" y="20" width="10" height="10"/> + <rect x="40" y="20" width="10" height="10"/> + <rect x="60" y="20" width="10" height="10"/> + <rect x="80" y="20" width="10" height="10"/> + <rect x="100" y="20" width="10" height="10"/> + <rect x="120" y="20" width="10" height="10"/> + <rect x="140" y="20" width="10" height="10"/> + <rect x="160" y="20" width="10" height="10"/> + <rect x="180" y="20" width="10" height="10"/> + <rect x="10" y="30" width="10" height="10"/> + <rect x="20" y="30" width="10" height="10"/> + <rect x="30" y="30" width="10" height="10"/> + <rect x="40" y="30" width="10" height="10"/> + <rect x="60" y="30" width="10" height="10"/> + <rect x="80" y="30" width="10" height="10"/> + <rect x="100" y="30" width="10" height="10"/> + <rect x="120" y="30" width="10" height="10"/> + <rect x="140" y="30" width="10" height="10"/> + <rect x="150" y="30" width="10" height="10"/> + <rect x="160" y="30" width="10" height="10"/> + <rect x="180" y="30" width="10" height="10"/> + <rect x="10" y="40" width="10" height="10"/> + <rect x="20" y="40" width="10" height="10"/> + <rect x="30" y="40" width="10" height="10"/> + <rect x="40" y="40" width="10" height="10"/> + <rect x="60" y="40" width="10" height="10"/> + <rect x="80" y="40" width="10" height="10"/> + <rect x="100" y="40" width="10" height="10"/> + <rect x="120" y="40" width="10" height="10"/> + <rect x="140" y="40" width="10" height="10"/> + <rect x="150" y="40" width="10" height="10"/> + <rect x="160" y="40" width="10" height="10"/> + <rect x="180" y="40" width="10" height="10"/> + <rect x="10" y="50" width="10" height="10"/> + <rect x="40" y="50" width="10" height="10"/> + <rect x="60" y="50" width="10" height="10"/> + <rect x="80" y="50" width="10" height="10"/> + <rect x="100" y="50" width="10" height="10"/> + <rect x="120" y="50" width="10" height="10"/> + <rect x="140" y="50" width="10" height="10"/> + <rect x="160" y="50" width="10" height="10"/> + <rect x="180" y="50" width="10" height="10"/> + <rect x="10" y="60" width="10" height="10"/> + <rect x="20" y="60" width="10" height="10"/> + <rect x="30" y="60" width="10" height="10"/> + <rect x="40" y="60" width="10" height="10"/> + <rect x="50" y="60" width="10" height="10"/> + <rect x="60" y="60" width="10" height="10"/> + <rect x="70" y="60" width="10" height="10"/> + <rect x="80" y="60" width="10" height="10"/> + <rect x="90" y="60" width="10" height="10"/> + <rect x="100" y="60" width="10" height="10"/> + <rect x="110" y="60" width="10" height="10"/> + <rect x="120" y="60" width="10" height="10"/> + <rect x="130" y="60" width="10" height="10"/> + <rect x="140" y="60" width="10" height="10"/> + <rect x="150" y="60" width="10" height="10"/> + <rect x="160" y="60" width="10" height="10"/> + <rect x="170" y="60" width="10" height="10"/> + <rect x="180" y="60" width="10" height="10"/> + <rect x="40" y="70" width="10" height="10"/> + <rect x="80" y="70" width="10" height="10"/> + <rect x="120" y="70" width="10" height="10"/> + <rect x="160" y="70" width="10" height="10"/> + <rect x="10" y="80" width="10" height="10"/> + <rect x="20" y="80" width="10" height="10"/> + <rect x="30" y="80" width="10" height="10"/> + <rect x="40" y="80" width="10" height="10"/> + <rect x="50" y="80" width="10" height="10"/> + <rect x="60" y="80" width="10" height="10"/> + <rect x="70" y="80" width="10" height="10"/> + <rect x="80" y="80" width="10" height="10"/> + <rect x="90" y="80" width="10" height="10"/> + <rect x="100" y="80" width="10" height="10"/> + <rect x="110" y="80" width="10" height="10"/> + <rect x="120" y="80" width="10" height="10"/> + <rect x="130" y="80" width="10" height="10"/> + <rect x="140" y="80" width="10" height="10"/> + <rect x="150" y="80" width="10" height="10"/> + <rect x="160" y="80" width="10" height="10"/> + <rect x="170" y="80" width="10" height="10"/> + <rect x="180" y="80" width="10" height="10"/> + <rect x="20" y="90" width="10" height="10"/> + <rect x="40" y="90" width="10" height="10"/> + <rect x="60" y="90" width="10" height="10"/> + <rect x="80" y="90" width="10" height="10"/> + <rect x="100" y="90" width="10" height="10"/> + <rect x="120" y="90" width="10" height="10"/> + <rect x="140" y="90" width="10" height="10"/> + <rect x="160" y="90" width="10" height="10"/> + <rect x="180" y="90" width="10" height="10"/> + <rect x="10" y="100" width="10" height="10"/> + <rect x="20" y="100" width="10" height="10"/> + <rect x="30" y="100" width="10" height="10"/> + <rect x="40" y="100" width="10" height="10"/> + <rect x="60" y="100" width="10" height="10"/> + <rect x="80" y="100" width="10" height="10"/> + <rect x="100" y="100" width="10" height="10"/> + <rect x="120" y="100" width="10" height="10"/> + <rect x="140" y="100" width="10" height="10"/> + <rect x="150" y="100" width="10" height="10"/> + <rect x="160" y="100" width="10" height="10"/> + <rect x="180" y="100" width="10" height="10"/> + <rect x="10" y="110" width="10" height="10"/> + <rect x="40" y="110" width="10" height="10"/> + <rect x="60" y="110" width="10" height="10"/> + <rect x="80" y="110" width="10" height="10"/> + <rect x="100" y="110" width="10" height="10"/> + <rect x="120" y="110" width="10" height="10"/> + <rect x="140" y="110" width="10" height="10"/> + <rect x="160" y="110" width="10" height="10"/> + <rect x="180" y="110" width="10" height="10"/> + <rect x="10" y="120" width="10" height="10"/> + <rect x="20" y="120" width="10" height="10"/> + <rect x="30" y="120" width="10" height="10"/> + <rect x="40" y="120" width="10" height="10"/> + <rect x="60" y="120" width="10" height="10"/> + <rect x="80" y="120" width="10" height="10"/> + <rect x="100" y="120" width="10" height="10"/> + <rect x="120" y="120" width="10" height="10"/> + <rect x="140" y="120" width="10" height="10"/> + <rect x="150" y="120" width="10" height="10"/> + <rect x="160" y="120" width="10" height="10"/> + <rect x="180" y="120" width="10" height="10"/> + <rect x="10" y="130" width="10" height="10"/> + <rect x="20" y="130" width="10" height="10"/> + <rect x="30" y="130" width="10" height="10"/> + <rect x="40" y="130" width="10" height="10"/> + <rect x="60" y="130" width="10" height="10"/> + <rect x="80" y="130" width="10" height="10"/> + <rect x="100" y="130" width="10" height="10"/> + <rect x="120" y="130" width="10" height="10"/> + <rect x="140" y="130" width="10" height="10"/> + <rect x="150" y="130" width="10" height="10"/> + <rect x="160" y="130" width="10" height="10"/> + <rect x="180" y="130" width="10" height="10"/> + <rect x="10" y="140" width="10" height="10"/> + <rect x="40" y="140" width="10" height="10"/> + <rect x="60" y="140" width="10" height="10"/> + <rect x="80" y="140" width="10" height="10"/> + <rect x="100" y="140" width="10" height="10"/> + <rect x="120" y="140" width="10" height="10"/> + <rect x="140" y="140" width="10" height="10"/> + <rect x="160" y="140" width="10" height="10"/> + <rect x="180" y="140" width="10" height="10"/> + <rect x="10" y="150" width="10" height="10"/> + <rect x="20" y="150" width="10" height="10"/> + <rect x="30" y="150" width="10" height="10"/> + <rect x="40" y="150" width="10" height="10"/> + <rect x="50" y="150" width="10" height="10"/> + <rect x="60" y="150" width="10" height="10"/> + <rect x="70" y="150" width="10" height="10"/> + <rect x="80" y="150" width="10" height="10"/> + <rect x="90" y="150" width="10" height="10"/> + <rect x="100" y="150" width="10" height="10"/> + <rect x="110" y="150" width="10" height="10"/> + <rect x="120" y="150" width="10" height="10"/> + <rect x="130" y="150" width="10" height="10"/> + <rect x="140" y="150" width="10" height="10"/> + <rect x="150" y="150" width="10" height="10"/> + <rect x="160" y="150" width="10" height="10"/> + <rect x="170" y="150" width="10" height="10"/> + <rect x="180" y="150" width="10" height="10"/> + <rect x="40" y="160" width="10" height="10"/> + <rect x="80" y="160" width="10" height="10"/> + <rect x="120" y="160" width="10" height="10"/> + <rect x="160" y="160" width="10" height="10"/> + <rect x="10" y="170" width="10" height="10"/> + <rect x="20" y="170" width="10" height="10"/> + <rect x="30" y="170" width="10" height="10"/> + <rect x="40" y="170" width="10" height="10"/> + <rect x="50" y="170" width="10" height="10"/> + <rect x="60" y="170" width="10" height="10"/> + <rect x="70" y="170" width="10" height="10"/> + <rect x="80" y="170" width="10" height="10"/> + <rect x="90" y="170" width="10" height="10"/> + <rect x="100" y="170" width="10" height="10"/> + <rect x="110" y="170" width="10" height="10"/> + <rect x="120" y="170" width="10" height="10"/> + <rect x="130" y="170" width="10" height="10"/> + <rect x="140" y="170" width="10" height="10"/> + <rect x="150" y="170" width="10" height="10"/> + <rect x="160" y="170" width="10" height="10"/> + <rect x="170" y="170" width="10" height="10"/> + <rect x="180" y="170" width="10" height="10"/> + <rect x="10" y="180" width="10" height="10"/> + <rect x="40" y="180" width="10" height="10"/> + <rect x="60" y="180" width="10" height="10"/> + <rect x="80" y="180" width="10" height="10"/> + <rect x="100" y="180" width="10" height="10"/> + <rect x="120" y="180" width="10" height="10"/> + <rect x="140" y="180" width="10" height="10"/> + <rect x="160" y="180" width="10" height="10"/> + <rect x="180" y="180" width="10" height="10"/> + <rect x="60" y="190" width="10" height="10"/> + <rect x="100" y="190" width="10" height="10"/> + <rect x="140" y="190" width="10" height="10"/> + </g> + <text x="100" y="120" font-family="Arial" font-size="20" text-anchor="middle" fill="#000000">鏀粯浜岀淮鐮�</text> +</svg> \ No newline at end of file diff --git a/app/static/images/tabbar/add.png b/app/static/images/tabbar/add.png new file mode 100644 index 0000000..32ba169 --- /dev/null +++ b/app/static/images/tabbar/add.png @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#000000"/> + <path d="M12,7L12,17M7,12L17,12" stroke="white" stroke-width="2"/> +</svg> \ No newline at end of file diff --git a/app/static/images/tabbar/add_.png b/app/static/images/tabbar/add_.png new file mode 100644 index 0000000..d365396 --- /dev/null +++ b/app/static/images/tabbar/add_.png @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <circle cx="12" cy="12" r="10" fill="#007AFF"/> + <path d="M12,7L12,17M7,12L17,12" stroke="white" stroke-width="2"/> +</svg> \ No newline at end of file diff --git a/app/static/images/tabbar/message.png b/app/static/images/tabbar/message.png new file mode 100644 index 0000000..f415695 --- /dev/null +++ b/app/static/images/tabbar/message.png @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path d="M20,2H4A2,2 0 0,0 2,4V22L6,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M6,9H18V11H6M14,14H6V12H14M18,8H6V6H18" fill="#000000"/> +</svg> \ No newline at end of file diff --git a/app/static/images/tabbar/message_.png b/app/static/images/tabbar/message_.png new file mode 100644 index 0000000..5b214f7 --- /dev/null +++ b/app/static/images/tabbar/message_.png @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path d="M20,2H4A2,2 0 0,0 2,4V22L6,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M6,9H18V11H6M14,14H6V12H14M18,8H6V6H18" fill="#007AFF"/> +</svg> \ No newline at end of file diff --git a/app/static/images/tabbar/task.png b/app/static/images/tabbar/task.png new file mode 100644 index 0000000..6a07192 --- /dev/null +++ b/app/static/images/tabbar/task.png @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" fill="#000000"/> +</svg> \ No newline at end of file diff --git a/app/static/images/tabbar/task_.png b/app/static/images/tabbar/task_.png new file mode 100644 index 0000000..7b50c5e --- /dev/null +++ b/app/static/images/tabbar/task_.png @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" fill="#007AFF"/> +</svg> \ No newline at end of file diff --git a/app/static/images/wechat.png b/app/static/images/wechat.png new file mode 100644 index 0000000..c2f9288 --- /dev/null +++ b/app/static/images/wechat.png @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <rect width="24" height="24" fill="#07c160" rx="4"/> + <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.5 14.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm-9 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm9.5-5.5c-.55 0-1-.45-1-1 0-.55.45-1 1-1s1 .45 1 1-.45 1-1 1zm-10 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z" fill="white"/> +</svg> \ No newline at end of file diff --git a/app/static/scss/global.scss b/app/static/scss/global.scss index ac636bd..bf4092c 100644 --- a/app/static/scss/global.scss +++ b/app/static/scss/global.scss @@ -21,6 +21,37 @@ color: #aaa; } +// 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘 +::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; +} + +// Firefox婊氬姩鏉¢殣钘� +* { + scrollbar-width: none; /* Firefox */ +} + +// IE/Edge婊氬姩鏉¢殣钘� +* { + -ms-overflow-style: none; /* IE 10+ */ +} + +// 鍏ㄥ眬闅愯棌婊氬姩鏉℃牱寮� +scroll-view::-webkit-scrollbar { + display: none; + width: 0 !important; + height: 0 !important; + background: transparent; +} + +scroll-view { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ +} + .list-cell-arrow::before { content: ' '; height: 10px; @@ -87,4 +118,4 @@ color: #999; } } - } + } \ No newline at end of file diff --git a/app/store/modules/user.js b/app/store/modules/user.js index c1ec441..79e8b98 100644 --- a/app/store/modules/user.js +++ b/app/store/modules/user.js @@ -2,6 +2,7 @@ import storage from '@/utils/storage' import constant from '@/utils/constant' import { login, logout, getInfo } from '@/api/login' +import { wechatLogin } from '@/api/wechat' import { getToken, setToken, removeToken } from '@/utils/auth' const baseUrl = config.baseUrl @@ -55,6 +56,19 @@ }) }, + // 寰俊鐧诲綍 + WechatLogin({ commit }, wechatData) { + return new Promise((resolve, reject) => { + wechatLogin(wechatData).then(res => { + setToken(res.token) + commit('SET_TOKEN', res.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + // 鑾峰彇鐢ㄦ埛淇℃伅 GetInfo({ commit, state }) { return new Promise((resolve, reject) => { @@ -95,4 +109,4 @@ } } -export default user +export default user \ No newline at end of file -- Gitblit v1.9.1