flat: 消息
This commit is contained in:
7
App.vue
7
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; */
|
||||
|
BIN
common/.DS_Store
vendored
Normal file
BIN
common/.DS_Store
vendored
Normal file
Binary file not shown.
256
common/UniStorageHelper.js
Normal file
256
common/UniStorageHelper.js
Normal file
@@ -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;
|
@@ -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
|
||||
}
|
@@ -68,8 +68,6 @@ const listData = computed(() => {
|
||||
const [reslist, lastDate] = insertSortData(ulist, props.seeDate);
|
||||
return reslist;
|
||||
}
|
||||
console.log(props.list);
|
||||
|
||||
return props.list;
|
||||
});
|
||||
|
||||
|
3
main.js
3
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)
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
||||
}
|
||||
</style>
|
||||
</style>
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
147
packageA/pages/newJobPosition/newJobPosition.vue
Normal file
147
packageA/pages/newJobPosition/newJobPosition.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<view class="reser-content">
|
||||
<scroll-view :scroll-x="true" :show-scrollbar="false" class="tab-scroll">
|
||||
<view class="content-top">
|
||||
<view
|
||||
class="top-item button-click"
|
||||
:class="{ active: state.tabIndex === 'all' }"
|
||||
@click="changeOption('all')"
|
||||
>
|
||||
全部
|
||||
</view>
|
||||
<view
|
||||
class="top-item button-click"
|
||||
:class="{ active: state.tabIndex === index }"
|
||||
v-for="(item, index) in userInfo.jobTitle"
|
||||
:key="index"
|
||||
@click="changeOption(index)"
|
||||
>
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="main">
|
||||
<scroll-view class="scroll-view" scroll-y @scrolltolower="scrollBottom">
|
||||
<view class="list">
|
||||
<renderJobs
|
||||
:list="pageState.list"
|
||||
v-if="pageState.list.length"
|
||||
:longitude="longitudeVal"
|
||||
:latitude="latitudeVal"
|
||||
></renderJobs>
|
||||
<empty v-else pdTop="200"></empty>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, watch, ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
const { $api, navTo, debounce, customSystem } = inject('globalFunction');
|
||||
import { storeToRefs } from 'pinia';
|
||||
import useLocationStore from '@/stores/useLocationStore';
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
const { userInfo } = storeToRefs(useUserStore());
|
||||
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
||||
|
||||
const pageState = reactive({
|
||||
page: 0,
|
||||
list: [],
|
||||
total: 0,
|
||||
maxPage: 1,
|
||||
pageSize: 10,
|
||||
search: {},
|
||||
lastDate: '',
|
||||
});
|
||||
const state = reactive({
|
||||
tabIndex: 'all',
|
||||
});
|
||||
|
||||
onLoad(() => {
|
||||
getList('refresh');
|
||||
});
|
||||
|
||||
function scrollBottom() {
|
||||
getList();
|
||||
}
|
||||
|
||||
function changeOption(index) {
|
||||
state.tabIndex = index;
|
||||
if (index === 'all') {
|
||||
pageState.search = {};
|
||||
getList('refresh');
|
||||
} else {
|
||||
pageState.search.jobTitle = userInfo.value.jobTitle[index];
|
||||
getList('refresh');
|
||||
}
|
||||
}
|
||||
|
||||
function getList(type = 'add', loading = true) {
|
||||
if (type === 'refresh') {
|
||||
pageState.page = 1;
|
||||
pageState.maxPage = 1;
|
||||
}
|
||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||
pageState.page += 1;
|
||||
}
|
||||
let params = {
|
||||
current: pageState.page,
|
||||
pageSize: pageState.pageSize,
|
||||
...pageState.search,
|
||||
};
|
||||
$api.createRequest('/app/notice/recommend', params).then((resData) => {
|
||||
const { rows, total } = resData;
|
||||
if (type === 'add') {
|
||||
const str = pageState.pageSize * (pageState.page - 1);
|
||||
const end = pageState.list.length;
|
||||
const reslist = rows;
|
||||
pageState.list.splice(str, end, ...reslist);
|
||||
} else {
|
||||
pageState.list = rows;
|
||||
}
|
||||
pageState.total = resData.total;
|
||||
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.reser-content{
|
||||
width: 100%;
|
||||
height: calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.content-top{
|
||||
display: flex
|
||||
padding: 28rpx
|
||||
.top-item{
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
margin-right: 48rpx
|
||||
color: #666D7F;
|
||||
white-space: nowrap
|
||||
}
|
||||
.top-item:last-child{
|
||||
padding-right: 38rpx
|
||||
}
|
||||
.active{
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
.main{
|
||||
flex: 1
|
||||
overflow: hidden
|
||||
background: #F4F4F4
|
||||
.scroll-view{
|
||||
height: 100%
|
||||
.list{
|
||||
padding: 0 28rpx 28rpx 28rpx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -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) {
|
||||
|
@@ -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() {
|
||||
|
138
packageA/pages/systemNotification/systemNotification.vue
Normal file
138
packageA/pages/systemNotification/systemNotification.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<view class="notifi-content">
|
||||
<scroll-view class="scroll-view" scroll-y @scrolltolower="scrollBottom">
|
||||
<view class="list">
|
||||
<view class="card btn-light" v-for="(item, index) in pageState.list" :key="index">
|
||||
<view class="card-Date">{{ item.date }}</view>
|
||||
<view class="card-Title">{{ item.title }}</view>
|
||||
<view class="card-subTitle">{{ item.subTitle }}</view>
|
||||
<view class="card-btns" v-if="item.noticeType === '2'" @click="seeBussiness(item)">
|
||||
<view class="btns-text">立即查看</view>
|
||||
<view class="btns-text"><uni-icons type="forward" color="#256bfa" size="18"></uni-icons></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, watch, ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app';
|
||||
const { $api, navTo, debounce, customSystem } = inject('globalFunction');
|
||||
|
||||
const pageState = reactive({
|
||||
page: 0,
|
||||
list: [],
|
||||
total: 0,
|
||||
maxPage: 1,
|
||||
pageSize: 10,
|
||||
search: {},
|
||||
lastDate: '',
|
||||
});
|
||||
|
||||
onLoad(() => {
|
||||
getList('refresh');
|
||||
});
|
||||
|
||||
function scrollBottom() {
|
||||
getList();
|
||||
}
|
||||
|
||||
function seeBussiness(item) {
|
||||
if (item.bussinessId) {
|
||||
navTo(`/packageA/pages/UnitDetails/UnitDetails?bussinessId=${item.bussinessId}`);
|
||||
}
|
||||
}
|
||||
|
||||
function setRead(row) {
|
||||
const ids = row
|
||||
.filter((item) => !item.isRead)
|
||||
.map((item) => item.noticeId)
|
||||
.join(',');
|
||||
if (ids) {
|
||||
$api.createRequest(`/app/notice/read/sysNotice?id=${ids}`, {}, 'POST').then((resData) => {
|
||||
console.log('设置已读');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getList(type = 'add', loading = true) {
|
||||
if (type === 'refresh') {
|
||||
pageState.page = 1;
|
||||
pageState.maxPage = 1;
|
||||
}
|
||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||
pageState.page += 1;
|
||||
}
|
||||
let params = {
|
||||
current: pageState.page,
|
||||
pageSize: pageState.pageSize,
|
||||
...pageState.search,
|
||||
};
|
||||
$api.createRequest('/app/notice/sysNotice', params).then((resData) => {
|
||||
const { rows, total } = resData;
|
||||
if (type === 'add') {
|
||||
const str = pageState.pageSize * (pageState.page - 1);
|
||||
const end = pageState.list.length;
|
||||
const reslist = rows;
|
||||
pageState.list.splice(str, end, ...reslist);
|
||||
} else {
|
||||
pageState.list = rows;
|
||||
}
|
||||
setRead(rows);
|
||||
pageState.total = resData.total;
|
||||
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.notifi-content {
|
||||
background-color: #f4f4f4;
|
||||
height: calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));
|
||||
.scroll-view {
|
||||
height: 100%;
|
||||
}
|
||||
.list {
|
||||
padding: 28rpx;
|
||||
.card {
|
||||
background: #ffffff;
|
||||
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.04);
|
||||
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 28rpx;
|
||||
.card-Date {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #6c7282;
|
||||
}
|
||||
.card-Title {
|
||||
margin-top: 24rpx;
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.card-subTitle {
|
||||
margin-top: 16rpx;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #495265;
|
||||
}
|
||||
.card-btns {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #256bfa;
|
||||
line-height: 45rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-top: 2rpx solid #efefef;
|
||||
width: 630rpx;
|
||||
margin-top: 28rpx;
|
||||
padding-top: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
18
pages.json
18
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",
|
||||
|
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -183,6 +183,10 @@
|
||||
</view>
|
||||
<!-- btn -->
|
||||
<CollapseTransition :show="showfile">
|
||||
<view class="area-tips">
|
||||
<uni-icons type="info-filled" color="#ADADAD" size="15"></uni-icons>
|
||||
上传后自动解析简历内容
|
||||
</view>
|
||||
<view class="area-file">
|
||||
<view class="file-card" @click="uploadCamera">
|
||||
<image class="card-img" src="/static/icon/file1.png"></image>
|
||||
@@ -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
|
||||
|
@@ -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');
|
||||
}
|
||||
|
@@ -4,12 +4,12 @@
|
||||
<!-- 顶部头部区域 -->
|
||||
<view class="container-header">
|
||||
<view class="header-btnLf button-click" @click="changeType(0)" :class="{ active: state.current === 0 }">
|
||||
已读消息
|
||||
<view class="btns-wd"></view>
|
||||
全部消息
|
||||
<!-- <view class="btns-wd"></view> -->
|
||||
</view>
|
||||
<view class="header-btnLf button-click" @click="changeType(1)" :class="{ active: state.current === 1 }">
|
||||
未读消息
|
||||
<view class="btns-wd"></view>
|
||||
<view class="btns-wd" v-if="unreadCount"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -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: [{}],
|
||||
|
@@ -1,16 +1,38 @@
|
||||
<template>
|
||||
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
|
||||
<scroll-view scroll-y class="main-scroll">
|
||||
<view class="scrollmain">
|
||||
<view class="list-card btn-feel" v-for="(item, index) in 20" :key="index">
|
||||
<view
|
||||
class="list-card btn-feel"
|
||||
v-for="(item, index) in msgList"
|
||||
:key="index"
|
||||
@click="seeDetail(item, index)"
|
||||
>
|
||||
<view class="card-img">
|
||||
<image class="card-img-flame" src="/static/icon/msgtype.png"></image>
|
||||
<image
|
||||
class="card-img-flame"
|
||||
v-if="item.title === '招聘会预约提醒'"
|
||||
src="/static/icon/msgtype.png"
|
||||
></image>
|
||||
<image
|
||||
class="card-img-flame"
|
||||
v-if="item.title === '职位上新'"
|
||||
src="/static/icon/msgtype2.png"
|
||||
></image>
|
||||
<image
|
||||
class="card-img-flame"
|
||||
v-if="item.title === '系统通知'"
|
||||
src="/static/icon/msgtype3.png"
|
||||
></image>
|
||||
<view class="subscript" v-if="item.notReadCount || !item.isRead">
|
||||
{{ item.notReadCount || '' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<view class="info-title">
|
||||
<text>今日推荐</text>
|
||||
<view class="card-time">刚才</view>
|
||||
<text>{{ item.title }}</text>
|
||||
<view class="card-time">{{ item.date }}</view>
|
||||
</view>
|
||||
<view class="info-text line_2">这里有9个职位很适合你,快来看看吧</view>
|
||||
<view class="info-text line_2">{{ item.subTitle || '消息' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -19,7 +41,12 @@
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, ref } from 'vue';
|
||||
const { $api, navTo, debounce } = inject('globalFunction');
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useReadMsg } from '@/stores/useReadMsg';
|
||||
const { msgList } = storeToRefs(useReadMsg());
|
||||
const isLoaded = ref(false);
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
if (isLoaded.value) return;
|
||||
@@ -30,7 +57,22 @@ async function loadData() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleScrollToLower() {}
|
||||
function seeDetail(item, index) {
|
||||
switch (item.title) {
|
||||
case '职位上新':
|
||||
useReadMsg().markAsRead(item, index);
|
||||
navTo('/packageA/pages/newJobPosition/newJobPosition');
|
||||
break;
|
||||
case '招聘会预约提醒':
|
||||
useReadMsg().markAsRead(item, index);
|
||||
navTo('/packageA/pages/reservation/reservation');
|
||||
break;
|
||||
case '系统通知':
|
||||
navTo('/packageA/pages/systemNotification/systemNotification');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ loadData });
|
||||
</script>
|
||||
|
||||
@@ -41,6 +83,9 @@ defineExpose({ loadData });
|
||||
}
|
||||
.scrollmain{
|
||||
padding: 28rpx
|
||||
}
|
||||
.read{
|
||||
|
||||
}
|
||||
.list-card
|
||||
background: #FFFFFF;
|
||||
@@ -57,9 +102,25 @@ defineExpose({ loadData });
|
||||
display: grid;
|
||||
place-items: center;
|
||||
margin-right: 30rpx;
|
||||
position: relative;
|
||||
.card-img-flame
|
||||
width: 100%;
|
||||
height: 100%
|
||||
.subscript
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
min-width: 26rpx;
|
||||
height: 26rpx;
|
||||
padding: 0 8rpx; /* 横向内边距控制宽度自适应 */
|
||||
border-radius: 1000rpx; /* 实现椭圆形/圆角 */
|
||||
text-align: center;
|
||||
line-height: 26rpx;
|
||||
background: #F73636;
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
color: #FFFFFF;
|
||||
box-sizing: border-box;
|
||||
.card-info
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
@@ -1,16 +1,36 @@
|
||||
<template>
|
||||
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
|
||||
<scroll-view scroll-y class="main-scroll">
|
||||
<view class="scrollmain">
|
||||
<view class="list-card btn-feel" v-for="(item, index) in 20" :key="index">
|
||||
<view
|
||||
class="list-card btn-feel"
|
||||
v-for="(item, index) in unreadMsgList"
|
||||
:key="index"
|
||||
@click="seeDetail(item)"
|
||||
>
|
||||
<view class="card-img">
|
||||
<image class="card-img-flame" src="/static/icon/msgtype.png"></image>
|
||||
<image
|
||||
class="card-img-flame"
|
||||
v-if="item.title === '招聘会预约提醒'"
|
||||
src="/static/icon/msgtype.png"
|
||||
></image>
|
||||
<image
|
||||
class="card-img-flame"
|
||||
v-if="item.title === '职位上新'"
|
||||
src="/static/icon/msgtype2.png"
|
||||
></image>
|
||||
<image
|
||||
class="card-img-flame"
|
||||
v-if="item.title === '系统通知'"
|
||||
src="/static/icon/msgtype3.png"
|
||||
></image>
|
||||
<view class="subscript" v-if="item.notReadCount">{{ item.notReadCount }}</view>
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<view class="info-title">
|
||||
<text>今日推荐</text>
|
||||
<view class="card-time">刚才</view>
|
||||
<text>{{ item.title }}</text>
|
||||
<view class="card-time">{{ item.date }}</view>
|
||||
</view>
|
||||
<view class="info-text line_2">这里有9个职位很适合你,快来看看吧</view>
|
||||
<view class="info-text line_2">{{ item.subTitle || '消息' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -19,7 +39,12 @@
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, ref } from 'vue';
|
||||
const { $api, navTo, debounce } = inject('globalFunction');
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useReadMsg } from '@/stores/useReadMsg';
|
||||
const { unreadMsgList } = storeToRefs(useReadMsg());
|
||||
const isLoaded = ref(false);
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
if (isLoaded.value) return;
|
||||
@@ -30,7 +55,10 @@ async function loadData() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleScrollToLower() {}
|
||||
function seeDetail(item) {
|
||||
console.log(item);
|
||||
}
|
||||
|
||||
defineExpose({ loadData });
|
||||
</script>
|
||||
|
||||
@@ -41,6 +69,9 @@ defineExpose({ loadData });
|
||||
}
|
||||
.scrollmain{
|
||||
padding: 28rpx
|
||||
}
|
||||
.read{
|
||||
|
||||
}
|
||||
.list-card
|
||||
background: #FFFFFF;
|
||||
@@ -57,9 +88,25 @@ defineExpose({ loadData });
|
||||
display: grid;
|
||||
place-items: center;
|
||||
margin-right: 30rpx;
|
||||
position: relative;
|
||||
.card-img-flame
|
||||
width: 100%;
|
||||
height: 100%
|
||||
.subscript
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
min-width: 26rpx;
|
||||
height: 26rpx;
|
||||
padding: 0 8rpx; /* 横向内边距控制宽度自适应 */
|
||||
border-radius: 1000rpx; /* 实现椭圆形/圆角 */
|
||||
text-align: center;
|
||||
line-height: 26rpx;
|
||||
background: #F73636;
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
color: #FFFFFF;
|
||||
box-sizing: border-box;
|
||||
.card-info
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
@@ -23,7 +23,7 @@
|
||||
</view>
|
||||
<scroll-view scroll-y class="Detailscroll-view" v-show="list.length" @scrolltolower="getJobList('add')">
|
||||
<view class="cards-box">
|
||||
<renderJobs :list="list" :longitude="longitude" :latitude="latitude"></renderJobs>
|
||||
<renderJobs :list="list" :longitude="longitudeVal" :latitude="latitudeVal"></renderJobs>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="main-content" v-show="!list.length">
|
||||
@@ -44,12 +44,12 @@
|
||||
|
||||
<script setup>
|
||||
import { inject, ref, reactive } from 'vue';
|
||||
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import SelectJobs from '@/components/selectJobs/selectJobs.vue';
|
||||
const { $api, navBack } = inject('globalFunction');
|
||||
import useLocationStore from '@/stores/useLocationStore';
|
||||
const { getLocation, longitude, latitude } = useLocationStore();
|
||||
import { storeToRefs } from 'pinia';
|
||||
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
||||
const searchValue = ref('');
|
||||
const historyList = ref([]);
|
||||
const list = ref([]);
|
||||
|
BIN
static/.DS_Store
vendored
BIN
static/.DS_Store
vendored
Binary file not shown.
BIN
static/font/.DS_Store
vendored
BIN
static/font/.DS_Store
vendored
Binary file not shown.
BIN
static/icon/.DS_Store
vendored
BIN
static/icon/.DS_Store
vendored
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
static/tabbar/.DS_Store
vendored
BIN
static/tabbar/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 9.8 KiB |
BIN
static/tabbar/logo3.png
Normal file
BIN
static/tabbar/logo3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
@@ -1,5 +1,6 @@
|
||||
// BaseStore.js - 基础Store类
|
||||
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
||||
// import UniStorageHelper from '../common/UniStorageHelper'
|
||||
import useChatGroupDBStore from './userChatGroupStore'
|
||||
import config from '@/config'
|
||||
|
||||
@@ -29,7 +30,12 @@ class BaseStore {
|
||||
}
|
||||
}
|
||||
initDB() {
|
||||
// // #ifdef H5
|
||||
this.db = new IndexedDBHelper(this.dbName, config.DBversion);
|
||||
// // #endif
|
||||
// // #ifndef H5
|
||||
// this.db = new UniStorageHelper(this.dbName, config.DBversion);
|
||||
// // #endif
|
||||
this.db.openDB([{
|
||||
name: 'record',
|
||||
keyPath: "id",
|
||||
|
@@ -38,7 +38,8 @@ const useDictStore = defineStore("dict", () => {
|
||||
sex: [],
|
||||
affiliation: [],
|
||||
industry: [],
|
||||
nature: []
|
||||
nature: [],
|
||||
noticeType: []
|
||||
})
|
||||
// political_affiliation
|
||||
const getDictData = async (dictType, dictName) => {
|
||||
@@ -49,7 +50,8 @@ const useDictStore = defineStore("dict", () => {
|
||||
return data
|
||||
})
|
||||
}
|
||||
const [education, experience, area, scale, sex, affiliation, nature] = await Promise.all([
|
||||
const [education, experience, area, scale, sex, affiliation, nature, noticeType] =
|
||||
await Promise.all([
|
||||
getDictSelectOption('education'),
|
||||
getDictSelectOption('experience'),
|
||||
getDictSelectOption('area', true),
|
||||
@@ -57,6 +59,7 @@ const useDictStore = defineStore("dict", () => {
|
||||
getDictSelectOption('app_sex'),
|
||||
getDictSelectOption('political_affiliation'),
|
||||
getDictSelectOption('company_nature'),
|
||||
getDictSelectOption('sys_notice_type'),
|
||||
]);
|
||||
|
||||
state.education = education;
|
||||
@@ -66,6 +69,7 @@ const useDictStore = defineStore("dict", () => {
|
||||
state.sex = sex;
|
||||
state.affiliation = affiliation;
|
||||
state.nature = nature
|
||||
state.noticeType = noticeType
|
||||
complete.value = true
|
||||
getIndustryDict() // 获取行业
|
||||
} catch (error) {
|
||||
|
84
stores/useReadMsg.js
Normal file
84
stores/useReadMsg.js
Normal file
@@ -0,0 +1,84 @@
|
||||
// store/useReadMsg.js
|
||||
import {
|
||||
defineStore
|
||||
} from 'pinia'
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
watch
|
||||
} from 'vue'
|
||||
import {
|
||||
msg,
|
||||
$api,
|
||||
} from '../common/globalFunction';
|
||||
export const useReadMsg = defineStore('readMsg', () => {
|
||||
const msgList = ref([])
|
||||
|
||||
// 计算总未读数量,基于 notReadCount 字段
|
||||
const unreadCount = computed(() =>
|
||||
msgList.value.reduce((sum, msg) => sum + (msg.notReadCount || 0), 0)
|
||||
)
|
||||
|
||||
// 未读消息列表
|
||||
const unreadMsgList = computed(() =>
|
||||
msgList.value.filter(msg => msg.notReadCount > 0)
|
||||
)
|
||||
|
||||
|
||||
// 设置 TabBar 角标
|
||||
function updateTabBarBadge() {
|
||||
const count = unreadCount.value
|
||||
if (count === 0) {
|
||||
uni.removeTabBarBadge({
|
||||
index: 3
|
||||
}) // 替换为你消息页面的 TabBar index
|
||||
} else {
|
||||
uni.setTabBarBadge({
|
||||
index: 3,
|
||||
text: count > 99 ? '99+' : String(count)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 拉取消息列表
|
||||
async function fetchMessages() {
|
||||
try {
|
||||
$api.createRequest('/app/notice/info', {
|
||||
isRead: 1
|
||||
}, "GET").then((res) => {
|
||||
msgList.value = res.data || []
|
||||
updateTabBarBadge()
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('获取消息失败:', err)
|
||||
}
|
||||
}
|
||||
|
||||
// 设置为已读
|
||||
async function markAsRead(item, index) {
|
||||
const msg = msgList.value[index]
|
||||
if (!msg || msg.isRead === 1) return
|
||||
|
||||
try {
|
||||
let params = {
|
||||
id: msg.noticeId
|
||||
}
|
||||
$api.createRequest('/app/notice/read?id=' + msg.noticeId, params, "POST").then((res) => {
|
||||
msgList.value[index].isRead = 1
|
||||
updateTabBarBadge()
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('设置消息已读失败:', err)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
msgList,
|
||||
unreadMsgList,
|
||||
unreadCount,
|
||||
fetchMessages,
|
||||
markAsRead,
|
||||
updateTabBarBadge
|
||||
}
|
||||
})
|
@@ -4,7 +4,6 @@ import {
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
||||
import useDictStore from '@/stores/useDictStore';
|
||||
import jobAnalyzer from '@/utils/jobAnalyzer';
|
||||
import {
|
||||
|
@@ -6,11 +6,14 @@ import {
|
||||
} from 'vue'
|
||||
import {
|
||||
createRequest
|
||||
} from '../utils/request';
|
||||
} from '@/utils/request';
|
||||
import similarityJobs from '@/utils/similarity_Job.js';
|
||||
import {
|
||||
UUID
|
||||
} from "@/lib/uuid-min.js";
|
||||
import {
|
||||
useReadMsg
|
||||
} from '@/stores/useReadMsg';
|
||||
|
||||
// 简历完成度计算
|
||||
function getResumeCompletionPercentage(resume) {
|
||||
@@ -97,6 +100,8 @@ const useUserStore = defineStore("user", () => {
|
||||
const loginSetToken = async (value) => {
|
||||
token.value = value
|
||||
uni.setStorageSync('token', value);
|
||||
// 获取消息列表
|
||||
useReadMsg().fetchMessages()
|
||||
// 获取用户信息
|
||||
return getUserResume()
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ import {
|
||||
ref,
|
||||
toRaw
|
||||
} from 'vue'
|
||||
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
||||
import baseDB from './BaseDBStore';
|
||||
import {
|
||||
msg,
|
||||
|
BIN
unpackage/.DS_Store
vendored
BIN
unpackage/.DS_Store
vendored
Binary file not shown.
BIN
unpackage/dist/.DS_Store
vendored
BIN
unpackage/dist/.DS_Store
vendored
Binary file not shown.
BIN
unpackage/dist/build/.DS_Store
vendored
BIN
unpackage/dist/build/.DS_Store
vendored
Binary file not shown.
Reference in New Issue
Block a user