jobs.js 12 KB

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