Merge branch 'master' of http://119.29.194.155:8894/zwq/zhxy-jsd
# Conflicts: # src/config.ts
This commit is contained in:
commit
a8a0edc5d4
@ -32,7 +32,7 @@ export const jsdFindPageTaskApi = async (params: any) => {
|
||||
};
|
||||
export const rwflFindRwlxsByRwId = async (params: any) => {
|
||||
return await get("/api/rwlx/findRwlxsByRwId", params);
|
||||
}
|
||||
};
|
||||
export const rwzxSaveApi = async (params: any) => {
|
||||
return await post("/api/rwzx/save", params);
|
||||
};
|
||||
@ -40,10 +40,9 @@ export const rwzxExecutedInfoByRwIdAndJsApi = async (params: any) => {
|
||||
return await get("/api/rwzx/executedInfoByRwIdAndJs", params);
|
||||
};
|
||||
|
||||
|
||||
export const rwFindInfoByRwId = async (params: any) => {
|
||||
return await get("/api/rw/findInfoByRwId", params);
|
||||
}
|
||||
};
|
||||
|
||||
export const fractionRuleApi = async () => {
|
||||
return await get(
|
||||
@ -75,6 +74,14 @@ export const jsdXkkcSaveApi = async (params: any) => {
|
||||
export const jsdXkXsListApi = async (params: any) => {
|
||||
return await get("/mobile/js/xkxs/list", params);
|
||||
};
|
||||
export const mobilejlstudentListApi = async (params: any) => {
|
||||
return await get("/mobile/jl/studentList", params);
|
||||
};
|
||||
|
||||
export const mobilejllistApi = async (params: any) => {
|
||||
const res = await get("/mobile/jl/list", params);
|
||||
return res.result;
|
||||
};
|
||||
|
||||
// 提交点名信息
|
||||
export const jsdXkdmListApi = async (params: any) => {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
const ip: string = "127.0.0.1:8897";
|
||||
// const ip: string = "192.168.239.1:8897";
|
||||
const ip: string = "yufangzc.com";
|
||||
// const ip: string = "yufangzc.com";
|
||||
const fwqip: string = "yufangzc.com";
|
||||
//打包服务器接口代理标识
|
||||
|
||||
@ -359,21 +359,21 @@
|
||||
{
|
||||
"path": "pages/view/notice/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "通知公告",
|
||||
"navigationBarTitleText": "发布接龙",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/view/notice/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "通知详情",
|
||||
"navigationBarTitleText": "接龙详情",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/view/notice/publish",
|
||||
"style": {
|
||||
"navigationBarTitleText": "发布通知",
|
||||
"navigationBarTitleText": "接龙推送",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
|
||||
@ -206,7 +206,7 @@ const sections = reactive<Section[]>([
|
||||
{
|
||||
id: "r7",
|
||||
icon: "file-text-fill-2",
|
||||
text: "选课详情",
|
||||
text: "课程介绍",
|
||||
show: true,
|
||||
path: "/pages/base/groupTeaching/xkList",
|
||||
},
|
||||
@ -218,6 +218,13 @@ const sections = reactive<Section[]>([
|
||||
show: true,
|
||||
path: "/pages/base/groupTeaching/dmXkList",
|
||||
},
|
||||
{
|
||||
id: "r8",
|
||||
icon: "draftfill",
|
||||
text: "发布接龙",
|
||||
show: true,
|
||||
path: "/pages/view/notice/index",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@ -226,29 +226,6 @@ if (getFile.rgqkList && getFile.rgqkList.length > 0) {
|
||||
});
|
||||
}
|
||||
|
||||
// 手动触发计算所有项目的任岗年限
|
||||
const calculateAllPositionYears = () => {
|
||||
education.xl.forEach((item: any, index: number) => {
|
||||
if (item.value.gwrzkstime) {
|
||||
const years = calculatePositionYears(
|
||||
item.value.gwrzkstime,
|
||||
item.value.gwrzjstime
|
||||
);
|
||||
item.value.gwrznx = years;
|
||||
console.log(`表单项${index}计算结果:`, {
|
||||
gwrzkstime: item.value.gwrzkstime,
|
||||
gwrzjstime: item.value.gwrzjstime,
|
||||
gwrznx: years,
|
||||
是否为0: years === "0",
|
||||
});
|
||||
} else {
|
||||
// 没有开始时间时,清空任岗年限
|
||||
item.value.gwrznx = "";
|
||||
}
|
||||
});
|
||||
forceUpdateKey.value++;
|
||||
};
|
||||
|
||||
function addEducation() {
|
||||
education.xl.push({ value: {} });
|
||||
// 强制重新渲染
|
||||
|
||||
@ -1,120 +1,81 @@
|
||||
<!-- src/pages/view/notice/index.vue -->
|
||||
<template>
|
||||
<view class="notice-list-page">
|
||||
<view class="jl-list-page">
|
||||
<!-- 列表内容 -->
|
||||
<BasicListLayout @register="register">
|
||||
<template #default="{ data }">
|
||||
<view class="notice-card" @click="goToDetail(data.id)">
|
||||
<template v-slot="{ data }">
|
||||
<view class="jl-card" @click="goToDetail(data.id)">
|
||||
<view class="card-header">
|
||||
<text class="notice-title">{{ data.title }}</text>
|
||||
<text class="notice-status" :class="getStatusClass(data.status)">{{
|
||||
data.statusText
|
||||
}}</text>
|
||||
<text class="jl-title">{{ data.jlmc }}</text>
|
||||
<text class="jl-status" :class="getStatusClass(data.jlStatus)">
|
||||
{{ getStatusText(data.jlStatus) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="card-body">
|
||||
<!-- 可选:显示封面缩略图 -->
|
||||
<image
|
||||
v-if="data.coverImage"
|
||||
:src="data.coverImage"
|
||||
v-if="data.jlfm"
|
||||
:src="imagUrl(data.jlfm)"
|
||||
mode="aspectFill"
|
||||
class="cover-thumbnail"
|
||||
></image>
|
||||
<text class="notice-excerpt">{{ data.excerpt }}</text>
|
||||
<rich-text class="jl-excerpt" :nodes="data.jlms"></rich-text>
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<text class="footer-item">发布者: {{ data.publisher }}</text>
|
||||
<text class="footer-item">{{ data.publishTime }}</text>
|
||||
<text class="footer-item" v-if="data.target"
|
||||
>范围: {{ data.target }}</text
|
||||
<text class="footer-item">发布者: {{ data.jsxm }}</text>
|
||||
<text class="footer-item">{{ formatTime(data.jlFbtime) }}</text>
|
||||
<text class="footer-item" v-if="data.bjmc"
|
||||
>范围: {{ data.njmc + data.bjmc }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</BasicListLayout>
|
||||
|
||||
<!-- 新建通知按钮 -->
|
||||
<view class="fab-button" @click="goToPublish">
|
||||
<uni-icons type="plusempty" size="24" color="#fff"></uni-icons>
|
||||
<template #bottom>
|
||||
<view class="white-bg-color py-5">
|
||||
<view class="flex-row items-center pb-10 pt-5">
|
||||
<u-button
|
||||
text="新增接龙"
|
||||
class="mx-15"
|
||||
type="primary"
|
||||
@click="goToPublish"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</BasicListLayout>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
|
||||
import { mobilejllistApi } from "@/api/base/server";
|
||||
import { imagUrl } from "@/utils";
|
||||
import BasicDragButton from "@/components/BasicDragButton/DragButton.vue";
|
||||
|
||||
interface NoticeItem {
|
||||
interface JlItem {
|
||||
id: string;
|
||||
title: string;
|
||||
excerpt: string; // 内容摘要
|
||||
status: "published" | "draft" | "ended"; // 状态
|
||||
statusText: string; // 状态文字
|
||||
publisher: string;
|
||||
publishTime: string;
|
||||
coverImage?: string; // 封面图 URL (可选)
|
||||
target?: string; // 通知范围 (可选)
|
||||
jlmc: string; // 接龙名称
|
||||
jlms: string; // 接龙描述
|
||||
jlStatus: string; // 发布状态:A已发布,B暂存
|
||||
jlFbr: string; // 发布人
|
||||
jlFbtime: string; // 发布时间
|
||||
jlfm: string; // 接龙封面
|
||||
njmc: string;
|
||||
bjmc: string; // 班级名称
|
||||
jlkstime: string; // 接龙开始时间
|
||||
jljstime: string; // 接龙结束时间
|
||||
jsxm?: string;
|
||||
}
|
||||
|
||||
// 模拟获取通知列表数据的 API 函数
|
||||
const fetchNoticeList = async (params: any): Promise<any> => {
|
||||
// 返回类型改为 Promise<any>
|
||||
console.log("Fetching notice list with params:", params);
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
// 根据 params.pageNo 和 params.pageSize 模拟分页
|
||||
const pageNo = params.pageNo || 1;
|
||||
const pageSize = params.pageSize || 10;
|
||||
const total = 35; // 模拟总数
|
||||
const mockData: NoticeItem[] = [];
|
||||
const startIndex = (pageNo - 1) * pageSize;
|
||||
|
||||
for (let i = 0; i < pageSize; i++) {
|
||||
const currentIndex = startIndex + i;
|
||||
if (currentIndex >= total) break; // 超出总数则停止
|
||||
|
||||
const status =
|
||||
currentIndex % 3 === 0
|
||||
? "draft"
|
||||
: currentIndex % 3 === 1
|
||||
? "published"
|
||||
: "ended";
|
||||
mockData.push({
|
||||
id: `notice_${currentIndex + 1}`,
|
||||
title: `重要通知标题 ${currentIndex + 1}`,
|
||||
excerpt: `这是通知 ${currentIndex + 1} 的内容摘要,只显示一部分...`,
|
||||
status: status,
|
||||
statusText:
|
||||
status === "draft"
|
||||
? "草稿"
|
||||
: status === "published"
|
||||
? "已发布"
|
||||
: "已结束",
|
||||
publisher: "教务处",
|
||||
publishTime: `2024-06-${String(
|
||||
18 - Math.floor(currentIndex / 5)
|
||||
).padStart(2, "0")}`,
|
||||
target: currentIndex % 2 === 0 ? "一年级3班" : "全体教师",
|
||||
// coverImage: i % 3 === 0 ? '/static/mock/cover.png' : undefined
|
||||
});
|
||||
}
|
||||
|
||||
resolve({
|
||||
message: "获取成功",
|
||||
resultCode: 1,
|
||||
rows: mockData,
|
||||
total: total,
|
||||
});
|
||||
}, 800); // 模拟网络延迟
|
||||
});
|
||||
};
|
||||
|
||||
// 使用 BasicListLayout
|
||||
const [register, { reload }] = useLayout({
|
||||
api: fetchNoticeList,
|
||||
api: mobilejllistApi, // 必须提供 api,即使使用了 query
|
||||
componentProps: {},
|
||||
});
|
||||
|
||||
// 跳转到详情页
|
||||
const goToDetail = (noticeId: string) => {
|
||||
const goToDetail = (jlId: string) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/view/notice/detail?id=${noticeId}`,
|
||||
url: `/pages/view/notice/detail?id=${jlId}`,
|
||||
});
|
||||
};
|
||||
|
||||
@ -126,21 +87,37 @@ const goToPublish = () => {
|
||||
};
|
||||
|
||||
// 根据状态获取对应的 CSS 类
|
||||
const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
if (status === "published") return "status-published";
|
||||
if (status === "draft") return "status-draft";
|
||||
if (status === "ended") return "status-ended";
|
||||
return "";
|
||||
const getStatusClass = (status: string) => {
|
||||
if (status === "A") return "status-published";
|
||||
if (status === "B") return "status-draft";
|
||||
return "status-ended";
|
||||
};
|
||||
|
||||
// 根据状态获取状态文字
|
||||
const getStatusText = (status: string) => {
|
||||
if (status === "A") return "已发布";
|
||||
if (status === "B") return "暂存";
|
||||
return "已结束";
|
||||
};
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (timeStr: string) => {
|
||||
if (!timeStr) return "";
|
||||
const date = new Date(timeStr);
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
|
||||
2,
|
||||
"0"
|
||||
)}-${String(date.getDate()).padStart(2, "0")}`;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.notice-list-page {
|
||||
.jl-list-page {
|
||||
position: relative; // 为了 FAB 定位
|
||||
min-height: 100vh; // 确保 FAB 总在视图内
|
||||
}
|
||||
|
||||
.notice-card {
|
||||
.jl-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
@ -155,7 +132,7 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
align-items: flex-start;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.notice-title {
|
||||
.jl-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
@ -169,7 +146,7 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.notice-status {
|
||||
.jl-status {
|
||||
font-size: 12px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
@ -180,9 +157,11 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
&.status-published {
|
||||
background-color: #19be6b; // 绿色-已发布
|
||||
}
|
||||
|
||||
&.status-draft {
|
||||
background-color: #ff9f0a; // 橙色-草稿
|
||||
background-color: #ff9f0a; // 橙色-暂存
|
||||
}
|
||||
|
||||
&.status-ended {
|
||||
background-color: #999999; // 灰色-已结束
|
||||
}
|
||||
@ -198,7 +177,8 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
margin-right: 10px;
|
||||
float: left; // 文字环绕图片
|
||||
}
|
||||
.notice-excerpt {
|
||||
|
||||
.jl-excerpt {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
@ -209,12 +189,6 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
// 清除浮动影响(如果用了 float)
|
||||
// &::after {
|
||||
// content: "";
|
||||
// display: table;
|
||||
// clear: both;
|
||||
// }
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
@ -232,11 +206,8 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
}
|
||||
}
|
||||
|
||||
// FAB 按钮样式
|
||||
// FAB 按钮样式 - 由 DragButton 组件处理定位
|
||||
.fab-button {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
bottom: 40px; // 根据需要调整距离底部的距离
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #4477ee;
|
||||
@ -245,6 +216,7 @@ const getStatusClass = (status: "published" | "draft" | "ended") => {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 空列表样式已由 BasicListLayout 组件处理,移除此样式 */
|
||||
</style>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<view class="cover-upload-wrapper">
|
||||
<CustomUpload
|
||||
field="coverImage"
|
||||
:value="formData.coverImage"
|
||||
:value="formData.coverImage ? imagUrl(formData.coverImage) : ''"
|
||||
@select="handleCoverSelected"
|
||||
@close="handleCoverClosed"
|
||||
>
|
||||
@ -80,21 +80,13 @@
|
||||
<view class="add-icon"
|
||||
><uni-icons type="plusempty" size="20" color="#ccc"></uni-icons
|
||||
></view>
|
||||
<text class="placeholder-text"
|
||||
>添加图文/视频/文件/公众号/小程序等</text
|
||||
>
|
||||
<text class="placeholder-text">添加图文/视频/文件</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-card">
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="combinedClassRange"
|
||||
:value="selectedClassIndex"
|
||||
@change="onClassPickerChange"
|
||||
>
|
||||
<view class="card-header picker-header">
|
||||
<view class="card-header picker-header" @click="showClassTree">
|
||||
<text class="section-title">按名单填写</text>
|
||||
<view class="target-class">
|
||||
<text :class="{ placeholder: !formData.targetClass }">{{
|
||||
@ -103,22 +95,20 @@
|
||||
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="name-tags">
|
||||
<text
|
||||
v-for="name in formData.targetNames"
|
||||
:key="name"
|
||||
v-for="(name, index) in displayNames"
|
||||
:key="name + index"
|
||||
class="name-tag"
|
||||
>{{ name }}</text
|
||||
>
|
||||
<button
|
||||
v-if="formData.targetNames.length > 0"
|
||||
size="mini"
|
||||
type="default"
|
||||
class="modify-btn"
|
||||
@click="handleModifyNames"
|
||||
</view>
|
||||
<view
|
||||
v-if="formData.targetNames.length > maxDisplayCount"
|
||||
class="more-btn-container"
|
||||
>
|
||||
修改
|
||||
<button size="mini" class="more-btn-full" @click="showAllStudents">
|
||||
更多({{ formData.targetNames.length - maxDisplayCount }})
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
@ -166,7 +156,9 @@
|
||||
<!-- Bottom slot -->
|
||||
<template #bottom>
|
||||
<view class="bottom-actions">
|
||||
<button class="action-btn draft-btn" @click="saveDraft">保存草稿</button>
|
||||
<button class="action-btn draft-btn" @click="saveDraft">
|
||||
保存草稿
|
||||
</button>
|
||||
<button class="action-btn preview-btn" @click="previewNotice">
|
||||
预览
|
||||
</button>
|
||||
@ -176,6 +168,51 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 班级选择树 -->
|
||||
<BasicTree
|
||||
ref="treeRef"
|
||||
:range="treeData"
|
||||
idKey="key"
|
||||
rangeKey="title"
|
||||
title="选择班级"
|
||||
:multiple="true"
|
||||
:selectParent="false"
|
||||
@confirm="onTreeConfirm"
|
||||
@cancel="onTreeCancel"
|
||||
/>
|
||||
|
||||
<!-- 学生名单弹窗 -->
|
||||
<view
|
||||
v-if="showStudentModal"
|
||||
class="student-modal-mask"
|
||||
@click="closeStudentModal"
|
||||
>
|
||||
<view class="student-modal" @click.stop>
|
||||
<view class="student-modal-header">
|
||||
<text class="modal-title">全部学生名单</text>
|
||||
<text class="student-count"
|
||||
>共{{ formData.targetNames.length }}人</text
|
||||
>
|
||||
<uni-icons
|
||||
type="closeempty"
|
||||
size="20"
|
||||
color="#999"
|
||||
@click="closeStudentModal"
|
||||
class="close-icon"
|
||||
></uni-icons>
|
||||
</view>
|
||||
<scroll-view scroll-y class="student-modal-content">
|
||||
<view class="all-student-tags">
|
||||
<text
|
||||
v-for="(name, index) in formData.targetNames"
|
||||
:key="name + index"
|
||||
class="student-tag"
|
||||
>{{ name }}</text
|
||||
>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
@ -183,6 +220,10 @@
|
||||
import { ref, reactive, computed } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import CustomUpload from "/src/components/BasicUpload/CustomUpload.vue";
|
||||
import BasicTree from "@/components/BasicTree/Tree.vue";
|
||||
import { attachmentUpload } from "@/api/system/upload";
|
||||
import { imagUrl } from "@/utils";
|
||||
import { findAllNjBjTree, mobilejlstudentListApi } from "@/api/base/server";
|
||||
|
||||
interface Attachment {
|
||||
name: string;
|
||||
@ -200,6 +241,8 @@ interface FormData {
|
||||
targetClass: string;
|
||||
targetNames: string[];
|
||||
targetStudentIds: string[];
|
||||
targetNjIds: string[]; // 年级ID数组
|
||||
targetBjIds: string[]; // 班级ID数组
|
||||
signatureRequired: boolean;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
@ -215,6 +258,8 @@ const formData = reactive<FormData>({
|
||||
targetClass: "",
|
||||
targetNames: [],
|
||||
targetStudentIds: [],
|
||||
targetNjIds: [],
|
||||
targetBjIds: [],
|
||||
signatureRequired: false,
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
@ -225,38 +270,40 @@ const signatureStatusText = computed(() => {
|
||||
return formData.signatureRequired ? "启用" : "不启用";
|
||||
});
|
||||
|
||||
const classList = ref([
|
||||
{ id: "g1c1", name: "一年级1班" },
|
||||
{ id: "g1c2", name: "一年级2班" },
|
||||
{ id: "g1c3", name: "一年级3班" },
|
||||
{ id: "g1c4", name: "一年级4班" },
|
||||
{ id: "g1c5", name: "一年级5班" },
|
||||
{ id: "g2c1", name: "二年级1班" },
|
||||
{ id: "g2c2", name: "二年级2班" },
|
||||
{ id: "g2c3", name: "二年级3班" },
|
||||
{ id: "g3c1", name: "三年级1班" },
|
||||
{ id: "g3c2", name: "三年级2班" },
|
||||
{ id: "g3c3", name: "三年级3班" },
|
||||
{ id: "g3c4", name: "三年级4班" },
|
||||
{ id: "g4c1", name: "四年级1班" },
|
||||
{ id: "g4c2", name: "四年级2班" },
|
||||
{ id: "g5c1", name: "五年级1班" },
|
||||
{ id: "g5c2", name: "五年级2班" },
|
||||
{ id: "g5c3", name: "五年级3班" },
|
||||
{ id: "g6c1", name: "六年级1班" },
|
||||
{ id: "g6c2", name: "六年级2班" },
|
||||
]);
|
||||
// 树形数据
|
||||
const treeData = ref([]);
|
||||
const treeRef = ref();
|
||||
|
||||
const combinedClassRange = computed(() => {
|
||||
return classList.value.map((cls) => cls.name);
|
||||
// 学生显示相关
|
||||
const maxDisplayCount = 24; // 最多显示24个学生(4行×6列)
|
||||
const showStudentModal = ref(false);
|
||||
|
||||
// 计算显示的学生名单(最多显示前24个)
|
||||
const displayNames = computed(() => {
|
||||
return formData.targetNames.slice(0, maxDisplayCount);
|
||||
});
|
||||
|
||||
const selectedClassIndex = computed(() => {
|
||||
const index = classList.value.findIndex(
|
||||
(cls) => cls.name === formData.targetClass
|
||||
);
|
||||
return index >= 0 ? index : 0;
|
||||
});
|
||||
// 加载树形数据
|
||||
const loadTreeData = async () => {
|
||||
try {
|
||||
const res = await findAllNjBjTree();
|
||||
if (res.resultCode === 1 && res.result) {
|
||||
// 转换数据格式以适配 BasicTree 组件
|
||||
treeData.value = res.result.map((item: any) => ({
|
||||
key: item.key,
|
||||
title: item.title,
|
||||
children: item.children || [],
|
||||
}));
|
||||
console.log("树形数据加载成功:", treeData.value);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("加载树形数据失败:", error);
|
||||
uni.showToast({ title: "加载班级数据失败", icon: "error" });
|
||||
}
|
||||
};
|
||||
|
||||
// 在组件挂载时加载数据
|
||||
loadTreeData();
|
||||
|
||||
const fetchStudentsByClass = async (className: string): Promise<string[]> => {
|
||||
console.log(`模拟获取班级 [${className}] 的学生列表...`);
|
||||
@ -281,40 +328,42 @@ const fetchStudentsByClass = async (className: string): Promise<string[]> => {
|
||||
return mockStudents;
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
if (options && options.id) {
|
||||
noticeId.value = options.id;
|
||||
uni.setNavigationBarTitle({ title: "编辑通知" });
|
||||
formData.title = "关于五一放假的通知 (编辑)";
|
||||
formData.content = "根据校历安排,现将2024年五一劳动节放假安排通知如下...";
|
||||
formData.targetClass = "二年级1班";
|
||||
formData.targetNames = ["张三", "李四"];
|
||||
formData.targetStudentIds = ["s201-mock", "s202-mock"];
|
||||
formData.signatureRequired = true;
|
||||
formData.startTime = "2024-04-30 18:00:00";
|
||||
formData.endTime = "2024-05-05 23:59:59";
|
||||
if (formData.targetClass && noticeId.value) {
|
||||
fetchStudentsByClass(formData.targetClass).then((students) => {
|
||||
formData.targetNames = students;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
uni.setNavigationBarTitle({ title: "发布通知" });
|
||||
}
|
||||
});
|
||||
onLoad((options) => {});
|
||||
|
||||
const handleCoverSelected = (e: any) => {
|
||||
console.log("选择封面 (CustomUpload):", e);
|
||||
const handleCoverSelected = async (e: any) => {
|
||||
if (e.tempFilePaths && e.tempFilePaths.length > 0) {
|
||||
formData.coverImage = e.tempFilePaths[0];
|
||||
console.log("封面临时路径:", formData.coverImage);
|
||||
const tempFilePath = e.tempFilePaths[0];
|
||||
|
||||
try {
|
||||
uni.showLoading({ title: "上传中..." });
|
||||
|
||||
// 直接使用 tempFilePath 作为 Blob 传给接口
|
||||
const uploadResult: any = await attachmentUpload(tempFilePath as any);
|
||||
|
||||
if (
|
||||
uploadResult.resultCode === 1 &&
|
||||
uploadResult.result &&
|
||||
uploadResult.result.length > 0
|
||||
) {
|
||||
// 保存原始的 filePath(用于提交到服务器)
|
||||
const originalPath = uploadResult.result[0].filePath;
|
||||
formData.coverImage = originalPath;
|
||||
uni.showToast({ title: "封面上传成功", icon: "success" });
|
||||
} else {
|
||||
throw new Error("上传响应格式异常");
|
||||
}
|
||||
} catch (error) {
|
||||
uni.showToast({ title: "封面上传失败", icon: "error" });
|
||||
formData.coverImage = null;
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
} else {
|
||||
console.error("无法从选择事件中获取封面路径:", e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCoverClosed = (field: string) => {
|
||||
console.log(`删除封面 (CustomUpload): field=${field}`);
|
||||
if (field === "coverImage") {
|
||||
formData.coverImage = null;
|
||||
}
|
||||
@ -324,12 +373,16 @@ const addAttachment = () => {
|
||||
uni.chooseFile({
|
||||
count: 5,
|
||||
type: "all",
|
||||
success: (res) => {
|
||||
success: async (res) => {
|
||||
const tempFiles = res.tempFiles;
|
||||
if (Array.isArray(tempFiles) && tempFiles.length > 0) {
|
||||
tempFiles.forEach((file: any) => {
|
||||
uni.showLoading({ title: "上传中..." });
|
||||
|
||||
try {
|
||||
for (const file of tempFiles) {
|
||||
const fileInfo = file as any; // 强制类型转换避免类型检查错误
|
||||
let fileType = "file";
|
||||
const fileName = file.name || "";
|
||||
const fileName = fileInfo.name || "";
|
||||
const fileExtension = fileName.split(".").pop()?.toLowerCase();
|
||||
|
||||
if (
|
||||
@ -349,22 +402,45 @@ const addAttachment = () => {
|
||||
}
|
||||
|
||||
if (
|
||||
file.type &&
|
||||
typeof file.type === "string" &&
|
||||
(file.type.startsWith("image/") ||
|
||||
file.type.startsWith("video/") ||
|
||||
file.type.startsWith("audio/"))
|
||||
fileInfo.type &&
|
||||
typeof fileInfo.type === "string" &&
|
||||
(fileInfo.type.startsWith("image/") ||
|
||||
fileInfo.type.startsWith("video/") ||
|
||||
fileInfo.type.startsWith("audio/"))
|
||||
) {
|
||||
fileType = file.type.split("/")[0];
|
||||
fileType = fileInfo.type.split("/")[0];
|
||||
}
|
||||
|
||||
// 直接使用文件路径作为 Blob 传给接口
|
||||
const uploadResult: any = await attachmentUpload(
|
||||
fileInfo.path as any
|
||||
);
|
||||
|
||||
if (
|
||||
uploadResult.resultCode === 1 &&
|
||||
uploadResult.result &&
|
||||
uploadResult.result.length > 0
|
||||
) {
|
||||
// 保存原始的 filePath(用于提交到服务器)
|
||||
const originalPath = uploadResult.result[0].filePath;
|
||||
formData.attachments.push({
|
||||
name: fileName,
|
||||
type: fileType,
|
||||
url: file.path,
|
||||
size: file.size,
|
||||
});
|
||||
url: originalPath, // 保存原始路径
|
||||
size: fileInfo.size,
|
||||
});
|
||||
} else {
|
||||
uni.showToast({ title: `${fileName} 上传失败`, icon: "error" });
|
||||
}
|
||||
}
|
||||
|
||||
uni.showToast({ title: "附件上传完成", icon: "success" });
|
||||
} catch (error) {
|
||||
console.error("附件上传失败:", error);
|
||||
uni.showToast({ title: "附件上传失败", icon: "error" });
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
} else {
|
||||
console.log("未选择任何文件或返回结果异常,或 tempFiles 不是数组");
|
||||
}
|
||||
@ -391,38 +467,124 @@ const getAttachmentIcon = (type: string): string => {
|
||||
|
||||
const previewAttachment = (attachment: Attachment) => {
|
||||
console.log("预览附件:", attachment);
|
||||
uni.showToast({ title: `预览 ${attachment.name} 功能待实现`, icon: "none" });
|
||||
// 如果是图片类型,可以预览
|
||||
if (attachment.type === "image") {
|
||||
const fullUrl = imagUrl(attachment.url);
|
||||
uni.previewImage({
|
||||
urls: [fullUrl],
|
||||
current: fullUrl,
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: `预览 ${attachment.name} 功能待实现`,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onClassPickerChange = async (e: any) => {
|
||||
const index = e.detail.value;
|
||||
const selectedClass = classList.value[index];
|
||||
if (selectedClass && selectedClass.name !== formData.targetClass) {
|
||||
formData.targetClass = selectedClass.name;
|
||||
// 显示班级选择树
|
||||
const showClassTree = () => {
|
||||
if (treeRef.value) {
|
||||
treeRef.value._show();
|
||||
}
|
||||
};
|
||||
|
||||
// 树形选择确认
|
||||
const onTreeConfirm = async (selectedItems: any[]) => {
|
||||
console.log("选择的班级:", selectedItems);
|
||||
if (selectedItems.length > 0) {
|
||||
// 处理多选情况
|
||||
const classNames = selectedItems.map((item) => item.title);
|
||||
formData.targetClass = classNames.join(", ");
|
||||
formData.targetNames = [];
|
||||
formData.targetStudentIds = [];
|
||||
formData.targetNjIds = [];
|
||||
formData.targetBjIds = [];
|
||||
|
||||
try {
|
||||
const students = await fetchStudentsByClass(formData.targetClass);
|
||||
formData.targetNames = students;
|
||||
uni.showLoading({ title: "获取学生列表中..." });
|
||||
|
||||
// 提取年级ID和班级ID
|
||||
const njIds: string[] = [];
|
||||
const bjIds: string[] = [];
|
||||
|
||||
selectedItems.forEach((item) => {
|
||||
// 如果选择的是班级(有parents表示是班级)
|
||||
if (item.parents && item.parents.length > 0) {
|
||||
const njId = item.parents[0].key; // 年级ID:parents[0].key
|
||||
const bjId = item.key; // 班级ID:item.key
|
||||
njIds.push(njId);
|
||||
bjIds.push(bjId);
|
||||
console.log(
|
||||
`选择班级: ${item.title}, 年级ID: ${njId}, 班级ID: ${bjId}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (njIds.length > 0 && bjIds.length > 0) {
|
||||
// 对年级ID去重
|
||||
const uniqueNjIds = [...new Set(njIds)];
|
||||
|
||||
// 保存选择的年级ID和班级ID到formData中
|
||||
formData.targetNjIds = uniqueNjIds;
|
||||
formData.targetBjIds = bjIds;
|
||||
|
||||
// 调用接口获取学生列表
|
||||
const params = {
|
||||
njId: uniqueNjIds.join(","),
|
||||
bjId: bjIds.join(","),
|
||||
};
|
||||
|
||||
const response = await mobilejlstudentListApi(params);
|
||||
|
||||
if (response && response.resultCode === 1 && response.result) {
|
||||
// 提取学生姓名,尝试多个可能的字段名
|
||||
const studentNames = response.result.map(
|
||||
(student: any) =>
|
||||
student.xsxm ||
|
||||
student.name ||
|
||||
student.studentName ||
|
||||
student.xm ||
|
||||
"未知姓名"
|
||||
);
|
||||
formData.targetNames = studentNames;
|
||||
formData.targetStudentIds = response.result.map(
|
||||
(student: any) =>
|
||||
student.id || student.xsId || student.studentId || ""
|
||||
);
|
||||
} else {
|
||||
throw new Error("获取学生列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: `已选择 ${selectedItems.length} 个班级`,
|
||||
icon: "success",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("获取学生列表失败:", error);
|
||||
uni.showToast({ title: "获取学生列表失败", icon: "none" });
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: "获取学生列表失败", icon: "error" });
|
||||
// 如果接口失败,使用模拟数据
|
||||
formData.targetNames = await fetchStudentsByClass(formData.targetClass);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleModifyNames = () => {
|
||||
const selectedClassObj = classList.value.find(
|
||||
(cls) => cls.name === formData.targetClass
|
||||
);
|
||||
if (!selectedClassObj) {
|
||||
uni.showToast({ title: "请先选择班级", icon: "none" });
|
||||
return;
|
||||
}
|
||||
const classId = selectedClassObj.id;
|
||||
uni.navigateTo({
|
||||
url: `/pages/view/notice/selectStudents?classId=${classId}`,
|
||||
});
|
||||
// 树形选择取消
|
||||
const onTreeCancel = () => {
|
||||
console.log("取消选择班级");
|
||||
};
|
||||
|
||||
// 显示全部学生
|
||||
const showAllStudents = () => {
|
||||
showStudentModal.value = true;
|
||||
};
|
||||
|
||||
// 关闭学生弹窗
|
||||
const closeStudentModal = () => {
|
||||
showStudentModal.value = false;
|
||||
};
|
||||
|
||||
const handleSignatureChange = (e: any) => {
|
||||
@ -464,13 +626,25 @@ const previewNotice = () => {
|
||||
|
||||
const publishNotice = () => {
|
||||
if (!validateForm()) return;
|
||||
console.log("发布通知", formData);
|
||||
uni.showLoading({ title: "发布中..." });
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({ title: "发布成功 (模拟)", icon: "success" });
|
||||
uni.navigateBack();
|
||||
}, 1000);
|
||||
|
||||
// 准备发布数据,包含年级ID和班级ID
|
||||
const publishData = {
|
||||
...formData,
|
||||
njIds: formData.targetNjIds.join(","), // 年级ID字符串
|
||||
bjIds: formData.targetBjIds.join(","), // 班级ID字符串
|
||||
};
|
||||
|
||||
console.log("发布通知数据:", publishData);
|
||||
console.log("年级ID:", publishData.njIds);
|
||||
console.log("班级ID:", publishData.bjIds);
|
||||
|
||||
// TODO: 调用发布接口
|
||||
// uni.showLoading({ title: "发布中..." });
|
||||
// setTimeout(() => {
|
||||
// uni.hideLoading();
|
||||
// uni.showToast({ title: "发布成功 (模拟)", icon: "success" });
|
||||
// uni.navigateBack();
|
||||
// }, 1000);
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -734,8 +908,7 @@ const publishNotice = () => {
|
||||
position: relative;
|
||||
min-height: 30px;
|
||||
|
||||
.name-tag,
|
||||
.modify-btn {
|
||||
.name-tag {
|
||||
font-size: 13px;
|
||||
padding: 5px 0;
|
||||
border-radius: 4px;
|
||||
@ -746,29 +919,10 @@ const publishNotice = () => {
|
||||
flex-basis: calc((100% - 50px) / 6);
|
||||
height: 28px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.name-tag {
|
||||
background-color: #f4f4f5;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.modify-btn {
|
||||
background-color: #ecf5ff;
|
||||
color: #409eff;
|
||||
border: 1px solid #d9ecff;
|
||||
padding: 0;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
@ -778,6 +932,26 @@ const publishNotice = () => {
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.more-btn-full {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
background-color: #fff2e8;
|
||||
color: #e6a23c;
|
||||
border: 1px solid #f5dab1;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
&:active {
|
||||
background-color: #ffecd1;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item-card {
|
||||
padding: 0;
|
||||
.uni-datetime-picker,
|
||||
@ -890,4 +1064,73 @@ const publishNotice = () => {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 学生名单弹窗样式 */
|
||||
.student-modal-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.student-modal {
|
||||
width: 90%;
|
||||
max-height: 80%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.student-modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.student-count {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.student-modal-content {
|
||||
max-height: 400px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.all-student-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 10px;
|
||||
}
|
||||
|
||||
.student-tag {
|
||||
font-size: 13px;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
background-color: #f4f4f5;
|
||||
color: #909399;
|
||||
min-width: 60px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user