28 Commits

Author SHA1 Message Date
Apcallover
adc1c6ef06 flat: 暂存 2025-12-06 14:31:57 +08:00
Apcallover
09faeb3509 flat: 合并 2025-12-06 14:19:52 +08:00
Apcallover
0d5e3024bc flat:合并冲突 2025-12-03 11:08:53 +08:00
Apcallover
268648868f flat: 合并 2025-12-03 11:04:38 +08:00
7ce14fa7e2 日期选择样式优化 2025-11-28 18:17:44 +08:00
9a5bffae85 岗位推荐固定位置插入改为随机插入 2025-11-28 17:22:05 +08:00
51e67a8c8f fix 2025-11-27 11:46:59 +08:00
531681b74e fix 2025-11-27 11:20:45 +08:00
7e0ec650b1 fix 2025-11-27 10:59:39 +08:00
3a5d8ccb1a fix 2025-11-27 10:56:46 +08:00
34bad16bf4 fix 2025-11-27 10:41:05 +08:00
f5099e9cc0 fix pixi 2025-11-27 10:22:45 +08:00
4295199887 static 2025-11-27 10:03:51 +08:00
Apcallover
7322e0854e Merge branch 'main' into bin 2025-11-27 09:08:22 +08:00
Apcallover
d260e24265 flat: 修复语法错误 2025-11-25 16:23:00 +08:00
Apcallover
c75653b7a3 flat: 备份 2025-11-24 15:06:15 +08:00
xiebin
805b384958 fix 2025-11-21 15:05:32 +08:00
Apcallover
77f97892bc flat: 合并 2025-11-21 10:47:43 +08:00
Apcallover
20191c9454 flat: pixjs 2025-11-21 10:41:34 +08:00
fc2d0f90ec feat : 视频提示遮罩的显示.复用之前判断逻辑 2025-11-20 15:35:48 +08:00
6b20c045a9 style 简历匹配职位的点击emit 2025-11-20 14:30:01 +08:00
183c71da3c style 2025-11-20 14:12:42 +08:00
5e2f8ac169 style 2025-11-20 14:10:00 +08:00
bca67b7f25 style 2025-11-20 13:51:34 +08:00
83a1078a4d Merge remote-tracking branch 'origin/main' into bin 2025-11-20 13:50:49 +08:00
e4d100242b refactor : 重构首页的简历匹配职位 2025-11-20 13:50:09 +08:00
3eca164bde refactor : 重构首页样式 2025-11-18 15:24:35 +08:00
a7d6b8709c 首页重构列表已完成 2025-11-17 15:03:20 +08:00
37 changed files with 3171 additions and 234 deletions

View File

