flat: 消息
This commit is contained in:
7
App.vue
7
App.vue
@@ -55,10 +55,11 @@ onHide(() => {
|
|||||||
@import '@/common/common.css';
|
@import '@/common/common.css';
|
||||||
/* 修改pages tabbar样式 H5有效 */
|
/* 修改pages tabbar样式 H5有效 */
|
||||||
.uni-tabbar .uni-tabbar__item:nth-child(4) .uni-tabbar__bd .uni-tabbar__icon {
|
.uni-tabbar .uni-tabbar__item:nth-child(4) .uni-tabbar__bd .uni-tabbar__icon {
|
||||||
height: 39px !important;
|
height: 110rpx !important;
|
||||||
width: 39px !important;
|
width: 122rpx !important;
|
||||||
margin-top: -1rpx;
|
margin-top: 6rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-tabbar-border {
|
.uni-tabbar-border {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
/* background-color: #e4e4e4 !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 = {
|
export const $api = {
|
||||||
msg,
|
msg,
|
||||||
@@ -574,5 +578,6 @@ export default {
|
|||||||
isFutureDate,
|
isFutureDate,
|
||||||
parseQueryParams,
|
parseQueryParams,
|
||||||
appendScriptTagElement,
|
appendScriptTagElement,
|
||||||
insertSortData
|
insertSortData,
|
||||||
|
isInWechatMiniProgramWebview
|
||||||
}
|
}
|
@@ -68,8 +68,6 @@ const listData = computed(() => {
|
|||||||
const [reslist, lastDate] = insertSortData(ulist, props.seeDate);
|
const [reslist, lastDate] = insertSortData(ulist, props.seeDate);
|
||||||
return reslist;
|
return reslist;
|
||||||
}
|
}
|
||||||
console.log(props.list);
|
|
||||||
|
|
||||||
return props.list;
|
return props.list;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
3
main.js
3
main.js
@@ -22,6 +22,9 @@ import {
|
|||||||
createSSRApp,
|
createSSRApp,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
|
|
||||||
|
const foldFeature = window.visualViewport && 'segments' in window.visualViewport
|
||||||
|
console.log('是否支持多段屏幕:', foldFeature)
|
||||||
|
|
||||||
// 全局组件
|
// 全局组件
|
||||||
export function createApp() {
|
export function createApp() {
|
||||||
const app = createSSRApp(App)
|
const app = createSSRApp(App)
|
||||||
|
@@ -47,7 +47,7 @@ function navToPost(jobId) {
|
|||||||
|
|
||||||
function getJobList(type = 'add') {
|
function getJobList(type = 'add') {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageState.page = 0;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 1;
|
pageState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
|
@@ -85,7 +85,7 @@ const companyInfo = ref({});
|
|||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
console.log(options);
|
console.log(options);
|
||||||
getCompanyInfo(options.companyId);
|
getCompanyInfo(options.companyId || options.bussinessId);
|
||||||
});
|
});
|
||||||
|
|
||||||
function companyCollection() {
|
function companyCollection() {
|
||||||
@@ -112,7 +112,7 @@ function getCompanyInfo(id) {
|
|||||||
|
|
||||||
function getJobsList(type = 'add') {
|
function getJobsList(type = 'add') {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageState.page = 0;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 1;
|
pageState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
import dictLabel from '@/components/dict-Label/dict-Label.vue';
|
import dictLabel from '@/components/dict-Label/dict-Label.vue';
|
||||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
import useUserStore from '@/stores/useUserStore';
|
import useUserStore from '@/stores/useUserStore';
|
||||||
const { $api, navTo, navBack } = inject('globalFunction');
|
const { $api, navTo, navBack } = inject('globalFunction');
|
||||||
import useLocationStore from '@/stores/useLocationStore';
|
import useLocationStore from '@/stores/useLocationStore';
|
||||||
@@ -68,15 +68,16 @@ const currentDate = ref('');
|
|||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
getBrowseDate();
|
getBrowseDate();
|
||||||
const today = new Date().toISOString().split('T')[0];
|
|
||||||
getJobList('refresh');
|
getJobList('refresh');
|
||||||
currentDate.value = today;
|
// const today = new Date().toISOString().split('T')[0];
|
||||||
|
// currentDate.value = today;
|
||||||
});
|
});
|
||||||
|
|
||||||
function toSelectDate() {
|
function toSelectDate() {
|
||||||
navTo('/packageA/pages/selectDate/selectDate', {
|
navTo('/packageA/pages/selectDate/selectDate', {
|
||||||
query: {
|
query: {
|
||||||
date: currentDate.value,
|
date: currentDate.value,
|
||||||
|
record: true,
|
||||||
},
|
},
|
||||||
onBack: (res) => {
|
onBack: (res) => {
|
||||||
currentDate.value = res.date;
|
currentDate.value = res.date;
|
||||||
|
@@ -72,7 +72,7 @@ function searchCollection(e) {
|
|||||||
// list
|
// list
|
||||||
function getDataList(type = 'add') {
|
function getDataList(type = 'add') {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageState.page = 0;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 1;
|
pageState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
|
@@ -93,7 +93,7 @@ function handleScrollToLowerCompany() {
|
|||||||
|
|
||||||
function getJobList(type = 'add') {
|
function getJobList(type = 'add') {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageState.page = 0;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 1;
|
pageState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
@@ -121,7 +121,7 @@ function getJobList(type = 'add') {
|
|||||||
|
|
||||||
function getCompanyList(type = 'add') {
|
function getCompanyList(type = 'add') {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageCompanyState.page = 0;
|
pageCompanyState.page = 1;
|
||||||
pageCompanyState.maxPage = 1;
|
pageCompanyState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageCompanyState.page < pageCompanyState.maxPage) {
|
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) {
|
function getList(type = 'add', loading = true) {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageState.page = 0;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 1;
|
pageState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
|
@@ -52,6 +52,8 @@ const calendarData = ref([]);
|
|||||||
const current = ref({});
|
const current = ref({});
|
||||||
import { Solar, Lunar } from '@/lib/lunar-javascript@1.7.2.js';
|
import { Solar, Lunar } from '@/lib/lunar-javascript@1.7.2.js';
|
||||||
|
|
||||||
|
const isRecord = ref(false);
|
||||||
|
const recordNum = ref(4);
|
||||||
const pages = reactive({
|
const pages = reactive({
|
||||||
year: 0,
|
year: 0,
|
||||||
month: 0,
|
month: 0,
|
||||||
@@ -63,15 +65,21 @@ onLoad((options) => {
|
|||||||
date: options?.date || null,
|
date: options?.date || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
console.log(options);
|
if (options.record) {
|
||||||
initPagesDate();
|
isRecord.value = true;
|
||||||
addMonth();
|
initOldPagesDate();
|
||||||
addMonth();
|
new Array(recordNum.value + 1).fill(null).map(() => {
|
||||||
addMonth();
|
addMonth();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
initPagesDate();
|
||||||
|
new Array(recordNum.value).fill(null).map(() => {
|
||||||
|
addMonth();
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function backParams() {
|
function backParams() {
|
||||||
console.log(isValidDateString(current.value.date));
|
|
||||||
if (isValidDateString(current.value.date)) {
|
if (isValidDateString(current.value.date)) {
|
||||||
navBack({
|
navBack({
|
||||||
data: current.value,
|
data: current.value,
|
||||||
@@ -94,6 +102,7 @@ function isValidDateString(dateStr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onScrollBottom() {
|
function onScrollBottom() {
|
||||||
|
if (isRecord.value) return;
|
||||||
addMonth();
|
addMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,10 +110,22 @@ function selectDay(item) {
|
|||||||
current.value = 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() {
|
function initPagesDate() {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
pages.year = d.getFullYear();
|
|
||||||
pages.month = d.getMonth();
|
pages.month = d.getMonth();
|
||||||
|
pages.year = d.getFullYear();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMonth() {
|
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",
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
"navigationStyle": "custom"
|
"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",
|
"pagePath": "pages/chat/chat",
|
||||||
"iconPath": "static/tabbar/logo2copy.png",
|
"iconPath": "static/tabbar/logo3.png",
|
||||||
"selectedIconPath": "static/tabbar/logo2copy.png"
|
"selectedIconPath": "static/tabbar/logo3.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/msglog/msglog",
|
"pagePath": "pages/msglog/msglog",
|
||||||
|
@@ -110,8 +110,14 @@ const pageState = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
onLoad(() => {
|
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({
|
const result = getNextDates({
|
||||||
startDate: '2025-04-21',
|
startDate: currentDate,
|
||||||
});
|
});
|
||||||
weekList.value = result;
|
weekList.value = result;
|
||||||
getFair('refresh');
|
getFair('refresh');
|
||||||
@@ -123,9 +129,17 @@ function toSelectDate() {
|
|||||||
date: currentDay.value.fullDate,
|
date: currentDay.value.fullDate,
|
||||||
},
|
},
|
||||||
onBack: (res) => {
|
onBack: (res) => {
|
||||||
|
console.log(res);
|
||||||
const result = getNextDates({
|
const result = getNextDates({
|
||||||
startDate: res.date,
|
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;
|
weekList.value = result;
|
||||||
getFair('refresh');
|
getFair('refresh');
|
||||||
},
|
},
|
||||||
@@ -151,7 +165,7 @@ const handleScrollToLower = () => {
|
|||||||
|
|
||||||
function getFair(type = 'add') {
|
function getFair(type = 'add') {
|
||||||
if (type === 'refresh') {
|
if (type === 'refresh') {
|
||||||
pageState.page = 0;
|
pageState.page = 1;
|
||||||
pageState.maxPage = 1;
|
pageState.maxPage = 1;
|
||||||
}
|
}
|
||||||
if (type === 'add' && pageState.page < pageState.maxPage) {
|
if (type === 'add' && pageState.page < pageState.maxPage) {
|
||||||
@@ -262,7 +276,6 @@ function getNextDates({ startDate = '', count = 6 }) {
|
|||||||
date: formattedDate,
|
date: formattedDate,
|
||||||
fullDate,
|
fullDate,
|
||||||
day: '周' + dayOfWeek,
|
day: '周' + dayOfWeek,
|
||||||
isToday: i === 0,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -183,6 +183,10 @@
|
|||||||
</view>
|
</view>
|
||||||
<!-- btn -->
|
<!-- btn -->
|
||||||
<CollapseTransition :show="showfile">
|
<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="area-file">
|
||||||
<view class="file-card" @click="uploadCamera">
|
<view class="file-card" @click="uploadCamera">
|
||||||
<image class="card-img" src="/static/icon/file1.png"></image>
|
<image class="card-img" src="/static/icon/file1.png"></image>
|
||||||
@@ -957,12 +961,18 @@ image-margin-top = 40rpx
|
|||||||
transform: rotate(45deg)
|
transform: rotate(45deg)
|
||||||
transition: transform 0.5s ease;
|
transition: transform 0.5s ease;
|
||||||
}
|
}
|
||||||
|
.area-tips{
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #434343;
|
||||||
|
margin-top: 18rpx
|
||||||
|
}
|
||||||
.area-file
|
.area-file
|
||||||
display: grid
|
display: grid
|
||||||
width: 100%
|
width: 100%
|
||||||
grid-template-columns: repeat(3, 1fr)
|
grid-template-columns: repeat(3, 1fr)
|
||||||
grid-gap: 20rpx
|
grid-gap: 20rpx
|
||||||
padding: 32rpx 0 0 0;
|
padding: 20rpx 0 0 0;
|
||||||
.file-card
|
.file-card
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
|
@@ -304,7 +304,7 @@ function choosePosition(index) {
|
|||||||
getJobRecommend('refresh');
|
getJobRecommend('refresh');
|
||||||
} else {
|
} else {
|
||||||
// const id = useUserStore().userInfo.jobTitleId.split(',')[index];
|
// const id = useUserStore().userInfo.jobTitleId.split(',')[index];
|
||||||
pageState.search.jobTitle = useUserStore().userInfo.jobTitle[index];
|
pageState.search.jobTitle = userInfo.value.jobTitle[index];
|
||||||
inputText.value = '';
|
inputText.value = '';
|
||||||
getJobList('refresh');
|
getJobList('refresh');
|
||||||
}
|
}
|
||||||
|
@@ -4,12 +4,12 @@
|
|||||||
<!-- 顶部头部区域 -->
|
<!-- 顶部头部区域 -->
|
||||||
<view class="container-header">
|
<view class="container-header">
|
||||||
<view class="header-btnLf button-click" @click="changeType(0)" :class="{ active: state.current === 0 }">
|
<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>
|
||||||
<view class="header-btnLf button-click" @click="changeType(1)" :class="{ active: state.current === 1 }">
|
<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>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -39,7 +39,14 @@ import UnreadComponent from './unread.vue';
|
|||||||
const loadedMap = reactive([false, false]);
|
const loadedMap = reactive([false, false]);
|
||||||
const swiperRefs = [ref(null), ref(null)];
|
const swiperRefs = [ref(null), ref(null)];
|
||||||
const components = [ReadComponent, UnreadComponent];
|
const components = [ReadComponent, UnreadComponent];
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useReadMsg } from '@/stores/useReadMsg';
|
||||||
|
const { unreadCount } = storeToRefs(useReadMsg());
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
// 获取消息列表
|
||||||
|
useReadMsg().fetchMessages();
|
||||||
|
});
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
current: 0,
|
current: 0,
|
||||||
all: [{}],
|
all: [{}],
|
||||||
|
@@ -1,16 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
|
<scroll-view scroll-y class="main-scroll">
|
||||||
<view class="scrollmain">
|
<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">
|
<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>
|
||||||
<view class="card-info">
|
<view class="card-info">
|
||||||
<view class="info-title">
|
<view class="info-title">
|
||||||
<text>今日推荐</text>
|
<text>{{ item.title }}</text>
|
||||||
<view class="card-time">刚才</view>
|
<view class="card-time">{{ item.date }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-text line_2">这里有9个职位很适合你,快来看看吧</view>
|
<view class="info-text line_2">{{ item.subTitle || '消息' }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -19,7 +41,12 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, ref } from 'vue';
|
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);
|
const isLoaded = ref(false);
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
try {
|
try {
|
||||||
if (isLoaded.value) return;
|
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 });
|
defineExpose({ loadData });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -41,6 +83,9 @@ defineExpose({ loadData });
|
|||||||
}
|
}
|
||||||
.scrollmain{
|
.scrollmain{
|
||||||
padding: 28rpx
|
padding: 28rpx
|
||||||
|
}
|
||||||
|
.read{
|
||||||
|
|
||||||
}
|
}
|
||||||
.list-card
|
.list-card
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
@@ -57,9 +102,25 @@ defineExpose({ loadData });
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
margin-right: 30rpx;
|
margin-right: 30rpx;
|
||||||
|
position: relative;
|
||||||
.card-img-flame
|
.card-img-flame
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 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
|
.card-info
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -1,16 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
|
<scroll-view scroll-y class="main-scroll">
|
||||||
<view class="scrollmain">
|
<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">
|
<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>
|
||||||
<view class="card-info">
|
<view class="card-info">
|
||||||
<view class="info-title">
|
<view class="info-title">
|
||||||
<text>今日推荐</text>
|
<text>{{ item.title }}</text>
|
||||||
<view class="card-time">刚才</view>
|
<view class="card-time">{{ item.date }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-text line_2">这里有9个职位很适合你,快来看看吧</view>
|
<view class="info-text line_2">{{ item.subTitle || '消息' }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -19,7 +39,12 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, inject, ref } from 'vue';
|
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);
|
const isLoaded = ref(false);
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
try {
|
try {
|
||||||
if (isLoaded.value) return;
|
if (isLoaded.value) return;
|
||||||
@@ -30,7 +55,10 @@ async function loadData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleScrollToLower() {}
|
function seeDetail(item) {
|
||||||
|
console.log(item);
|
||||||
|
}
|
||||||
|
|
||||||
defineExpose({ loadData });
|
defineExpose({ loadData });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -41,6 +69,9 @@ defineExpose({ loadData });
|
|||||||
}
|
}
|
||||||
.scrollmain{
|
.scrollmain{
|
||||||
padding: 28rpx
|
padding: 28rpx
|
||||||
|
}
|
||||||
|
.read{
|
||||||
|
|
||||||
}
|
}
|
||||||
.list-card
|
.list-card
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
@@ -57,9 +88,25 @@ defineExpose({ loadData });
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
margin-right: 30rpx;
|
margin-right: 30rpx;
|
||||||
|
position: relative;
|
||||||
.card-img-flame
|
.card-img-flame
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 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
|
.card-info
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y class="Detailscroll-view" v-show="list.length" @scrolltolower="getJobList('add')">
|
<scroll-view scroll-y class="Detailscroll-view" v-show="list.length" @scrolltolower="getJobList('add')">
|
||||||
<view class="cards-box">
|
<view class="cards-box">
|
||||||
<renderJobs :list="list" :longitude="longitude" :latitude="latitude"></renderJobs>
|
<renderJobs :list="list" :longitude="longitudeVal" :latitude="latitudeVal"></renderJobs>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="main-content" v-show="!list.length">
|
<view class="main-content" v-show="!list.length">
|
||||||
@@ -44,12 +44,12 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { inject, ref, reactive } from 'vue';
|
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';
|
import SelectJobs from '@/components/selectJobs/selectJobs.vue';
|
||||||
const { $api, navBack } = inject('globalFunction');
|
const { $api, navBack } = inject('globalFunction');
|
||||||
import useLocationStore from '@/stores/useLocationStore';
|
import useLocationStore from '@/stores/useLocationStore';
|
||||||
const { getLocation, longitude, latitude } = useLocationStore();
|
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
|
||||||
const searchValue = ref('');
|
const searchValue = ref('');
|
||||||
const historyList = ref([]);
|
const historyList = ref([]);
|
||||||
const list = 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类
|
// BaseStore.js - 基础Store类
|
||||||
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
||||||
|
// import UniStorageHelper from '../common/UniStorageHelper'
|
||||||
import useChatGroupDBStore from './userChatGroupStore'
|
import useChatGroupDBStore from './userChatGroupStore'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
|
|
||||||
@@ -29,7 +30,12 @@ class BaseStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
initDB() {
|
initDB() {
|
||||||
|
// // #ifdef H5
|
||||||
this.db = new IndexedDBHelper(this.dbName, config.DBversion);
|
this.db = new IndexedDBHelper(this.dbName, config.DBversion);
|
||||||
|
// // #endif
|
||||||
|
// // #ifndef H5
|
||||||
|
// this.db = new UniStorageHelper(this.dbName, config.DBversion);
|
||||||
|
// // #endif
|
||||||
this.db.openDB([{
|
this.db.openDB([{
|
||||||
name: 'record',
|
name: 'record',
|
||||||
keyPath: "id",
|
keyPath: "id",
|
||||||
|
@@ -38,7 +38,8 @@ const useDictStore = defineStore("dict", () => {
|
|||||||
sex: [],
|
sex: [],
|
||||||
affiliation: [],
|
affiliation: [],
|
||||||
industry: [],
|
industry: [],
|
||||||
nature: []
|
nature: [],
|
||||||
|
noticeType: []
|
||||||
})
|
})
|
||||||
// political_affiliation
|
// political_affiliation
|
||||||
const getDictData = async (dictType, dictName) => {
|
const getDictData = async (dictType, dictName) => {
|
||||||
@@ -49,7 +50,8 @@ const useDictStore = defineStore("dict", () => {
|
|||||||
return data
|
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('education'),
|
||||||
getDictSelectOption('experience'),
|
getDictSelectOption('experience'),
|
||||||
getDictSelectOption('area', true),
|
getDictSelectOption('area', true),
|
||||||
@@ -57,6 +59,7 @@ const useDictStore = defineStore("dict", () => {
|
|||||||
getDictSelectOption('app_sex'),
|
getDictSelectOption('app_sex'),
|
||||||
getDictSelectOption('political_affiliation'),
|
getDictSelectOption('political_affiliation'),
|
||||||
getDictSelectOption('company_nature'),
|
getDictSelectOption('company_nature'),
|
||||||
|
getDictSelectOption('sys_notice_type'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
state.education = education;
|
state.education = education;
|
||||||
@@ -66,6 +69,7 @@ const useDictStore = defineStore("dict", () => {
|
|||||||
state.sex = sex;
|
state.sex = sex;
|
||||||
state.affiliation = affiliation;
|
state.affiliation = affiliation;
|
||||||
state.nature = nature
|
state.nature = nature
|
||||||
|
state.noticeType = noticeType
|
||||||
complete.value = true
|
complete.value = true
|
||||||
getIndustryDict() // 获取行业
|
getIndustryDict() // 获取行业
|
||||||
} catch (error) {
|
} 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 {
|
import {
|
||||||
ref
|
ref
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
|
||||||
import useDictStore from '@/stores/useDictStore';
|
import useDictStore from '@/stores/useDictStore';
|
||||||
import jobAnalyzer from '@/utils/jobAnalyzer';
|
import jobAnalyzer from '@/utils/jobAnalyzer';
|
||||||
import {
|
import {
|
||||||
|
@@ -6,11 +6,14 @@ import {
|
|||||||
} from 'vue'
|
} from 'vue'
|
||||||
import {
|
import {
|
||||||
createRequest
|
createRequest
|
||||||
} from '../utils/request';
|
} from '@/utils/request';
|
||||||
import similarityJobs from '@/utils/similarity_Job.js';
|
import similarityJobs from '@/utils/similarity_Job.js';
|
||||||
import {
|
import {
|
||||||
UUID
|
UUID
|
||||||
} from "@/lib/uuid-min.js";
|
} from "@/lib/uuid-min.js";
|
||||||
|
import {
|
||||||
|
useReadMsg
|
||||||
|
} from '@/stores/useReadMsg';
|
||||||
|
|
||||||
// 简历完成度计算
|
// 简历完成度计算
|
||||||
function getResumeCompletionPercentage(resume) {
|
function getResumeCompletionPercentage(resume) {
|
||||||
@@ -97,6 +100,8 @@ const useUserStore = defineStore("user", () => {
|
|||||||
const loginSetToken = async (value) => {
|
const loginSetToken = async (value) => {
|
||||||
token.value = value
|
token.value = value
|
||||||
uni.setStorageSync('token', value);
|
uni.setStorageSync('token', value);
|
||||||
|
// 获取消息列表
|
||||||
|
useReadMsg().fetchMessages()
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
return getUserResume()
|
return getUserResume()
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,6 @@ import {
|
|||||||
ref,
|
ref,
|
||||||
toRaw
|
toRaw
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import IndexedDBHelper from '@/common/IndexedDBHelper.js'
|
|
||||||
import baseDB from './BaseDBStore';
|
import baseDB from './BaseDBStore';
|
||||||
import {
|
import {
|
||||||
msg,
|
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