瀏覽代碼

添加详情页面

yangg 1 月之前
父節點
當前提交
131396bf47

+ 7 - 0
pages.json

@@ -107,6 +107,13 @@
 				"navigationBarTitleText" : "",
 				"navigationStyle": "default"
 			}
+		},
+		{
+			"path" : "pages/job-detail/job-detail",
+			"style" : 
+			{
+				"navigationBarTitleText" : ""
+			}
 		}
 	],
 	

+ 38 - 0
pages/index/index.vue

@@ -7,10 +7,14 @@
 				<view v-for="(job, index) in jobList" :key="index" class="job-item"
 					:class="{'job-selected': selectedJobId === job.id}" @click="selectJob(job)">
 					<view class="job-name">{{job.title}}</view>
+					<!-- <view class="job-actions">
+						<button class="detail-btn" @click.stop="viewJobDetail(job)">查看详情</button>
+					</view> -->
 					<view class="job-details">
 						<text class="job-salary">{{job.publish_date}}</text>
 						<text class="job-location">{{job.location}}</text>
 					</view>
+					
 				</view>
 			</view>
 
@@ -550,6 +554,22 @@ import { apiBaseUrl } from '@/common/config.js';
 				this.genderIndex = e.detail.value;
 				const displayGender = this.genderOptions[this.genderIndex];
 				this.formData.gender = displayGender;
+			},
+			viewJobDetail(job) {
+				// 保存所选职位信息到本地存储
+				uni.setStorageSync('currentJobDetail', JSON.stringify(job));
+				
+				// 跳转到职位详情页面
+				uni.navigateTo({
+						url: '/pages/job-detail/job-detail',
+						fail: (err) => {
+							console.error('页面跳转失败:', err);
+							uni.showToast({
+								title: '页面跳转失败',
+								icon: 'none'
+							});
+						}
+					});
 			}
 		}
 	}
@@ -847,4 +867,22 @@ import { apiBaseUrl } from '@/common/config.js';
 		font-size: 24rpx;
 		color: #999;
 	}
+
+	.job-actions {
+		display: flex;
+		justify-content: flex-end;
+		margin-top: 15rpx;
+		margin-bottom: 15rpx;
+	}
+
+	.detail-btn {
+		background-color: #0052d9;
+		color: #fff;
+		font-size: 24rpx;
+		padding: 6rpx 20rpx;
+		border-radius: 30rpx;
+		line-height: 1.5;
+		margin: 0;
+		min-height: auto;
+	}
 </style>

+ 294 - 0
pages/job-detail/job-detail.vue

