tab1.page.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. import { Component, AfterViewInit } from '@angular/core';
  2. import { Router } from '@angular/router';
  3. import { ModalController, NavController, ToastController } from '@ionic/angular';
  4. import { HttpClient } from '@angular/common/http';
  5. import { Observable } from 'rxjs';
  6. import { map, catchError } from 'rxjs/operators';
  7. @Component({
  8. selector: 'app-tab1',
  9. templateUrl: 'tab1.page.html',
  10. styleUrls: ['tab1.page.scss']
  11. })
  12. export class Tab1Page implements AfterViewInit {
  13. doctors = [
  14. {
  15. avatar: '../../assets/images/doctor.png',
  16. name: '张医生',
  17. specialty: '心血管科'
  18. },
  19. {
  20. avatar: '../../assets/images/doctor.png',
  21. name: '李医生',
  22. specialty: '神经科'
  23. },
  24. {
  25. avatar: '../../assets/images/doctor.png',
  26. name: '王医生',
  27. specialty: '儿科'
  28. },
  29. {
  30. avatar: '../../assets/images/doctor.png',
  31. name: '赵医生',
  32. specialty: '外科'
  33. },
  34. {
  35. avatar: '../../assets/images/doctor.png',
  36. name: '陈医生',
  37. specialty: '内科'
  38. }
  39. ];
  40. // 功能按钮数据
  41. functionItems1 = [
  42. { label: '我的病历', icon: 'document-text', route: '/medical-records' },
  43. { label: '在线问诊', icon: 'chatbubbles', route: '/online-consultation' },
  44. { label: '健康档案', icon: 'person', route: '/health-profile' },
  45. { label: '预约挂号', icon: 'calendar', route: '/appointment' },
  46. { label: '健康资讯', icon: 'newspaper', route: '/health-news' }
  47. ];
  48. functionItems2 = [
  49. { label: '药品购买', icon: 'medkit', route: '/medicine-purchase' },
  50. { label: '体检套餐', icon: 'clipboard', route: '/checkup-packages' },
  51. { label: '专家讲座', icon: 'podium', route: '/expert-lectures' },
  52. { label: '远程医疗', icon: 'videocam', route: '/telemedicine' },
  53. { label: '健康社区', icon: 'people', route: '/health-community' }
  54. ];
  55. currentIndex = 0;
  56. startX: number = 0; // 初始化 startX
  57. endX: number = 0; // 初始化 endX
  58. isDragging: boolean = false; // 标记是否正在拖动
  59. currentTranslate: number = 0; // 当前的平移值
  60. cardWidth = 216; // 每个卡片的宽度加上间距 (200 + 16)
  61. isCyclic: boolean = true;
  62. fileToUpload: File | null = null; // 是否启用循环滑动
  63. ngAfterViewInit() {
  64. this.updateCarousel(); // 确保初始状态正确
  65. this.calculateCardWidth(); // 动态计算卡片宽度
  66. }
  67. // 计算卡片宽度
  68. calculateCardWidth() {
  69. const container = document.getElementById('carousel');
  70. if (container && container.children.length > 0) {
  71. const firstCard = container.children[0] as HTMLElement;
  72. this.cardWidth = firstCard.offsetWidth + 16; // 加上间距
  73. }
  74. }
  75. // 更新轮播位置
  76. updateCarousel() {
  77. this.currentTranslate = -this.currentIndex * this.cardWidth;
  78. this.updateCarouselPosition();
  79. }
  80. // 更新轮播位置
  81. updateCarouselPosition() {
  82. const container = document.getElementById('carousel');
  83. if (container) {
  84. container.style.transform = `translateX(${this.currentTranslate}px)`;
  85. }
  86. }
  87. // 触摸开始
  88. onTouchStart(event: TouchEvent) {
  89. this.startX = event.touches[0].clientX;
  90. this.isDragging = true;
  91. }
  92. // 触摸移动
  93. onTouchMove(event: TouchEvent) {
  94. if (this.isDragging) {
  95. const touchX = event.touches[0].clientX;
  96. const deltaX = touchX - this.startX;
  97. this.currentTranslate = -this.currentIndex * this.cardWidth + deltaX; // 动态更新平移值
  98. // 限制 currentTranslate 的值
  99. const maxTranslate = -(this.doctors.length - 1) * this.cardWidth;
  100. this.currentTranslate = Math.max(Math.min(this.currentTranslate, 0), maxTranslate);
  101. this.updateCarouselPosition();
  102. }
  103. }
  104. // 触摸结束
  105. onTouchEnd(event: TouchEvent) {
  106. this.endX = event.changedTouches[0].clientX;
  107. this.isDragging = false;
  108. const swipeThreshold = 50; // 滑动阈值
  109. const deltaX = this.startX - this.endX;
  110. if (deltaX > swipeThreshold) {
  111. // 向左滑动
  112. this.nextSlide();
  113. } else if (deltaX < -swipeThreshold) {
  114. // 向右滑动
  115. this.prevSlide();
  116. } else {
  117. // 如果滑动距离不够,则恢复到原来的位置
  118. this.snapToNearestCard();
  119. }
  120. }
  121. // 上一张
  122. prevSlide() {
  123. if (this.isCyclic) {
  124. if (this.currentIndex === 0) {
  125. this.currentIndex = this.doctors.length - 1;
  126. } else {
  127. this.currentIndex--;
  128. }
  129. } else {
  130. if (this.currentIndex > 0) {
  131. this.currentIndex--;
  132. }
  133. }
  134. this.updateCarousel();
  135. }
  136. // 下一张
  137. nextSlide() {
  138. if (this.isCyclic) {
  139. if (this.currentIndex === this.doctors.length - 1) {
  140. this.currentIndex = 0;
  141. } else {
  142. this.currentIndex++;
  143. }
  144. } else {
  145. if (this.currentIndex < this.doctors.length - 1) {
  146. this.currentIndex++;
  147. }
  148. }
  149. this.updateCarousel();
  150. }
  151. // 快照到最近的卡片
  152. snapToNearestCard() {
  153. const cardIndex = Math.round(-this.currentTranslate / this.cardWidth);
  154. this.currentIndex = Math.max(0, Math.min(cardIndex, this.doctors.length - 1));
  155. this.updateCarousel();
  156. }
  157. // 在线咨询按钮点击事件
  158. onConsultNow() {
  159. console.log(`立即咨询`);
  160. this.router.navigate(['/consultation']);
  161. }
  162. // 在线咨询按钮点击事件
  163. onlineConsultNow(doctor: any) {
  164. console.log(`在线咨询: ${doctor.name}`);
  165. // 跳转到 ConsultationPage 并传递医生信息
  166. this.router.navigate(['/consultation'], { state: { doctor: doctor } });
  167. }
  168. // 导航到指定路由
  169. navigateTo(route: string) {
  170. this.router.navigate([route]);
  171. }
  172. // 发布求医信息
  173. handleClick() {
  174. const fileInput = document.getElementById('fileInput');
  175. if (fileInput) {
  176. fileInput.click();
  177. } else {
  178. console.error('File input element not found');
  179. }
  180. }
  181. publishHealthInfo(files: FileList) {
  182. if (files && files.length > 0) {
  183. const file = files[0];
  184. const allowedTypes = ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  185. 'image/jpeg', 'image/png', 'image/gif'];
  186. if (allowedTypes.includes(file.type)) {
  187. console.log('Selected file:', file.name);
  188. // 在这里可以添加上传文件的逻辑
  189. this.fileToUpload = file;
  190. // 在这里添加上传文件的逻辑
  191. this.uploadFile().then(() => this.navCtrl.navigateForward('/tabs/tab2'));
  192. } else {
  193. this.presentToast('仅支持 .doc, .docx, .jpg, .jpeg, .png, .gif 文件类型');
  194. }
  195. } else {
  196. console.log('No file selected');
  197. }
  198. }
  199. async presentToast(message: string) {
  200. const toast = await this.toastController.create({
  201. message: message,
  202. duration: 2000,
  203. position: 'bottom'
  204. });
  205. toast.present();
  206. }
  207. private async uploadFile(): Promise<void> {
  208. if (this.fileToUpload) {
  209. // 这里是模拟文件上传的过程,您可以替换为实际的上传逻辑。
  210. // 比如调用API进行文件上传,并处理响应。
  211. // 简单示例:
  212. // await this.http.post('your-upload-endpoint', this.fileToUpload).toPromise();
  213. return new Promise((resolve) => setTimeout(resolve, 1000)); // 模拟异步操作
  214. }
  215. }
  216. isLoginModalOpen = false; // 声明 isLoginModalOpen 属性
  217. user = {
  218. username: '',
  219. password: ''
  220. };
  221. constructor(
  222. private router: Router,
  223. private modalController: ModalController,
  224. private navCtrl: NavController,
  225. private http: HttpClient,
  226. private toastController: ToastController // 注入 ToastController
  227. ) {}
  228. openLoginModal() {
  229. this.isLoginModalOpen = true;
  230. console.log('打开登录/注册模态框');
  231. }
  232. closeLoginModal() {
  233. this.isLoginModalOpen = false;
  234. console.log('关闭登录/注册模态框');
  235. }
  236. onLoginModalDismissed(event: any) {
  237. this.isLoginModalOpen = false;
  238. console.log('登录/注册模态框已关闭');
  239. }
  240. onLoginFormSubmit(formValue: any) {
  241. // 处理登录逻辑
  242. console.log('登录表单提交:', formValue);
  243. // 发送登录请求
  244. this.loginUser(formValue.username, formValue.password)
  245. .subscribe(
  246. (response) => {
  247. console.log('登录成功:', response);
  248. // 这里可以处理登录成功的逻辑,例如跳转到主页
  249. this.closeLoginModal();
  250. },
  251. (error) => {
  252. console.error('登录失败:', error);
  253. // 这里可以处理登录失败的逻辑,例如显示错误消息
  254. this.closeLoginModal();
  255. }
  256. );
  257. }
  258. registerUser() {
  259. // 处理注册逻辑
  260. console.log('注册用户:', this.user);
  261. // 发送注册请求
  262. this.registerNewUser(this.user.username, this.user.password)
  263. .subscribe(
  264. (response) => {
  265. console.log('注册成功:', response);
  266. // 这里可以处理注册成功的逻辑,例如跳转到登录页面
  267. this.closeLoginModal();
  268. },
  269. (error) => {
  270. console.error('注册失败:', error);
  271. // 这里可以处理注册失败的逻辑,例如显示错误消息
  272. this.closeLoginModal();
  273. }
  274. );
  275. }
  276. private loginUser(username: string, password: string): Observable<any> {
  277. const loginUrl = 'YOUR_API_ENDPOINT/login'; // 替换为你的登录 API 端点
  278. return this.http.post(loginUrl, { username, password })
  279. .pipe(
  280. map(response => response),
  281. catchError(error => {
  282. throw error;
  283. })
  284. );
  285. }
  286. private registerNewUser(username: string, password: string): Observable<any> {
  287. const registerUrl = 'YOUR_API_ENDPOINT/register'; // 替换为你的注册 API 端点
  288. return this.http.post(registerUrl, { username, password })
  289. .pipe(
  290. map(response => response),
  291. catchError(error => {
  292. throw error;
  293. })
  294. );
  295. }
  296. // 新增方法:处理“点击了解更多”按钮点击事件
  297. onLearnMore() {
  298. // 跳转到详情页面
  299. this.navCtrl.navigateForward('/details');
  300. }
  301. }