jobs.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. "use strict";
  2. const common_vendor = require("../../common/vendor.js");
  3. const common_assets = require("../../common/assets.js");
  4. const api_position = require("../../api/position.js");
  5. const api_dict = require("../../api/dict.js");
  6. if (!Math) {
  7. CustomTabbar();
  8. }
  9. const CustomTabbar = () => "../../components/custom-tabbar/custom-tabbar.js";
  10. const _sfc_main = {
  11. __name: "jobs",
  12. setup(__props) {
  13. const getStudentId = () => {
  14. const userInfo = common_vendor.index.getStorageSync("userInfo");
  15. if (!userInfo)
  16. return null;
  17. const id = userInfo.id || userInfo.studentId || null;
  18. common_vendor.index.__f__("log", "at pages/jobs/jobs.vue:172", "[getStudentId] userInfo:", JSON.stringify(userInfo), "=> id:", id);
  19. return id;
  20. };
  21. const statusBarHeight = common_vendor.ref(20);
  22. const titleBarMargin = common_vendor.ref(8);
  23. const menuButtonHeight = common_vendor.ref(32);
  24. const keyword = common_vendor.ref("");
  25. const sortType = common_vendor.ref("comprehensive");
  26. const currentJobType = common_vendor.ref(0);
  27. const jobTypeTabs = common_vendor.ref(["全部"]);
  28. const jobTypeValue = common_vendor.ref([""]);
  29. const loadDicts = () => {
  30. api_dict.getDicts("main_position_type").then((res) => {
  31. if (res.data && res.data.length > 0) {
  32. jobTypeTabs.value = ["全部岗位", ...res.data.map((item) => item.dictLabel)];
  33. jobTypeValue.value = ["", ...res.data.map((item) => item.dictValue)];
  34. } else {
  35. jobTypeTabs.value = ["全部岗位", "全职", "实习", "兼职"];
  36. jobTypeValue.value = ["", "0", "1", "2"];
  37. }
  38. fetchJobs(true);
  39. });
  40. };
  41. const jobList = common_vendor.ref([]);
  42. const pageNum = common_vendor.ref(1);
  43. const pageSize = common_vendor.ref(10);
  44. const hasMore = common_vendor.ref(true);
  45. const isLoading = common_vendor.ref(false);
  46. const showPopup = common_vendor.ref(false);
  47. const activeJob = common_vendor.ref(null);
  48. const openFeedbackPopup = (job) => {
  49. activeJob.value = job;
  50. showPopup.value = true;
  51. };
  52. const closePopup = () => {
  53. showPopup.value = false;
  54. };
  55. const handleDislikePosition = () => {
  56. if (!activeJob.value)
  57. return;
  58. const studentId = getStudentId();
  59. const job = activeJob.value;
  60. closePopup();
  61. jobList.value = jobList.value.filter((item) => item.id !== job.id);
  62. if (studentId) {
  63. api_position.dislikePosition(studentId, job.id).catch(() => {
  64. });
  65. }
  66. common_vendor.index.showToast({ title: "已屏蔽该岗位", icon: "none" });
  67. };
  68. const handleDislikeCompany = () => {
  69. if (!activeJob.value)
  70. return;
  71. const studentId = getStudentId();
  72. const job = activeJob.value;
  73. closePopup();
  74. jobList.value = jobList.value.filter((item) => item.rawTenantId !== job.rawTenantId);
  75. if (studentId && job.rawTenantId) {
  76. api_position.dislikeCompany(studentId, job.rawTenantId).catch(() => {
  77. });
  78. }
  79. common_vendor.index.showToast({ title: "已屏蔽该公司", icon: "none" });
  80. };
  81. const filterCriteria = common_vendor.ref({
  82. jobType: "",
  83. minSalary: 0,
  84. maxSalary: 50,
  85. experience: "",
  86. education: ""
  87. });
  88. const activeFilterCount = common_vendor.computed(() => {
  89. let count = 0;
  90. if (filterCriteria.value.experience)
  91. count++;
  92. if (filterCriteria.value.education)
  93. count++;
  94. if (filterCriteria.value.minSalary > 0 || filterCriteria.value.maxSalary < 50)
  95. count++;
  96. return count;
  97. });
  98. const fetchJobs = (reset = false) => {
  99. if (isLoading.value)
  100. return;
  101. if (reset) {
  102. pageNum.value = 1;
  103. hasMore.value = true;
  104. jobList.value = [];
  105. }
  106. if (!hasMore.value)
  107. return;
  108. isLoading.value = true;
  109. let postTypeStr = jobTypeValue.value[currentJobType.value] || "";
  110. if (!postTypeStr && filterCriteria.value.jobType) {
  111. postTypeStr = filterCriteria.value.jobType;
  112. }
  113. const params = {
  114. pageNum: pageNum.value,
  115. pageSize: pageSize.value,
  116. postName: keyword.value.trim(),
  117. postType: postTypeStr,
  118. schoolRequirement: filterCriteria.value.education || "",
  119. gradeRequirement: filterCriteria.value.experience || "",
  120. minSalary: filterCriteria.value.minSalary,
  121. maxSalary: filterCriteria.value.maxSalary
  122. };
  123. const currentStudentId = getStudentId();
  124. if (currentStudentId) {
  125. params.studentId = currentStudentId;
  126. }
  127. if (sortType.value === "latest") {
  128. params.orderByColumn = "createTime";
  129. params.isAsc = "desc";
  130. }
  131. api_position.getPositionList(params).then((res) => {
  132. if (res.code === 200) {
  133. const rows = res.rows || [];
  134. let formattedRows = rows.map((item) => ({
  135. id: item.id,
  136. title: item.postName,
  137. salaryText: item.salaryRange || "面议",
  138. // 使用后端翻译好的 Label 字段(如"全职"、"本科"、"3-5年"),而不是原始字典 value
  139. tags: [item.workCity, item.educationRequirementLabel || item.educationRequirement, item.gradeRequirementLabel || item.gradeRequirement].filter(Boolean),
  140. isUrgent: item.isUrgent === 1,
  141. count: item.recruitNum || 1,
  142. deadline: item.registrationEndDate ? item.registrationEndDate.split(" ")[0] : "长期有效",
  143. isExpiring: false,
  144. company: item.companyName || "平台推荐",
  145. rawTenantId: item.tenantId,
  146. // 保留原始 tenantId 用于屏蔽公司
  147. location: (item.workProvince || "") + (item.workCity ? "·" + item.workCity : ""),
  148. logo: item.companyAvatar || "/static/images/default-company.svg"
  149. }));
  150. jobList.value = reset ? formattedRows : [...jobList.value, ...formattedRows];
  151. if (jobList.value.length >= res.total || rows.length < pageSize.value) {
  152. hasMore.value = formattedRows.length >= pageSize.value;
  153. } else {
  154. pageNum.value++;
  155. }
  156. }
  157. }).finally(() => {
  158. isLoading.value = false;
  159. });
  160. };
  161. const loadMore = () => {
  162. fetchJobs(false);
  163. };
  164. const handleSearch = () => {
  165. fetchJobs(true);
  166. };
  167. const handleSearchConfirm = () => {
  168. if (keyword.value.trim()) {
  169. let history = common_vendor.index.getStorageSync("search_history");
  170. if (!history)
  171. history = [];
  172. else
  173. history = JSON.parse(history);
  174. history = history.filter((item) => item !== keyword.value.trim());
  175. history.unshift(keyword.value.trim());
  176. if (history.length > 10)
  177. history = history.slice(0, 10);
  178. common_vendor.index.setStorageSync("search_history", JSON.stringify(history));
  179. }
  180. fetchJobs(true);
  181. };
  182. common_vendor.watch([currentJobType, sortType], () => {
  183. fetchJobs(true);
  184. });
  185. const goToFilter = () => {
  186. common_vendor.index.navigateTo({
  187. url: "/pages/jobs/filter"
  188. });
  189. };
  190. const goToDetail = (item) => {
  191. common_vendor.index.navigateTo({
  192. url: "/pages/jobdetail/index?id=" + item.id
  193. });
  194. };
  195. const scrollTop = common_vendor.computed(() => {
  196. const gradientArea = titleBarMargin.value + menuButtonHeight.value + 8;
  197. const whiteArea = 82;
  198. return statusBarHeight.value + gradientArea + whiteArea;
  199. });
  200. common_vendor.onPullDownRefresh(async () => {
  201. await fetchJobs(true);
  202. common_vendor.index.stopPullDownRefresh();
  203. });
  204. common_vendor.onMounted(() => {
  205. common_vendor.index.$on("updateFilters", (params) => {
  206. filterCriteria.value = params;
  207. if (params.keyword !== void 0) {
  208. keyword.value = params.keyword;
  209. }
  210. fetchJobs(true);
  211. });
  212. loadDicts();
  213. try {
  214. const sysInfo = common_vendor.index.getSystemInfoSync();
  215. const menuInfo = common_vendor.index.getMenuButtonBoundingClientRect();
  216. if (sysInfo && menuInfo) {
  217. statusBarHeight.value = sysInfo.statusBarHeight || 20;
  218. titleBarMargin.value = menuInfo.top - sysInfo.statusBarHeight;
  219. menuButtonHeight.value = menuInfo.height;
  220. }
  221. } catch (e) {
  222. }
  223. });
  224. common_vendor.onUnmounted(() => {
  225. common_vendor.index.$off("updateFilters");
  226. });
  227. common_vendor.onPullDownRefresh(async () => {
  228. fetchJobs(true);
  229. setTimeout(() => {
  230. common_vendor.index.stopPullDownRefresh();
  231. }, 800);
  232. });
  233. return (_ctx, _cache) => {
  234. return common_vendor.e({
  235. a: common_assets._imports_0$3,
  236. b: common_vendor.o(handleSearchConfirm),
  237. c: common_vendor.o([($event) => keyword.value = $event.detail.value, handleSearch]),
  238. d: keyword.value,
  239. e: menuButtonHeight.value + "px",
  240. f: statusBarHeight.value + titleBarMargin.value + "px",
  241. g: common_vendor.f(jobTypeTabs.value, (tab, index, i0) => {
  242. return {
  243. a: common_vendor.t(tab),
  244. b: currentJobType.value === index ? 1 : "",
  245. c: index,
  246. d: common_vendor.o(($event) => currentJobType.value = index, index)
  247. };
  248. }),
  249. h: common_vendor.t(activeFilterCount.value > 0 ? "· " + activeFilterCount.value : ""),
  250. i: common_vendor.o(goToFilter),
  251. j: sortType.value === "comprehensive" ? 1 : "",
  252. k: common_vendor.o(($event) => sortType.value = "comprehensive"),
  253. l: sortType.value === "latest" ? 1 : "",
  254. m: common_vendor.o(($event) => sortType.value = "latest"),
  255. n: isLoading.value && jobList.value.length === 0
  256. }, isLoading.value && jobList.value.length === 0 ? {} : common_vendor.e({
  257. o: common_vendor.f(jobList.value, (item, index, i0) => {
  258. return common_vendor.e({
  259. a: common_vendor.t(item.title),
  260. b: item.isUrgent
  261. }, item.isUrgent ? {} : {}, {
  262. c: common_vendor.t(item.salaryText),
  263. d: common_vendor.f(item.tags, (tag, tagIdx, i1) => {
  264. return {
  265. a: common_vendor.t(tag),
  266. b: tagIdx
  267. };
  268. }),
  269. e: common_vendor.t(item.count),
  270. f: common_vendor.t(item.deadline),
  271. g: item.isExpiring
  272. }, item.isExpiring ? {} : {}, {
  273. h: item.logo,
  274. i: common_vendor.t(item.company),
  275. j: common_vendor.t(item.location),
  276. k: common_vendor.o(($event) => openFeedbackPopup(item), item.id || index),
  277. l: item.id || index,
  278. m: index === 0 ? 1 : "",
  279. n: common_vendor.o(($event) => goToDetail(item), item.id || index)
  280. });
  281. }),
  282. p: common_assets._imports_0$2,
  283. q: common_assets._imports_1$1,
  284. r: common_assets._imports_2$1,
  285. s: common_assets._imports_3$1,
  286. t: jobList.value.length === 0
  287. }, jobList.value.length === 0 ? {} : {}, {
  288. v: jobList.value.length > 0 && !hasMore.value
  289. }, jobList.value.length > 0 && !hasMore.value ? {} : {}, {
  290. w: scrollTop.value + "px",
  291. x: common_vendor.o(loadMore)
  292. }), {
  293. y: common_vendor.p({
  294. activeIndex: 0
  295. }),
  296. z: showPopup.value
  297. }, showPopup.value ? {
  298. A: common_assets._imports_3$1,
  299. B: common_vendor.o(closePopup),
  300. C: common_vendor.o(($event) => handleDislikePosition()),
  301. D: common_vendor.o(($event) => handleDislikeCompany()),
  302. E: common_vendor.o(() => {
  303. }),
  304. F: common_vendor.o(closePopup),
  305. G: common_vendor.o(() => {
  306. })
  307. } : {});
  308. };
  309. }
  310. };
  311. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-ac4b611d"]]);
  312. wx.createPage(MiniProgramPage);
  313. //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/jobs/jobs.js.map