@@ -0,0 +1,294 @@
+<template>
+  <view class="job-detail-container">
+    <!-- 顶部信息区域 -->
+    <view class="job-header">
+      <view class="job-title">{{ jobDetail.title }}</view>
+      <view class="job-salary">{{ jobDetail.salary }}</view>
+      <view class="job-department">{{ jobDetail.department }}</view>
+      
+      <view class="job-requirements">
+        <view class="requirement-item">
+          <view class="dot"></view>
+          <text>{{ jobDetail.location }}</text>
+        </view>
+        <view class="requirement-item">
+          <view class="time-icon"></view>
+          <text>{{ jobDetail.experience }}</text>
+        </view>
+      </view>
+    </view>
+    
+    <!-- 工作地点区域 -->
+    <view class="section">
+      <view class="section-title">工作地点</view>
+      <view class="map-container">
+        <image class="map-image" src="/static/images/map.png" mode="aspectFill"></image>
+        <view class="map-time">预计14:32到达</view>
+        <view class="refresh-icon">
+          <text class="iconfont icon-refresh"></text>
+        </view>
+      </view>
+    </view>
+    
+    <!-- 福利待遇区域 -->
+    <view class="section">
+      <view class="section-title">福利待遇</view>
+      <view class="benefits-list">
+        <view class="benefit-tag" v-for="(benefit, index) in jobDetail.benefits" :key="index">{{ benefit }}</view>
+      </view>
+    </view>
+    
+    <!-- 岗位介绍区域 -->
+    <view class="section">
+      <view class="section-title">岗位介绍</view>
+      <view class="job-description">
+        <view class="description-subtitle">{{ jobDetail.description[0].subtitle }}</view>
+        <view class="description-content">
+          <view class="description-item" v-for="(item, index) in jobDetail.description[0].items" :key="index">
+            <view class="blue-dot"></view>
+            <text>{{ item }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+    
+    <!-- 右侧开始面试按钮 -->
+    <view class="interview-button" @click="startInterview">
+      <text>开始面试</text>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      jobDetail: {
+        title: '产品经理',
+        salary: '20k-30k/月',
+        department: '产品研发部 全职',
+        location: '浙江线',
+        experience: '5-8年',
+        benefits: ['五险一金', '节日福利', '股权激励'],
+        description: [
+          {
+            subtitle: '战略规划与执行',
+            items: [
+              '负责敏锐的行业热点感受性,密切追踪行业动态与趋势,为企业战略决策提供参考。',
+              '结心制定企业战略规划,将长期愿景转化为可操作的战略目标,并有效分解为各阶段具体任务。'
+            ]
+          }
+        ]
+      }
+    }
+  },
+  onLoad() {
+    // 尝试从本地存储获取职位详情
+    try {
+      const jobDetailStr = uni.getStorageSync('currentJobDetail');
+      if (jobDetailStr) {
+        const jobData = JSON.parse(jobDetailStr);
+        // 这里可以根据实际数据结构进行处理
+        // 如果后端返回的数据结构与页面需要的不一致,可以在这里进行转换
+        this.jobDetail = {
+          ...this.jobDetail,
+          title: jobData.title || this.jobDetail.title,
+          salary: jobData.salary || this.jobDetail.salary,
+          department: jobData.department || this.jobDetail.department,
+          location: jobData.location || this.jobDetail.location,
+          experience: jobData.experience || this.jobDetail.experience,
+          benefits: jobData.benefits || this.jobDetail.benefits,
+          description: jobData.description || this.jobDetail.description
+        };
+      }
+    } catch (e) {
+      console.error('获取职位详情失败:', e);
+    }
+  },
+  methods: {
+    startInterview() {
+      // 开始面试的逻辑
+      uni.navigateTo({
+        url: '/pages/camera/camera'
+      });
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.job-detail-container {
+  padding: 20rpx;
+  position: relative;
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
+
+.job-header {
+  padding: 20rpx 0;
+}
+
+.job-title {
+  font-size: 36rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 10rpx;
+}
+
+.job-salary {
+  font-size: 32rpx;
+  color: #ff6b00;
+  margin-bottom: 10rpx;
+}
+
+.job-department {
+  font-size: 28rpx;
+  color: #666;
+  margin-bottom: 20rpx;
+}
+
+.job-requirements {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20rpx;
+}
+
+.requirement-item {
+  display: flex;
+  align-items: center;
+  margin-right: 30rpx;
+  font-size: 26rpx;
+  color: #666;
+}
+
+.dot {
+  width: 16rpx;
+  height: 16rpx;
+  border-radius: 50%;
+  background-color: #0052d9;
+  margin-right: 10rpx;
+}
+
+.time-icon {
+  width: 26rpx;
+  height: 26rpx;
+  background-color: #999;
+  border-radius: 50%;
+  margin-right: 10rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 18rpx;
+  color: #fff;
+}
+
+.section {
+  margin-bottom: 30rpx;
+  background-color: #fff;
+  border-radius: 16rpx;
+  padding: 20rpx;
+}
+
+.section-title {
+  font-size: 32rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+}
+
+.map-container {
+  position: relative;
+  border-radius: 16rpx;
+  overflow: hidden;
+}
+
+.map-image {
+  width: 100%;
+  height: 300rpx;
+  border-radius: 16rpx;
+}
+
+.map-time {
+  position: absolute;
+  left: 20rpx;
+  bottom: 20rpx;
+  background-color: rgba(0, 0, 0, 0.6);
+  color: #fff;
+  font-size: 24rpx;
+  padding: 6rpx 12rpx;
+  border-radius: 6rpx;
+}
+
+.refresh-icon {
+  position: absolute;
+  right: 20rpx;
+  bottom: 20rpx;
+  width: 60rpx;
+  height: 60rpx;
+  background-color: #fff;
+  border-radius: 50%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.benefits-list {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.benefit-tag {
+  background-color: #f5f5f5;
+  color: #666;
+  font-size: 26rpx;
+  padding: 10rpx 20rpx;
+  border-radius: 6rpx;
+  margin-right: 20rpx;
+  margin-bottom: 20rpx;
+}
+
+.description-subtitle {
+  font-size: 28rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+}
+
+.description-content {
+  padding-left: 10rpx;
+}
+
+.description-item {
+  display: flex;
+  margin-bottom: 20rpx;
+}
+
+.blue-dot {
+  min-width: 16rpx;
+  height: 16rpx;
+  border-radius: 50%;
+  background-color: #0052d9;
+  margin-right: 10rpx;
+  margin-top: 12rpx;
+}
+
+.description-item text {
+  font-size: 26rpx;
+  color: #666;
+  line-height: 1.6;
+}
+
+.interview-button {
+  position: fixed;
+  right: 0;
+  top: 50%;
+  transform: translateY(-50%);
+  background-color: #0052d9;
+  color: #fff;
+  writing-mode: vertical-lr;
+  padding: 30rpx 20rpx;
+  font-size: 32rpx;
+  border-top-left-radius: 16rpx;
+  border-bottom-left-radius: 16rpx;
+}
+</style> 

+ 1 - 0
unpackage/dist/dev/mp-weixin/app.js

@@ -19,6 +19,7 @@ if (!Math) {
   "./pages/agreement/agreement.js";
   "./pages/test/test.js";
   "./pages/Personal/Personal.js";
+  "./pages/job-detail/job-detail.js";
 }
 const _sfc_main = {
   onLaunch: function() {

+ 2 - 1
unpackage/dist/dev/mp-weixin/app.json

@@ -15,7 +15,8 @@
     "pages/interview_success/interview_success",
     "pages/agreement/agreement",
     "pages/test/test",
-    "pages/Personal/Personal"
+    "pages/Personal/Personal",
+    "pages/job-detail/job-detail"
   ],
   "window": {
     "navigationBarTextStyle": "black",

+ 6 - 4
unpackage/dist/dev/mp-weixin/common/assets.js

@@ -1,5 +1,7 @@
 "use strict";
-const _imports_0$1 = "/static/login-image.png";
-const _imports_0 = "/static/avatar.png";
-exports._imports_0 = _imports_0$1;
-exports._imports_0$1 = _imports_0;
+const _imports_0$2 = "/static/login-image.png";
+const _imports_0$1 = "/static/avatar.png";
+const _imports_0 = "/static/images/map.png";
+exports._imports_0 = _imports_0$2;
+exports._imports_0$1 = _imports_0$1;
+exports._imports_0$2 = _imports_0;

+ 13 - 0
unpackage/dist/dev/mp-weixin/pages/index/index.js

@@ -401,6 +401,19 @@ const _sfc_main = {
       this.genderIndex = e.detail.value;
       const displayGender = this.genderOptions[this.genderIndex];
       this.formData.gender = displayGender;
+    },
+    viewJobDetail(job) {
+      common_vendor.index.setStorageSync("currentJobDetail", JSON.stringify(job));
+      common_vendor.index.navigateTo({
+        url: "/pages/job-detail/job-detail",
+        fail: (err) => {
+          console.error("页面跳转失败:", err);
+          common_vendor.index.showToast({
+            title: "页面跳转失败",
+            icon: "none"
+          });
+        }
+      });
     }
   }
 };

+ 16 - 0
unpackage/dist/dev/mp-weixin/pages/index/index.wxss

@@ -255,3 +255,19 @@ input {
 		font-size: 24rpx;
 		color: #999;
 }
+.job-actions {
+		display: flex;
+		justify-content: flex-end;
+		margin-top: 15rpx;
+		margin-bottom: 15rpx;
+}
+.detail-btn {
+		background-color: #0052d9;
+		color: #fff;
+		font-size: 24rpx;
+		padding: 6rpx 20rpx;
+		border-radius: 30rpx;
+		line-height: 1.5;
+		margin: 0;
+		min-height: auto;
+}

+ 79 - 0
unpackage/dist/dev/mp-weixin/pages/job-detail/job-detail.js

@@ -0,0 +1,79 @@
+"use strict";
+const common_vendor = require("../../common/vendor.js");
+const common_assets = require("../../common/assets.js");
+const _sfc_main = {
+  data() {
+    return {
+      jobDetail: {
+        title: "产品经理",
+        salary: "20k-30k/月",
+        department: "产品研发部 全职",
+        location: "浙江线",
+        experience: "5-8年",
+        benefits: ["五险一金", "节日福利", "股权激励"],
+        description: [
+          {
+            subtitle: "战略规划与执行",
+            items: [
+              "负责敏锐的行业热点感受性,密切追踪行业动态与趋势,为企业战略决策提供参考。",
+              "结心制定企业战略规划,将长期愿景转化为可操作的战略目标,并有效分解为各阶段具体任务。"
+            ]
+          }
+        ]
+      }
+    };
+  },
+  onLoad() {
+    try {
+      const jobDetailStr = common_vendor.index.getStorageSync("currentJobDetail");
+      if (jobDetailStr) {
+        const jobData = JSON.parse(jobDetailStr);
+        this.jobDetail = {
+          ...this.jobDetail,
+          title: jobData.title || this.jobDetail.title,
+          salary: jobData.salary || this.jobDetail.salary,
+          department: jobData.department || this.jobDetail.department,
+          location: jobData.location || this.jobDetail.location,
+          experience: jobData.experience || this.jobDetail.experience,
+          benefits: jobData.benefits || this.jobDetail.benefits,
+          description: jobData.description || this.jobDetail.description
+        };
+      }
+    } catch (e) {
+      console.error("获取职位详情失败:", e);
+    }
+  },
+  methods: {
+    startInterview() {
+      common_vendor.index.navigateTo({
+        url: "/pages/camera/camera"
+      });
+    }
+  }
+};
+function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
+  return {
+    a: common_vendor.t($data.jobDetail.title),
+    b: common_vendor.t($data.jobDetail.salary),
+    c: common_vendor.t($data.jobDetail.department),
+    d: common_vendor.t($data.jobDetail.location),
+    e: common_vendor.t($data.jobDetail.experience),
+    f: common_assets._imports_0$2,
+    g: common_vendor.f($data.jobDetail.benefits, (benefit, index, i0) => {
+      return {
+        a: common_vendor.t(benefit),
+        b: index
+      };
+    }),
+    h: common_vendor.t($data.jobDetail.description[0].subtitle),
+    i: common_vendor.f($data.jobDetail.description[0].items, (item, index, i0) => {
+      return {
+        a: common_vendor.t(item),
+        b: index
+      };
+    }),
+    j: common_vendor.o((...args) => $options.startInterview && $options.startInterview(...args))
+  };
+}
+const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-2bde8e2a"]]);
+wx.createPage(MiniProgramPage);

+ 4 - 0
unpackage/dist/dev/mp-weixin/pages/job-detail/job-detail.json

@@ -0,0 +1,4 @@
+{
+  "navigationBarTitleText": "",
+  "usingComponents": {}
+}

+ 1 - 0
unpackage/dist/dev/mp-weixin/pages/job-detail/job-detail.wxml

@@ -0,0 +1 @@
+<view class="job-detail-container data-v-2bde8e2a"><view class="job-header data-v-2bde8e2a"><view class="job-title data-v-2bde8e2a">{{a}}</view><view class="job-salary data-v-2bde8e2a">{{b}}</view><view class="job-department data-v-2bde8e2a">{{c}}</view><view class="job-requirements data-v-2bde8e2a"><view class="requirement-item data-v-2bde8e2a"><view class="dot data-v-2bde8e2a"></view><text class="data-v-2bde8e2a">{{d}}</text></view><view class="requirement-item data-v-2bde8e2a"><view class="time-icon data-v-2bde8e2a"></view><text class="data-v-2bde8e2a">{{e}}</text></view></view></view><view class="section data-v-2bde8e2a"><view class="section-title data-v-2bde8e2a">工作地点</view><view class="map-container data-v-2bde8e2a"><image class="map-image data-v-2bde8e2a" src="{{f}}" mode="aspectFill"></image><view class="map-time data-v-2bde8e2a">预计14:32到达</view><view class="refresh-icon data-v-2bde8e2a"><text class="iconfont icon-refresh data-v-2bde8e2a"></text></view></view></view><view class="section data-v-2bde8e2a"><view class="section-title data-v-2bde8e2a">福利待遇</view><view class="benefits-list data-v-2bde8e2a"><view wx:for="{{g}}" wx:for-item="benefit" wx:key="b" class="benefit-tag data-v-2bde8e2a">{{benefit.a}}</view></view></view><view class="section data-v-2bde8e2a"><view class="section-title data-v-2bde8e2a">岗位介绍</view><view class="job-description data-v-2bde8e2a"><view class="description-subtitle data-v-2bde8e2a">{{h}}</view><view class="description-content data-v-2bde8e2a"><view wx:for="{{i}}" wx:for-item="item" wx:key="b" class="description-item data-v-2bde8e2a"><view class="blue-dot data-v-2bde8e2a"></view><text class="data-v-2bde8e2a">{{item.a}}</text></view></view></view></view><view class="interview-button data-v-2bde8e2a" bindtap="{{j}}"><text class="data-v-2bde8e2a">开始面试</text></view></view>

+ 178 - 0
unpackage/dist/dev/mp-weixin/pages/job-detail/job-detail.wxss

@@ -0,0 +1,178 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+.job-detail-container.data-v-2bde8e2a {
+  padding: 20rpx;
+  position: relative;
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
+.job-header.data-v-2bde8e2a {
+  padding: 20rpx 0;
+}
+.job-title.data-v-2bde8e2a {
+  font-size: 36rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 10rpx;
+}
+.job-salary.data-v-2bde8e2a {
+  font-size: 32rpx;
+  color: #ff6b00;
+  margin-bottom: 10rpx;
+}
+.job-department.data-v-2bde8e2a {
+  font-size: 28rpx;
+  color: #666;
+  margin-bottom: 20rpx;
+}
+.job-requirements.data-v-2bde8e2a {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20rpx;
+}
+.requirement-item.data-v-2bde8e2a {
+  display: flex;
+  align-items: center;
+  margin-right: 30rpx;
+  font-size: 26rpx;
+  color: #666;
+}
+.dot.data-v-2bde8e2a {
+  width: 16rpx;
+  height: 16rpx;
+  border-radius: 50%;
+  background-color: #0052d9;
+  margin-right: 10rpx;
+}
+.time-icon.data-v-2bde8e2a {
+  width: 26rpx;
+  height: 26rpx;
+  background-color: #999;
+  border-radius: 50%;
+  margin-right: 10rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 18rpx;
+  color: #fff;
+}
+.section.data-v-2bde8e2a {
+  margin-bottom: 30rpx;
+  background-color: #fff;
+  border-radius: 16rpx;
+  padding: 20rpx;
+}
+.section-title.data-v-2bde8e2a {
+  font-size: 32rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+}
+.map-container.data-v-2bde8e2a {
+  position: relative;
+  border-radius: 16rpx;
+  overflow: hidden;
+}
+.map-image.data-v-2bde8e2a {
+  width: 100%;
+  height: 300rpx;
+  border-radius: 16rpx;
+}
+.map-time.data-v-2bde8e2a {
+  position: absolute;
+  left: 20rpx;
+  bottom: 20rpx;
+  background-color: rgba(0, 0, 0, 0.6);
+  color: #fff;
+  font-size: 24rpx;
+  padding: 6rpx 12rpx;
+  border-radius: 6rpx;
+}
+.refresh-icon.data-v-2bde8e2a {
+  position: absolute;
+  right: 20rpx;
+  bottom: 20rpx;
+  width: 60rpx;
+  height: 60rpx;
+  background-color: #fff;
+  border-radius: 50%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.benefits-list.data-v-2bde8e2a {
+  display: flex;
+  flex-wrap: wrap;
+}
+.benefit-tag.data-v-2bde8e2a {
+  background-color: #f5f5f5;
+  color: #666;
+  font-size: 26rpx;
+  padding: 10rpx 20rpx;
+  border-radius: 6rpx;
+  margin-right: 20rpx;
+  margin-bottom: 20rpx;
+}
+.description-subtitle.data-v-2bde8e2a {
+  font-size: 28rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+}
+.description-content.data-v-2bde8e2a {
+  padding-left: 10rpx;
+}
+.description-item.data-v-2bde8e2a {
+  display: flex;
+  margin-bottom: 20rpx;
+}
+.blue-dot.data-v-2bde8e2a {
+  min-width: 16rpx;
+  height: 16rpx;
+  border-radius: 50%;
+  background-color: #0052d9;
+  margin-right: 10rpx;
+  margin-top: 12rpx;
+}
+.description-item text.data-v-2bde8e2a {
+  font-size: 26rpx;
+  color: #666;
+  line-height: 1.6;
+}
+.interview-button.data-v-2bde8e2a {
+  position: fixed;
+  right: 0;
+  top: 50%;
+  transform: translateY(-50%);
+  background-color: #0052d9;
+  color: #fff;
+  -webkit-writing-mode: vertical-lr;
+          writing-mode: vertical-lr;
+  padding: 30rpx 20rpx;
+  font-size: 32rpx;
+  border-top-left-radius: 16rpx;
+  border-bottom-left-radius: 16rpx;
+}

+ 1 - 1
unpackage/dist/dev/mp-weixin/project.config.json

@@ -8,7 +8,7 @@
     "urlCheck": false,
     "es6": true,
     "postcss": false,
-    "minified": true,
+    "minified": false,
     "newFeature": true,
     "bigPackageSizeSupport": true,
     "babelSetting": {