jobs.js 12 KB

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