diff --git a/.DS_Store b/.DS_Store index 5ff22ec..71ba820 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/App.vue b/App.vue index a1b412d..325350b 100644 --- a/App.vue +++ b/App.vue @@ -55,10 +55,11 @@ onHide(() => { @import '@/common/common.css'; /* 修改pages tabbar样式 H5有效 */ .uni-tabbar .uni-tabbar__item:nth-child(4) .uni-tabbar__bd .uni-tabbar__icon { - height: 39px !important; - width: 39px !important; - margin-top: -1rpx; + height: 110rpx !important; + width: 122rpx !important; + margin-top: 6rpx; } + .uni-tabbar-border { background-color: transparent !important; /* background-color: #e4e4e4 !important; */ diff --git a/common/.DS_Store b/common/.DS_Store new file mode 100644 index 0000000..415e9cb Binary files /dev/null and b/common/.DS_Store differ diff --git a/common/UniStorageHelper.js b/common/UniStorageHelper.js new file mode 100644 index 0000000..b8241b3 --- /dev/null +++ b/common/UniStorageHelper.js @@ -0,0 +1,256 @@ +// uni-storage-helper.js +class UniStorageHelper { + constructor(dbName, options = {}) { + this.dbName = dbName; + this.storesMeta = {}; + this.options = { + maxEntries: 500, // 单个存储空间最大条目数 + maxSizeMB: 1, // 单条数据最大限制(微信小程序限制) + autoPurge: true, // 是否自动清理旧数据 + purgeBatch: 10, // 自动清理批次数量 + debug: false, // 调试模式 + ...options + }; + } + + /*================== + 核心方法 + ==================*/ + + /** + * 初始化存储空间 + * @param {Array} stores - 存储空间配置 + */ + async openDB(stores = []) { + stores.forEach(store => { + const storeKey = this._getStoreKey(store.name); + if (!this._storageHas(storeKey)) { + this._storageSet(storeKey, []); + } + + this.storesMeta[store.name] = { + keyPath: store.keyPath, + autoIncrement: !!store.autoIncrement, + indexes: store.indexes || [] + }; + + if (store.autoIncrement) { + const counterKey = this._getCounterKey(store.name); + if (!this._storageHas(counterKey)) { + this._storageSet(counterKey, 1); + } + } + }); + + this._log('数据库初始化完成'); + return Promise.resolve(); + } + + /** + * 添加数据(自动处理容量限制) + */ + async add(storeName, data) { + try { + const storeKey = this._getStoreKey(storeName); + let storeData = this._storageGet(storeKey) || []; + const meta = this.storesMeta[storeName]; + const items = Array.isArray(data) ? data : [data]; + + // 容量预检 + await this._checkCapacity(storeName, items); + + // 处理自增ID + if (meta?.autoIncrement) { + const counterKey = this._getCounterKey(storeName); + let nextId = this._storageGet(counterKey) || 1; + items.forEach(item => { + item[meta.keyPath] = nextId++; + this._createIndexes(meta.indexes, item); + }); + this._storageSet(counterKey, nextId); + } + + // 保存数据 + storeData = [...storeData, ...items]; + this._storageSet(storeKey, storeData); + + this._log(`成功添加${items.length}条数据到${storeName}`); + + return meta?.autoIncrement ? + Array.isArray(data) ? + items.map(i => i[meta.keyPath]) : + items[0][meta.keyPath] : + undefined; + + } catch (error) { + if (error.message.includes('exceed')) { + this._log('触发自动清理...'); + await this._purgeData(storeName, this.options.purgeBatch); + return this.add(storeName, data); + } + throw error; + } + } + + /*================== + 查询方法 + ==================*/ + + async get(storeName, key) { + const storeData = this._storageGet(this._getStoreKey(storeName)) || []; + const keyPath = this.storesMeta[storeName]?.keyPath; + return storeData.find(item => item[keyPath] === key); + } + + async getAll(storeName) { + return this._storageGet(this._getStoreKey(storeName)) || []; + } + + async queryByField(storeName, fieldName, value) { + const storeData = this._storageGet(this._getStoreKey(storeName)) || []; + return storeData.filter(item => item[fieldName] === value); + } + + /*================== + 更新/删除方法 + ==================*/ + + async update(storeName, data, key) { + const storeKey = this._getStoreKey(storeName); + const storeData = this._storageGet(storeKey) || []; + const meta = this.storesMeta[storeName]; + const keyPath = meta?.keyPath; + const targetKey = key ?? data[keyPath]; + + const index = storeData.findIndex(item => item[keyPath] === targetKey); + if (index === -1) throw new Error('未找到对应记录'); + + // 合并数据并重建索引 + const newItem = { + ...storeData[index], + ...data + }; + this._createIndexes(meta.indexes, newItem); + + storeData[index] = newItem; + this._storageSet(storeKey, storeData); + + return "更新成功"; + } + + async delete(storeName, key) { + const storeKey = this._getStoreKey(storeName); + const storeData = this._storageGet(storeKey) || []; + const keyPath = this.storesMeta[storeName]?.keyPath; + const newData = storeData.filter(item => item[keyPath] !== key); + this._storageSet(storeKey, newData); + return `删除${storeData.length - newData.length}条记录`; + } + + /*================== + 存储管理 + ==================*/ + + async clearStore(storeName) { + this._storageSet(this._getStoreKey(storeName), []); + return "存储空间已清空"; + } + + async deleteDB() { + Object.keys(this.storesMeta).forEach(storeName => { + uni.removeStorageSync(this._getStoreKey(storeName)); + uni.removeStorageSync(this._getCounterKey(storeName)); + }); + return "数据库已删除"; + } + + /*================== + 私有方法 + ==================*/ + + _getStoreKey(storeName) { + return `${this.dbName}_${storeName}`; + } + + _getCounterKey(storeName) { + return `${this.dbName}_${storeName}_counter`; + } + + _createIndexes(indexes, item) { + indexes.forEach(index => { + item[index.name] = item[index.key]; + }); + } + + async _checkCapacity(storeName, newItems) { + const storeKey = this._getStoreKey(storeName); + const currentData = this._storageGet(storeKey) || []; + + // 检查条目数限制 + if (currentData.length + newItems.length > this.options.maxEntries) { + await this._purgeData(storeName, newItems.length); + } + + // 检查单条数据大小 + newItems.forEach(item => { + const sizeMB = this._getItemSizeMB(item); + if (sizeMB > this.options.maxSizeMB) { + throw new Error(`单条数据大小超出${this.options.maxSizeMB}MB限制`); + } + }); + } + + _getItemSizeMB(item) { + try { + // 精确计算(支持Blob的环境) + return new Blob([JSON.stringify(item)]).size / 1024 / 1024; + } catch { + // 兼容方案 + return encodeURIComponent(JSON.stringify(item)).length * 2 / 1024 / 1024; + } + } + + async _purgeData(storeName, count) { + const storeKey = this._getStoreKey(storeName); + const currentData = this._storageGet(storeKey) || []; + const newData = currentData.slice(count); + this._storageSet(storeKey, newData); + this._log(`自动清理${count}条旧数据`); + } + + /*================== + 存储适配器 + ==================*/ + + _storageHas(key) { + return !!uni.getStorageSync(key); + } + + _storageGet(key) { + try { + return uni.getStorageSync(key); + } catch (e) { + return null; + } + } + + _storageSet(key, value) { + try { + uni.setStorageSync(key, value); + return true; + } catch (error) { + if (error.errMsg?.includes('exceed')) { + throw new Error('STORAGE_QUOTA_EXCEEDED'); + } + throw error; + } + } + + _log(...args) { + if (this.options.debug) { + console.log(`[StorageHelper]`, ...args); + } + } +} + +export default UniStorageHelper; \ No newline at end of file diff --git a/common/globalFunction.js b/common/globalFunction.js index df27454..2dc5b90 100644 --- a/common/globalFunction.js +++ b/common/globalFunction.js @@ -534,6 +534,10 @@ function appendScriptTagElement(src) { }) } +function isInWechatMiniProgramWebview() { + const ua = navigator.userAgent.toLowerCase() + return ua.includes('miniprogram') || window.__wxjs_environment === 'miniprogram' +} export const $api = { msg, @@ -574,5 +578,6 @@ export default { isFutureDate, parseQueryParams, appendScriptTagElement, - insertSortData + insertSortData, + isInWechatMiniProgramWebview } \ No newline at end of file diff --git a/components/renderJobs/renderJobs.vue b/components/renderJobs/renderJobs.vue index ead65a2..96cd980 100644 --- a/components/renderJobs/renderJobs.vue +++ b/components/renderJobs/renderJobs.vue @@ -68,8 +68,6 @@ const listData = computed(() => { const [reslist, lastDate] = insertSortData(ulist, props.seeDate); return reslist; } - console.log(props.list); - return props.list; }); diff --git a/main.js b/main.js index 1b037be..8ae9e2a 100644 --- a/main.js +++ b/main.js @@ -22,6 +22,9 @@ import { createSSRApp, } from 'vue' +const foldFeature = window.visualViewport && 'segments' in window.visualViewport +console.log('是否支持多段屏幕:', foldFeature) + // 全局组件 export function createApp() { const app = createSSRApp(App) diff --git a/packageA/pages/Intendedposition/Intendedposition.vue b/packageA/pages/Intendedposition/Intendedposition.vue index c3607b9..1ed76e9 100644 --- a/packageA/pages/Intendedposition/Intendedposition.vue +++ b/packageA/pages/Intendedposition/Intendedposition.vue @@ -47,7 +47,7 @@ function navToPost(jobId) { function getJobList(type = 'add') { if (type === 'refresh') { - pageState.page = 0; + pageState.page = 1; pageState.maxPage = 1; } if (type === 'add' && pageState.page < pageState.maxPage) { diff --git a/packageA/pages/UnitDetails/UnitDetails.vue b/packageA/pages/UnitDetails/UnitDetails.vue index 1096c9b..2cdccd9 100644 --- a/packageA/pages/UnitDetails/UnitDetails.vue +++ b/packageA/pages/UnitDetails/UnitDetails.vue @@ -85,7 +85,7 @@ const companyInfo = ref({}); onLoad((options) => { console.log(options); - getCompanyInfo(options.companyId); + getCompanyInfo(options.companyId || options.bussinessId); }); function companyCollection() { @@ -112,7 +112,7 @@ function getCompanyInfo(id) { function getJobsList(type = 'add') { if (type === 'refresh') { - pageState.page = 0; + pageState.page = 1; pageState.maxPage = 1; } if (type === 'add' && pageState.page < pageState.maxPage) { diff --git a/packageA/pages/browseJob/browseJob.vue b/packageA/pages/browseJob/browseJob.vue index 7bc6f04..961bc4f 100644 --- a/packageA/pages/browseJob/browseJob.vue +++ b/packageA/pages/browseJob/browseJob.vue @@ -44,7 +44,7 @@ import dictLabel from '@/components/dict-Label/dict-Label.vue'; import { reactive, inject, watch, ref, onMounted } from 'vue'; import { storeToRefs } from 'pinia'; -import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app'; +import { onLoad, onShow } from '@dcloudio/uni-app'; import useUserStore from '@/stores/useUserStore'; const { $api, navTo, navBack } = inject('globalFunction'); import useLocationStore from '@/stores/useLocationStore'; @@ -68,15 +68,16 @@ const currentDate = ref(''); onLoad(() => { getBrowseDate(); - const today = new Date().toISOString().split('T')[0]; getJobList('refresh'); - currentDate.value = today; + // const today = new Date().toISOString().split('T')[0]; + // currentDate.value = today; }); function toSelectDate() { navTo('/packageA/pages/selectDate/selectDate', { query: { date: currentDate.value, + record: true, }, onBack: (res) => { currentDate.value = res.date; @@ -216,4 +217,4 @@ image { background: #f4f4f4 } - + \ No newline at end of file diff --git a/packageA/pages/choicenessList/choicenessList.vue b/packageA/pages/choicenessList/choicenessList.vue index f0be602..2a5e2df 100644 --- a/packageA/pages/choicenessList/choicenessList.vue +++ b/packageA/pages/choicenessList/choicenessList.vue @@ -72,7 +72,7 @@ function searchCollection(e) { // list function getDataList(type = 'add') { if (type === 'refresh') { - pageState.page = 0; + pageState.page = 1; pageState.maxPage = 1; } if (type === 'add' && pageState.page < pageState.maxPage) { diff --git a/packageA/pages/collection/collection.vue b/packageA/pages/collection/collection.vue index 6308601..928dd70 100644 --- a/packageA/pages/collection/collection.vue +++ b/packageA/pages/collection/collection.vue @@ -93,7 +93,7 @@ function handleScrollToLowerCompany() { function getJobList(type = 'add') { if (type === 'refresh') { - pageState.page = 0; + pageState.page = 1; pageState.maxPage = 1; } if (type === 'add' && pageState.page < pageState.maxPage) { @@ -121,7 +121,7 @@ function getJobList(type = 'add') { function getCompanyList(type = 'add') { if (type === 'refresh') { - pageCompanyState.page = 0; + pageCompanyState.page = 1; pageCompanyState.maxPage = 1; } if (type === 'add' && pageCompanyState.page < pageCompanyState.maxPage) { diff --git a/packageA/pages/newJobPosition/newJobPosition.vue b/packageA/pages/newJobPosition/newJobPosition.vue new file mode 100644 index 0000000..4536ce0 --- /dev/null +++ b/packageA/pages/newJobPosition/newJobPosition.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/packageA/pages/reservation/reservation.vue b/packageA/pages/reservation/reservation.vue index a34f8df..cecd81f 100644 --- a/packageA/pages/reservation/reservation.vue +++ b/packageA/pages/reservation/reservation.vue @@ -97,7 +97,7 @@ function updateCancel(item) { function getList(type = 'add', loading = true) { if (type === 'refresh') { - pageState.page = 0; + pageState.page = 1; pageState.maxPage = 1; } if (type === 'add' && pageState.page < pageState.maxPage) { diff --git a/packageA/pages/selectDate/selectDate.vue b/packageA/pages/selectDate/selectDate.vue index b01a15a..03cf809 100644 --- a/packageA/pages/selectDate/selectDate.vue +++ b/packageA/pages/selectDate/selectDate.vue @@ -52,6 +52,8 @@ const calendarData = ref([]); const current = ref({}); import { Solar, Lunar } from '@/lib/lunar-javascript@1.7.2.js'; +const isRecord = ref(false); +const recordNum = ref(4); const pages = reactive({ year: 0, month: 0, @@ -63,15 +65,21 @@ onLoad((options) => { date: options?.date || null, }; } - console.log(options); - initPagesDate(); - addMonth(); - addMonth(); - addMonth(); + if (options.record) { + isRecord.value = true; + initOldPagesDate(); + new Array(recordNum.value + 1).fill(null).map(() => { + addMonth(); + }); + } else { + initPagesDate(); + new Array(recordNum.value).fill(null).map(() => { + addMonth(); + }); + } }); function backParams() { - console.log(isValidDateString(current.value.date)); if (isValidDateString(current.value.date)) { navBack({ data: current.value, @@ -94,6 +102,7 @@ function isValidDateString(dateStr) { } function onScrollBottom() { + if (isRecord.value) return; addMonth(); } @@ -101,10 +110,22 @@ function selectDay(item) { current.value = item; } +function initOldPagesDate() { + const d = new Date(); + const yue = d.getMonth(); + if (yue < recordNum.value) { + pages.month = 12 + (yue - recordNum.value); + pages.year = d.getFullYear() - 1; + } else { + pages.month = yue - recordNum.value; + pages.year = d.getFullYear(); + } +} + function initPagesDate() { const d = new Date(); - pages.year = d.getFullYear(); pages.month = d.getMonth(); + pages.year = d.getFullYear(); } function addMonth() { diff --git a/packageA/pages/systemNotification/systemNotification.vue b/packageA/pages/systemNotification/systemNotification.vue new file mode 100644 index 0000000..9124fb2 --- /dev/null +++ b/packageA/pages/systemNotification/systemNotification.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/pages.json b/pages.json index 8fc1194..b03aa14 100644 --- a/pages.json +++ b/pages.json @@ -172,6 +172,20 @@ "navigationBarBackgroundColor": "#FFFFFF", "navigationStyle": "custom" } + }, + { + "path": "pages/newJobPosition/newJobPosition", + "style": { + "navigationBarTitleText": "新职位推荐", + "navigationBarBackgroundColor": "#FFFFFF" + } + }, + { + "path": "pages/systemNotification/systemNotification", + "style": { + "navigationBarTitleText": "系统通知", + "navigationBarBackgroundColor": "#FFFFFF" + } } ] }], @@ -199,8 +213,8 @@ }, { "pagePath": "pages/chat/chat", - "iconPath": "static/tabbar/logo2copy.png", - "selectedIconPath": "static/tabbar/logo2copy.png" + "iconPath": "static/tabbar/logo3.png", + "selectedIconPath": "static/tabbar/logo3.png" }, { "pagePath": "pages/msglog/msglog", diff --git a/pages/careerfair/careerfair.vue b/pages/careerfair/careerfair.vue index 434ea47..dc22fae 100644 --- a/pages/careerfair/careerfair.vue +++ b/pages/careerfair/careerfair.vue @@ -110,8 +110,14 @@ const pageState = reactive({ }); onLoad(() => { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + + const currentDate = `${year}-${month}-${day}`; const result = getNextDates({ - startDate: '2025-04-21', + startDate: currentDate, }); weekList.value = result; getFair('refresh'); @@ -123,9 +129,17 @@ function toSelectDate() { date: currentDay.value.fullDate, }, onBack: (res) => { + console.log(res); const result = getNextDates({ startDate: res.date, }); + const formattedDate = res.date.slice(5); // MM-DD + const dateFull = { + date: res.date.slice(5), + day: '周' + res.week, + fullDate: res.date, + }; + currentDay.value = dateFull; weekList.value = result; getFair('refresh'); }, @@ -151,7 +165,7 @@ const handleScrollToLower = () => { function getFair(type = 'add') { if (type === 'refresh') { - pageState.page = 0; + pageState.page = 1; pageState.maxPage = 1; } if (type === 'add' && pageState.page < pageState.maxPage) { @@ -262,7 +276,6 @@ function getNextDates({ startDate = '', count = 6 }) { date: formattedDate, fullDate, day: '周' + dayOfWeek, - isToday: i === 0, }); } diff --git a/pages/chat/components/ai-paging.vue b/pages/chat/components/ai-paging.vue index 6bb0046..615c99f 100644 --- a/pages/chat/components/ai-paging.vue +++ b/pages/chat/components/ai-paging.vue @@ -183,6 +183,10 @@ + + + 上传后自动解析简历内容 + @@ -957,12 +961,18 @@ image-margin-top = 40rpx transform: rotate(45deg) transition: transform 0.5s ease; } +.area-tips{ + font-weight: 400; + font-size: 26rpx; + color: #434343; + margin-top: 18rpx +} .area-file display: grid width: 100% grid-template-columns: repeat(3, 1fr) grid-gap: 20rpx - padding: 32rpx 0 0 0; + padding: 20rpx 0 0 0; .file-card display: flex flex-direction: column diff --git a/pages/index/index.vue b/pages/index/index.vue index 72a1df0..ddf87c9 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -304,7 +304,7 @@ function choosePosition(index) { getJobRecommend('refresh'); } else { // const id = useUserStore().userInfo.jobTitleId.split(',')[index]; - pageState.search.jobTitle = useUserStore().userInfo.jobTitle[index]; + pageState.search.jobTitle = userInfo.value.jobTitle[index]; inputText.value = ''; getJobList('refresh'); } diff --git a/pages/msglog/msglog.vue b/pages/msglog/msglog.vue index 964012e..30c0b61 100644 --- a/pages/msglog/msglog.vue +++ b/pages/msglog/msglog.vue @@ -4,12 +4,12 @@ - 已读消息 - + 全部消息 + 未读消息 - + @@ -39,7 +39,14 @@ import UnreadComponent from './unread.vue'; const loadedMap = reactive([false, false]); const swiperRefs = [ref(null), ref(null)]; const components = [ReadComponent, UnreadComponent]; +import { storeToRefs } from 'pinia'; +import { useReadMsg } from '@/stores/useReadMsg'; +const { unreadCount } = storeToRefs(useReadMsg()); +onShow(() => { + // 获取消息列表 + useReadMsg().fetchMessages(); +}); const state = reactive({ current: 0, all: [{}], diff --git a/pages/msglog/read.vue b/pages/msglog/read.vue index 7355663..7dc0445 100644 --- a/pages/msglog/read.vue +++ b/pages/msglog/read.vue @@ -1,16 +1,38 @@