@@ -473,3 +473,8 @@ html {
.height-100 { .height-100 {
height: 100%; height: 100%;
} }
.pointEveNone {
pointer-events: none;
}

View File

@@ -1,17 +1,37 @@
<template> <template>
<view>{{ salaryText }}</view> <view>
<view v-if="!minSalary || !maxSalary">面议</view>
<view v-else class="texts">
<text class="num">{{ minSalary / 1000 }}</text>
<text class="unit">k</text>
<text class="gap">~</text>
<text class="num">{{ maxSalary / 1000 }}</text>
<text class="unit">k</text>
</view>
</view>
</template> </template>
<script setup> <script setup>
import { inject, computed } from 'vue'; import { inject, computed } from "vue";
import useDictStore from '../../stores/useDictStore'; import useDictStore from "../../stores/useDictStore";
const { minSalary, maxSalary, isMonth } = defineProps(['minSalary', 'maxSalary', 'isMonth']); const { minSalary, maxSalary } = defineProps(["minSalary", "maxSalary"]);
const salaryText = computed(() => {
if (!minSalary || !maxSalary) return '面议';
if (isMonth) {
return `${minSalary}-${maxSalary}/月`;
}
return `${minSalary / 1000}k-${maxSalary / 1000}k`;
});
</script> </script>
<style lang="scss" scoped>
.texts{
letter-spacing: 1rpx;
}
.num{
font-size: 32rpx;
font-weight: 500;
}
.unit{
font-size: 24rpx;
font-weight: 500;
}
.gap{
font-size: 32rpx;
font-weight: 500;
margin-left: 5rpx;
}
</style>

View File

@@ -86,8 +86,7 @@ export function usePagination(
const res = await requestFn(params) const res = await requestFn(params)
const rawData = res[dataKey] const rawData = res[dataKey]
const total = res[totalKey] || 99999999
console.log(total, rawData)
const data = typeof transformFn === 'function' ? transformFn(rawData) : rawData const data = typeof transformFn === 'function' ? transformFn(rawData) : rawData
if (type === 'refresh') { if (type === 'refresh') {
@@ -96,9 +95,9 @@ export function usePagination(
list.value.push(...data) list.value.push(...data)
} }
const total = res[totalKey] || list.value?.length
pageState.total = total pageState.total = total
pageState.maxPage = Math.ceil(total / pageState.pageSize) pageState.maxPage = Math.ceil(total / pageState.pageSize)
finished.value = list.value.length >= total finished.value = list.value.length >= total
empty.value = list.value.length === 0 empty.value = list.value.length === 0
} catch (err) { } catch (err) {

View File

@@ -31,6 +31,8 @@
<script type="text/javascript" src="https://isdapp.shandong.gov.cn/jmopen/jssdk/index.js"></script> <script type="text/javascript" src="https://isdapp.shandong.gov.cn/jmopen/jssdk/index.js"></script>
<!-- 只在内网有效 --> <!-- 只在内网有效 -->
<script type="text/javascript" src="./static/js/SM.js"></script> <script type="text/javascript" src="./static/js/SM.js"></script>
<script type="text/javascript" src="./static/js/pixi.min.js"></script>
</head> </head>
<body> <body>
<div id="app"><!--app-html--></div> <div id="app"><!--app-html--></div>

View File

@@ -80,7 +80,7 @@
"locale": "zh-Hans", "locale": "zh-Hans",
"h5": { "h5": {
"router": { "router": {
"base": "./", "base": "/app/",
"mode": "hash" "mode": "hash"
}, },
"title": "青岛智慧就业服务", "title": "青岛智慧就业服务",

View File

@@ -1,5 +1,11 @@
<template> <template>
<AppLayout title="个人信息" :sub-title="`完成度${percent}`" border back-gorund-color="#ffffff" :show-bg-image="false"> <AppLayout
title="个人信息"
:sub-title="`完成度${percent}`"
border
back-gorund-color="#ffffff"
:show-bg-image="false"
>
<template #headerleft> <template #headerleft>
<view class="btn mar_le20 button-click" @click="navBack">取消</view> <view class="btn mar_le20 button-click" @click="navBack">取消</view>
</template> </template>
@@ -22,21 +28,40 @@
<view class="content-sex"> <view class="content-sex">
<view class="sex-titile">性别</view> <view class="sex-titile">性别</view>
<view class="sext-ri"> <view class="sext-ri">
<view class="sext-box" :class="{ 'sext-boxactive': fromValue.sex === 0 }" @click="changeSex(0)"> </view> <view class="sext-box" :class="{ 'sext-boxactive': fromValue.sex === 0 }" @click="changeSex(0)">
<view class="sext-box" :class="{ 'sext-boxactive': fromValue.sex === 1 }" @click="changeSex(1)"> </view>
</view>
<view class="sext-box" :class="{ 'sext-boxactive': fromValue.sex === 1 }" @click="changeSex(1)">
</view>
</view> </view>
</view> </view>
<view class="content-input" @click="changeDateBirt"> <view class="content-input" @click="changeDateBirt">
<view class="input-titile">出生年月</view> <view class="input-titile">出生年月</view>
<input class="input-con triangle" v-model="fromValue.birthDate" disabled placeholder="请选择您的出生年月" /> <input
class="input-con triangle pointEveNone"
v-model="fromValue.birthDate"
disabled
placeholder="请选择您的出生年月"
/>
</view> </view>
<view class="content-input" @click="changeEducation"> <view class="content-input" @click="changeEducation">
<view class="input-titile">学历</view> <view class="input-titile">学历</view>
<input class="input-con triangle" v-model="state.educationText" disabled placeholder="请选择您的学历" /> <input
class="input-con triangle pointEveNone"
v-model="state.educationText"
disabled
placeholder="请选择您的学历"
/>
</view> </view>
<view class="content-input" @click="changePoliticalAffiliation"> <view class="content-input" @click="changePoliticalAffiliation">
<view class="input-titile">政治面貌</view> <view class="input-titile">政治面貌</view>
<input class="input-con triangle" v-model="state.politicalAffiliationText" disabled placeholder="请选择您的政治面貌" /> <input
class="input-con triangle pointEveNone"
v-model="state.politicalAffiliationText"
disabled
placeholder="请选择您的政治面貌"
/>
</view> </view>
<view class="content-input"> <view class="content-input">
<view class="input-titile">手机号码</view> <view class="input-titile">手机号码</view>
@@ -47,29 +72,29 @@
</template> </template>
<script setup> <script setup>
import { reactive, inject, watch, ref, onMounted } from "vue"; import { reactive, inject, watch, ref, onMounted } from 'vue';
import { onLoad, onShow } from "@dcloudio/uni-app"; import { onLoad, onShow } from '@dcloudio/uni-app';
const { $api, navTo, navBack, checkingPhoneRegExp } = inject("globalFunction"); const { $api, navTo, navBack, checkingPhoneRegExp } = inject('globalFunction');
import { storeToRefs } from "pinia"; import { storeToRefs } from 'pinia';
import useUserStore from "@/stores/useUserStore"; import useUserStore from '@/stores/useUserStore';
import useDictStore from "@/stores/useDictStore"; import useDictStore from '@/stores/useDictStore';
const { userInfo } = storeToRefs(useUserStore()); const { userInfo } = storeToRefs(useUserStore());
const { getUserResume } = useUserStore(); const { getUserResume } = useUserStore();
const { dictLabel, oneDictData } = useDictStore(); const { dictLabel, oneDictData } = useDictStore();
const openSelectPopup = inject("openSelectPopup"); const openSelectPopup = inject('openSelectPopup');
const percent = ref("0%"); const percent = ref('0%');
const state = reactive({ const state = reactive({
educationText: "", educationText: '',
politicalAffiliationText: "", politicalAffiliationText: '',
}); });
const fromValue = reactive({ const fromValue = reactive({
name: "", name: '',
sex: 0, sex: 0,
birthDate: "", birthDate: '',
education: "", education: '',
politicalAffiliation: "", politicalAffiliation: '',
avatar: "", avatar: '',
}); });
onLoad(() => { onLoad(() => {
initLoad(); initLoad();
@@ -92,23 +117,23 @@ function initLoad() {
fromValue.politicalAffiliation = userInfo.value.politicalAffiliation; fromValue.politicalAffiliation = userInfo.value.politicalAffiliation;
fromValue.avatar = userInfo.value.avatar; fromValue.avatar = userInfo.value.avatar;
// 回显 // 回显
state.educationText = dictLabel("education", userInfo.value.education); state.educationText = dictLabel('education', userInfo.value.education);
state.politicalAffiliationText = dictLabel("affiliation", userInfo.value.politicalAffiliation); state.politicalAffiliationText = dictLabel('affiliation', userInfo.value.politicalAffiliation);
const result = getFormCompletionPercent(fromValue); const result = getFormCompletionPercent(fromValue);
percent.value = result; percent.value = result;
} }
const confirm = () => { const confirm = () => {
if (!fromValue.name) { if (!fromValue.name) {
return $api.msg("请输入姓名"); return $api.msg('请输入姓名');
} }
if (!fromValue.birthDate) { if (!fromValue.birthDate) {
return $api.msg("请选择出生年月"); return $api.msg('请选择出生年月');
} }
if (!fromValue.education) { if (!fromValue.education) {
return $api.msg("请选择学历"); return $api.msg('请选择学历');
} }
if (!fromValue.politicalAffiliation) { if (!fromValue.politicalAffiliation) {
return $api.msg("请选择政治面貌"); return $api.msg('请选择政治面貌');
} }
// if (!checkingPhoneRegExp(fromValue.phone)) { // if (!checkingPhoneRegExp(fromValue.phone)) {
// return $api.msg('请输入正确手机号'); // return $api.msg('请输入正确手机号');
@@ -117,8 +142,8 @@ const confirm = () => {
...fromValue, ...fromValue,
age: calculateAge(fromValue.birthDate), age: calculateAge(fromValue.birthDate),
}; };
$api.createRequest("/app/user/resume", params, "post").then((resData) => { $api.createRequest('/app/user/resume', params, 'post').then((resData) => {
$api.msg("完成"); $api.msg('完成');
state.disbleDate = true; state.disbleDate = true;
getUserResume().then(() => { getUserResume().then(() => {
navBack(); navBack();
@@ -128,9 +153,13 @@ const confirm = () => {
const changeDateBirt = () => { const changeDateBirt = () => {
const datearray = generateDatePickerArrays(); const datearray = generateDatePickerArrays();
let defaultIndex = [0, 0, 0];
if (fromValue.birthDate) {
const defaultIndex = getDatePickerIndexes(fromValue.birthDate); const defaultIndex = getDatePickerIndexes(fromValue.birthDate);
}
console.log(defaultIndex);
openSelectPopup({ openSelectPopup({
title: "年龄段", title: '年龄段',
maskClick: true, maskClick: true,
data: datearray, data: datearray,
defaultIndex, defaultIndex,
@@ -140,16 +169,16 @@ const changeDateBirt = () => {
if (isValidDate(dateStr)) { if (isValidDate(dateStr)) {
fromValue.birthDate = dateStr; fromValue.birthDate = dateStr;
} else { } else {
$api.msg("没有这一天"); $api.msg('没有这一天');
} }
}, },
}); });
}; };
const changeEducation = () => { const changeEducation = () => {
openSelectPopup({ openSelectPopup({
title: "学历", title: '学历',
maskClick: true, maskClick: true,
data: [oneDictData("education")], data: [oneDictData('education')],
success: (_, [value]) => { success: (_, [value]) => {
fromValue.education = value.value; fromValue.education = value.value;
state.educationText = value.label; state.educationText = value.label;
@@ -162,9 +191,9 @@ const changeSex = (sex) => {
const changePoliticalAffiliation = () => { const changePoliticalAffiliation = () => {
openSelectPopup({ openSelectPopup({
title: "政治面貌", title: '政治面貌',
maskClick: true, maskClick: true,
data: [oneDictData("affiliation")], data: [oneDictData('affiliation')],
success: (_, [value]) => { success: (_, [value]) => {
fromValue.politicalAffiliation = value.value; fromValue.politicalAffiliation = value.value;
state.politicalAffiliationText = value.label; state.politicalAffiliationText = value.label;
@@ -181,17 +210,17 @@ function generateDatePickerArrays(startYear = 1975, endYear = new Date().getFull
years.push(y.toString()); years.push(y.toString());
} }
for (let m = 1; m <= 12; m++) { for (let m = 1; m <= 12; m++) {
months.push(m.toString().padStart(2, "0")); months.push(m.toString().padStart(2, '0'));
} }
for (let d = 1; d <= 31; d++) { for (let d = 1; d <= 31; d++) {
days.push(d.toString().padStart(2, "0")); days.push(d.toString().padStart(2, '0'));
} }
return [years, months, days]; return [years, months, days];
} }
function isValidDate(dateString) { function isValidDate(dateString) {
const [year, month, day] = dateString.split("-").map(Number); const [year, month, day] = dateString.split('-').map(Number);
const date = new Date(year, month - 1, day); // 月份从0开始 const date = new Date(year, month - 1, day); // 月份从0开始
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day; return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
@@ -218,22 +247,22 @@ function getFormCompletionPercent(form) {
for (const key in form) { for (const key in form) {
const value = form[key]; const value = form[key];
if (value !== "" && value !== null && value !== undefined) { if (value !== '' && value !== null && value !== undefined) {
if (typeof value === "number") { if (typeof value === 'number') {
filled += 1; filled += 1;
} else if (typeof value === "string" && value.trim() !== "") { } else if (typeof value === 'string' && value.trim() !== '') {
filled += 1; filled += 1;
} }
} }
} }
if (total === 0) return "0%"; if (total === 0) return '0%';
const percent = (filled / total) * 100; const percent = (filled / total) * 100;
return percent.toFixed(0) + "%"; // 取整,不要小数点 return percent.toFixed(0) + '%'; // 取整,不要小数点
} }
// 主函数 // 主函数
function getDatePickerIndexes(dateStr) { function getDatePickerIndexes(dateStr) {
const [year, month, day] = dateStr.split("-"); const [year, month, day] = dateStr.split('-');
const [years, months, days] = generateDatePickerArrays(); const [years, months, days] = generateDatePickerArrays();
@@ -246,18 +275,17 @@ function getDatePickerIndexes(dateStr) {
function selectAvatar() { function selectAvatar() {
uni.chooseImage({ uni.chooseImage({
sizeType: ["original", "compressed"], sizeType: ['original', 'compressed'],
sourceType: ["album", "camera"], sourceType: ['album', 'camera'],
count: 1, count: 1,
success: ({ tempFilePaths, tempFiles }) => { success: ({ tempFilePaths, tempFiles }) => {
$api $api.uploadFile(tempFilePaths[0], true)
.uploadFile(tempFilePaths[0], true)
.then((res) => { .then((res) => {
res = JSON.parse(res); res = JSON.parse(res);
if (res.msg) fromValue.avatar = res.msg; if (res.msg) fromValue.avatar = res.msg;
}) })
.catch((err) => { .catch((err) => {
$api.msg("上传失败"); $api.msg('上传失败');
}); });
}, },
fail: (error) => {}, fail: (error) => {},

View File

@@ -59,10 +59,10 @@ const pages = reactive({
year: 0, year: 0,
month: 0, month: 0,
}); });
const hasZphDateArray = ref([]); const hasZphDateArray = ref([]);
onLoad((options) => { onLoad((options) => {
updateDateArray();
if (options.date) { if (options.date) {
current.value = { current.value = {
date: options?.date || null, date: options?.date || null,

View File

@@ -0,0 +1,371 @@
<template>
<view class="container" id="pixi-box" ref="pixiContainerRef"></view>
</template>
<script setup>
import { onMounted, onUnmounted, ref, nextTick } from 'vue';
const emit = defineEmits(['tag-click']);
// DOM Ref
const pixiContainerRef = ref(null);
// PIXI 变量
let app = null;
let tagsContainer = null;
let activeTagInstances = [];
// 配置数据
const mockTags = [
{ name: '医生', bgColor: 0x0069fe, fontColor: 0xffffff, size: 17, opacity: 1.0, angle: 0, radius: 0 },
{
name: '工程师',
bgColor: 0x87e2ec,
fontColor: 0xffffff,
size: 14,
opacity: 1,
angle: -Math.PI / 2,
radius: 68,
tailRotation: Math.PI / 2,
},
{
name: '建筑师',
bgColor: 0xffebeb,
tailColor: 0xffe1e1,
fontColor: 0xff6969,
size: 11.5,
opacity: 1,
angle: -Math.PI / 4.2,
radius: 125,
tailRotation: (3 * Math.PI) / 4,
},
{
name: '律师',
bgColor: 0x21ea85,
fontColor: 0xffffff,
size: 15,
opacity: 1,
angle: -Math.PI / 10,
radius: 130,
tailRotation: (3 * Math.PI) / 4,
},
{
name: '记者',
bgColor: 0xebf3ff,
tailColor: 0xb9d3ff,
fontColor: 0x1d71ef,
size: 12,
opacity: 1,
angle: Math.PI / 120,
radius: 130,
tailRotation: (3 * Math.PI) / 3.4,
},
{
name: '程序员',
bgColor: 0xffd4b6,
fontColor: 0xffffff,
size: 14,
opacity: 1,
angle: Math.PI / 7,
radius: 120,
tailRotation: (5 * Math.PI) / 4,
},
{
name: '摄影师',
bgColor: 0xd8e5fe,
tailColor: 0xb9d3ff,
fontColor: 0x1d71ef,
size: 11,
opacity: 1,
angle: Math.PI / 3,
radius: 79,
tailRotation: (3 * Math.PI) / 2,
},
{
name: '设计师',
bgColor: 0xff9400,
fontColor: 0xffffff,
size: 14,
opacity: 1,
angle: (2 * Math.PI) / 3,
radius: 92,
tailRotation: (7 * Math.PI) / 4,
},
{
name: '心理咨询师',
bgColor: 0xebf3ff,
tailColor: 0xb9d3ff,
fontColor: 0x1d71ef,
size: 10.5,
opacity: 1,
angle: (5.4 * Math.PI) / 6,
radius: 110,
tailRotation:(3 * Math.PI) /1.78,
},
{
name: '护士',
bgColor: 0xff6969,
fontColor: 0xffffff,
size: 15,
opacity: 1,
angle: (6.3 * Math.PI) / 5.9,
radius: 110,
tailRotation: Math.PI / 4,
},
{
name: '会计',
bgColor: 0xfce9c9,
fontColor: 0xfbc55f,
size: 13,
opacity: 1,
angle: (7.2 * Math.PI) / 5.9,
radius: 120,
tailRotation: Math.PI / 4,
},
];
onMounted(async () => {
await nextTick();
setTimeout(() => {
initPixi();
}, 100);
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
if (app) {
app.destroy(true, { children: true, texture: true, baseTexture: true });
app = null;
}
});
const getContainerDOM = () => {
const refVal = pixiContainerRef.value;
if (!refVal) return document.getElementById('pixi-box');
if (refVal.$el) return refVal.$el;
return refVal;
};
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
const initPixi = () => {
const container = getContainerDOM();
if (!container) return;
const width = container.clientWidth || 300;
const height = container.clientHeight || 300;
if (app) return;
app = new PIXI.Application({
width: width,
height: height,
backgroundAlpha: 0,
backgroundColor: 0xf5f7fa,
antialias: true,
resolution: window.devicePixelRatio || 1,
autoDensity: true,
});
app.view.style.touchAction = 'auto';
container.appendChild(app.view);
tagsContainer = new PIXI.Container();
app.stage.addChild(tagsContainer);
renderScene(width, height);
};
const renderScene = (sw, sh) => {
tagsContainer.removeChildren();
activeTagInstances = [];
const baseSize = 375;
const scaleFactor = (Math.min(sw, sh) / baseSize) * 0.9;
mockTags.forEach((data, index) => {
const scaledRadius = data.radius * (scaleFactor < 1 ? 1 : scaleFactor * 0.8);
let x = sw / 2 + scaledRadius * Math.cos(data.angle);
let y = sh / 2 + scaledRadius * Math.sin(data.angle);
const tag = createTag(data, index);
tagsContainer.addChild(tag);
const safeW = tag.width / 2 + 10;
const safeH = tag.height / 2 + 10;
// 强制修正 x 和 y使其不超出屏幕
x = clamp(x, safeW, sw - safeW);
y = clamp(y, safeH, sh - safeH);
tag.x = x;
tag.y = y;
// 4. 保存元数据
tag.userData = {
originalX: x,
originalY: y,
angle: data.angle,
radius: scaledRadius,
floatOffset: Math.random() * Math.PI * 2,
floatSpeed: 0.01 + Math.random() * 0.02,
floatRange: 2 + Math.random() * 2,
safeH: safeH,
};
if (data.radius > 0) {
const tail = createCometTail( data.tailColor || data.bgColor, data.tailRotation, tag.width);
tag.addChildAt(tail, 0);
tag.updateTail = () => tail.updateAnim();
}
activeTagInstances.push(tag);
});
// 动画循环
app.ticker.add(() => {
const screenH = app.screen.height;
activeTagInstances.forEach((tag) => {
const meta = tag.userData;
if (meta) {
// 计算新的浮动位置
meta.floatOffset += meta.floatSpeed;
let nextY = meta.originalY + Math.sin(meta.floatOffset) * meta.floatRange;
// 再次进行边界检查
if (nextY < meta.safeH) nextY = meta.safeH;
if (nextY > screenH - meta.safeH) nextY = screenH - meta.safeH;
tag.y = nextY;
if (tag.updateTail) tag.updateTail();
}
});
});
};
const createTag = (tagData, index) => {
const tagGroup = new PIXI.Container();
tagGroup.eventMode = 'static';
tagGroup.cursor = 'pointer';
tagGroup.on('pointertap', () => emit('tag-click', tagData));
const text = new PIXI.Text(tagData.name, {
fontFamily: ['PingFang SC', 'Microsoft YaHei', 'Arial'],
fontSize: tagData.size,
fill: tagData.fontColor,
padding: 4,
resolution: 2,
});
text.anchor.set(0.5);
const paddingH = 26;
const paddingV = 10;
let bgWidth = text.width + paddingH;
let bgHeight = text.height + paddingV;
if (index === 0) bgWidth = Math.max(bgWidth, tagData.size * 4.5);
const bg = new PIXI.Graphics();
bg.beginFill(tagData.bgColor, tagData.opacity ?? 1);
bg.drawRoundedRect(-bgWidth / 2, -bgHeight / 2, bgWidth, bgHeight, bgHeight / 2);
bg.endFill();
tagGroup.addChild(bg);
tagGroup.addChild(text);
return tagGroup;
};
const createCometTail = (bgColor, tailRotation, parentWidth) => {
const tailGroup = new PIXI.Container();
const graphics = new PIXI.Graphics();
tailGroup.addChild(graphics);
const baseLength = 45;
const startWidth = parentWidth * 0.6;
const endWidth = 20;
let breathPhase = Math.random() * Math.PI * 2;
const breathSpeed = 0.04;
tailGroup.updateAnim = () => {
breathPhase += breathSpeed;
const breathScale = 0.85 + 0.15 * Math.sin(breathPhase);
graphics.clear();
const currentLength = baseLength * breathScale;
const cos = Math.cos(tailRotation);
const sin = Math.sin(tailRotation);
const perpX = -sin;
const perpY = cos;
const p1 = { x: perpX * (startWidth / 2), y: perpY * (startWidth / 2) };
const p2 = { x: -perpX * (startWidth / 2), y: -perpY * (startWidth / 2) };
const endCX = cos * currentLength;
const endCY = sin * currentLength;
const p3 = { x: endCX - perpX * (endWidth / 2), y: endCY - perpY * (endWidth / 2) };
const p4 = { x: endCX + perpX * (endWidth / 2), y: endCY + perpY * (endWidth / 2) };
const segments = 8;
for (let i = 0; i < segments; i++) {
const t1 = i / segments;
const t2 = (i + 1) / segments;
const alpha = 0.4 * (1 - t1);
const sp1 = { x: p1.x + (p4.x - p1.x) * t1, y: p1.y + (p4.y - p1.y) * t1 };
const sp2 = { x: p2.x + (p3.x - p2.x) * t1, y: p2.y + (p3.y - p2.y) * t1 };
const ep1 = { x: p1.x + (p4.x - p1.x) * t2, y: p1.y + (p4.y - p1.y) * t2 };
const ep2 = { x: p2.x + (p3.x - p2.x) * t2, y: p2.y + (p3.y - p2.y) * t2 };
graphics.beginFill(bgColor, alpha);
graphics.moveTo(sp1.x, sp1.y);
graphics.lineTo(sp2.x, sp2.y);
graphics.lineTo(ep2.x, ep2.y);
graphics.lineTo(ep1.x, ep1.y);
graphics.endFill();
}
};
tailGroup.updateAnim();
return tailGroup;
};
const handleResize = () => {
const container = getContainerDOM();
if (!app || !container) return;
const w = container.clientWidth || 300;
const h = container.clientHeight || 300;
app.renderer.resize(w, h);
activeTagInstances.forEach((tag) => {
const meta = tag.userData;
if (!meta) return;
let newX = w / 2 + meta.radius * Math.cos(meta.angle);
let newY = h / 2 + meta.radius * Math.sin(meta.angle);
const safeW = tag.width / 2 + 10;
const safeH = tag.height / 2 + 10;
meta.originalX = clamp(newX, safeW, w - safeW);
meta.originalY = clamp(newY, safeH, h - safeH);
meta.safeH = safeH; // 更新安全高度
tag.x = meta.originalX;
});
};
</script>
<style scoped>
.container {
width: 100%;
height: 500rpx;
position: relative;
overflow: hidden;
color: #b9d3ff;
}
</style>

View File

@@ -148,14 +148,14 @@
<!-- 筛选 --> <!-- 筛选 -->
<select-filter ref="selectFilterModel"></select-filter> <select-filter ref="selectFilterModel"></select-filter>
<!-- <view class="maskFristEntry" v-if="maskFristEntry"> <view class="maskFristEntry" v-if="maskFristEntry">
<view class="entry-content"> <view class="entry-content">
<text class="text1">左滑查看视频</text> <text class="text1">左滑查看视频</text>
<text class="text2">左滑查看视频</text> <text class="text2">左滑查看视频</text>
<view class="goExperience">去体验</view> <view class="goExperience">去体验</view>
<view class="maskFristEntry-Close" @click="closeFristEntry">1</view> <view class="maskFristEntry-Close" @click="closeFristEntry">1</view>
</view> </view>
</view> --> </view>
</view> </view>
</template> </template>
@@ -183,7 +183,7 @@ const waterfallsFlowRef = ref(null);
const loadmoreRef = ref(null); const loadmoreRef = ref(null);
const conditionSearch = ref({}); const conditionSearch = ref({});
const waterfallcolumn = ref(2); const waterfallcolumn = ref(2);
const maskFristEntry = ref(false); const maskFristEntry = ref(true);
const state = reactive({ const state = reactive({
tabIndex: 'all', tabIndex: 'all',
}); });

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,6 @@
ref="waterfallsFlowRef" ref="waterfallsFlowRef"
:column="columnCount" :column="columnCount"
:columnSpace="columnSpace" :columnSpace="columnSpace"
@loaded="imageloaded"
:value="list" :value="list"
> >
<template v-slot:default="job"> <template v-slot:default="job">
@@ -94,7 +93,7 @@ const state = reactive({
// 响应式搜索条件(可以被修改) // 响应式搜索条件(可以被修改)
const searchParams = ref({}); const searchParams = ref({});
const pageSize = ref(10); const pageSize = ref(10);
const { list, loading, refresh, loadMore } = usePagination( const { list, loading, refresh, loadMore,finished } = usePagination(
(params) => $api.createRequest('/app/job/littleVideo', params), (params) => $api.createRequest('/app/job/littleVideo', params),
dataToImg, // 转换函数 dataToImg, // 转换函数
{ {
@@ -106,10 +105,25 @@ const { list, loading, refresh, loadMore } = usePagination(
}, },
} }
); );
watch(()=>finished.value, (newVal) => {
if (newVal) {
// 确保瀑布流组件知道数据已加载完成
loadmoreRef.value?.change('noMore')
}else{
loadmoreRef.value?.change('more')
}
})
function imageloaded() { // function imageloaded() {
loadmoreRef.value?.change('more'); // nextTick(() => {
} // console.log('触发',finished.value)
// if (finished.value) {
// loadmoreRef.value?.change('noMore')
// } else {
// loadmoreRef.value?.change('more')
// }
// })
// }
const { columnCount, columnSpace } = useColumnCount(() => { const { columnCount, columnSpace } = useColumnCount(() => {
pageSize.value = 10 * (columnCount.value - 1); pageSize.value = 10 * (columnCount.value - 1);

View File

@@ -60,11 +60,13 @@
import { reactive, inject, watch, ref, onMounted } from 'vue'; import { reactive, inject, watch, ref, onMounted } from 'vue';
import Tabbar from '@/components/tabbar/midell-box.vue'; import Tabbar from '@/components/tabbar/midell-box.vue';
import { onLoad, onShow } from '@dcloudio/uni-app'; import { onLoad, onShow } from '@dcloudio/uni-app';
import IndexRefactor from './components/index-refactor.vue';
import IndexOne from './components/index-one.vue'; import IndexOne from './components/index-one.vue';
import IndexTwo from './components/index-two.vue'; import IndexTwo from './components/index-two.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 = [IndexOne, IndexTwo]; // const components = [IndexOne, IndexTwo];
const components = [IndexRefactor, IndexTwo];
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useReadMsg } from '@/stores/useReadMsg'; import { useReadMsg } from '@/stores/useReadMsg';
const { unreadCount } = storeToRefs(useReadMsg()); const { unreadCount } = storeToRefs(useReadMsg());

View File

@@ -1,6 +1,6 @@
<template> <template>
<scroll-view scroll-y class="main-scroll"> <scroll-view scroll-y class="main-scroll">
<view class="scrollmain"> <view v-if="msgList.length" class="scrollmain">
<view <view
class="list-card press-button" class="list-card press-button"
v-for="(item, index) in msgList" v-for="(item, index) in msgList"
@@ -38,6 +38,7 @@
</view> </view>
<empty v-if="!msgList.length"></empty> <empty v-if="!msgList.length"></empty>
</view> </view>
<empty v-else pdTop="200" content="暂无消息~"></empty>
</scroll-view> </scroll-view>
</template> </template>

View File

@@ -1,6 +1,6 @@
<template> <template>
<scroll-view scroll-y class="main-scroll"> <scroll-view scroll-y class="main-scroll">
<view class="scrollmain"> <view v-if="unreadMsgList.length" class="scrollmain">
<view <view
class="list-card press-button" class="list-card press-button"
v-for="(item, index) in unreadMsgList" v-for="(item, index) in unreadMsgList"
@@ -36,6 +36,7 @@
</view> </view>
<empty v-if="!unreadMsgList.length"></empty> <empty v-if="!unreadMsgList.length"></empty>
</view> </view>
<empty v-else pdTop="200" content="暂无消息~"></empty>
</scroll-view> </scroll-view>
</template> </template>

BIN
static/icon/add-circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/icon/ai-card-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
static/icon/flame3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 B

BIN
static/icon/index-robot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/icon/leart-gold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
static/icon/pintDate2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

BIN
static/icon/top-card-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
static/icon/video-mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

BIN
static/icon/work-img1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
static/icon/work-img2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

1108
static/js/pixi.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
<view <view
v-for="(item, index) in data.column" v-for="(item, index) in data.column"
:key="index" :key="index"
class="waterfalls-flow-column" class="waterfalls-flow-column "
:id="`waterfalls_flow_column_${index + 1}`" :id="`waterfalls_flow_column_${index + 1}`"
:msg="msg" :msg="msg"
:style="{ width: w, 'margin-left': index == 0 ? 0 : m }" :style="{ width: w, 'margin-left': index == 0 ? 0 : m }"