This commit is contained in:
Net 2025-07-02 22:43:30 +08:00
parent 66bc9dc920
commit 4f220f1855
5 changed files with 514 additions and 303 deletions

View File

@ -1,82 +1,89 @@
// 参数接口 // 参数接口
// 响应接口 // 响应接口
import {get, post} from "@/utils/request"; import { get, post } from "@/utils/request";
/** /**
* *
*/ */
export const xqgwFindAllApi = async () => { export const xqgwFindAllApi = async () => {
return await get("/api/xqgw/findAll"); return await get("/api/xqgw/findAll");
}; };
export const xqxjFindAllApi = async () => { export const xqxjFindAllApi = async () => {
return await get("/api/xqxj/findAll"); return await get("/api/xqxj/findAll");
}; };
export const findAllNjBjTreeApi = async () => { export const findAllNjBjTreeApi = async () => {
return await get("/api/nj/findAllNjBjTree"); return await get("/api/nj/findAllNjBjTree");
}; };
export const kmFindAllApi = async () => { export const kmFindAllApi = async () => {
return await get("/api/km/findAll"); return await get("/api/km/findAll");
}; };
export const findAllXxXqNjTree = async () => { export const findAllXxXqNjTree = async () => {
return await get("/api/nj/findAllXxXqNjTree"); return await get("/api/nj/findAllXxXqNjTree");
}; };
export const findAllNjBjTree = async () => { export const findAllNjBjTree = async () => {
return await get("/api/nj/findAllNjBjTree"); return await get("/api/nj/findAllNjBjTree");
}; };
export const jsConfirmJsDataApi = async (params: any) => { export const jsConfirmJsDataApi = async (params: any) => {
return await post("/api/js/confirmJsData", params); return await post("/api/js/confirmJsData", params);
}; };
export const jsdFindPageTaskApi = async (params: any) => { export const jsdFindPageTaskApi = async (params: any) => {
return await get("/api/jsd/findPageTask", params); return await get("/api/jsd/findPageTask", params);
}; };
export const rwflFindRwlxsByRwId = async (params: any) => { export const rwflFindRwlxsByRwId = async (params: any) => {
return await get("/api/rwlx/findRwlxsByRwId", params); return await get("/api/rwlx/findRwlxsByRwId", params);
} };
export const rwzxSaveApi = async (params: any) => { export const rwzxSaveApi = async (params: any) => {
return await post("/api/rwzx/save", params); return await post("/api/rwzx/save", params);
}; };
export const rwzxExecutedInfoByRwIdAndJsApi = async (params: any) => { export const rwzxExecutedInfoByRwIdAndJsApi = async (params: any) => {
return await get("/api/rwzx/executedInfoByRwIdAndJs", params); return await get("/api/rwzx/executedInfoByRwIdAndJs", params);
}; };
export const rwFindInfoByRwId = async (params: any) => { export const rwFindInfoByRwId = async (params: any) => {
return await get("/api/rw/findInfoByRwId", params); return await get("/api/rw/findInfoByRwId", params);
} };
export const fractionRuleApi = async () => { export const fractionRuleApi = async () => {
return await get( return await get(
"/api/fractionRule/findAllByItemId?itemId=CDFDED2A704F46E2A4D7E8816968BD23" "/api/fractionRule/findAllByItemId?itemId=CDFDED2A704F46E2A4D7E8816968BD23"
); );
}; };
export const fractionRuleApi1 = async () => { export const fractionRuleApi1 = async () => {
return await get( return await get(
"/api/fractionRule/findAllByItemId?itemId=B96A0FA22C414F71A3E1CDCA7E206B10" "/api/fractionRule/findAllByItemId?itemId=B96A0FA22C414F71A3E1CDCA7E206B10"
); );
}; };
// 查询教师信息 // 查询教师信息
export const jsdfindJsByPhoneApi = async (params: any) => { export const jsdfindJsByPhoneApi = async (params: any) => {
return await get("/api/js/findJsByPhone", params); return await get("/api/js/findJsByPhone", params);
}; };
// 选课列表 // 选课列表
export const jsdXkListApi = async (params: any) => { export const jsdXkListApi = async (params: any) => {
return await get("/mobile/js/xk/list", params); return await get("/mobile/js/xk/list", params);
}; };
// 选课列表 // 选课列表
export const jsdXkkcSaveApi = async (params: any) => { export const jsdXkkcSaveApi = async (params: any) => {
return await post("/api/xkkc/save", params); return await post("/api/xkkc/save", params);
}; };
// 选课学生列表 // 选课学生列表
export const jsdXkXsListApi = async (params: any) => { export const jsdXkXsListApi = async (params: any) => {
return await get("/mobile/js/xkxs/list", params); 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) => { export const jsdXkdmListApi = async (params: any) => {
return await post("/mobile/js/xkdm/add", params); return await post("/mobile/js/xkdm/add", params);
}; };

View File

@ -1,4 +1,5 @@
const ip: string = "192.168.239.1:8897"; // const ip: string = "192.168.239.1:8897";
const ip: string = "yufangzc.com";
// const ip: string = "yufangzc.com"; // const ip: string = "yufangzc.com";
const fwqip: string = "yufangzc.com"; const fwqip: string = "yufangzc.com";
//打包服务器接口代理标识 //打包服务器接口代理标识

View File

@ -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() { function addEducation() {
education.xl.push({ value: {} }); education.xl.push({ value: {} });
// //

View File

@ -1,38 +1,55 @@
<!-- src/pages/view/notice/index.vue --> <!-- src/pages/view/notice/index.vue -->
<template> <template>
<view class="jl-list-page"> <view class="jl-list-page">
<!-- 新建接龙按钮 -->
<view class="fab-button" @click="goToPublish">
<uni-icons type="plusempty" size="24" color="#fff"></uni-icons>
</view>
<!-- 列表内容 --> <!-- 列表内容 -->
<view v-if="jlList.length > 0"> <BasicListLayout @register="register">
<view v-for="item in jlList" :key="item.id" class="jl-card" @click="goToDetail(item.id)"> <template v-slot="{ data }">
<view class="card-header"> <view class="jl-card" @click="goToDetail(data.id)">
<text class="jl-title">{{ item.jlmc }}</text> <view class="card-header">
<text class="jl-status" :class="getStatusClass(item.jlStatus)"> <text class="jl-title">{{ data.jlmc }}</text>
{{ getStatusText(item.jlStatus) }} <text class="jl-status" :class="getStatusClass(data.jlStatus)">
</text> {{ getStatusText(data.jlStatus) }}
</text>
</view>
<view class="card-body">
<image
v-if="data.jlfm"
:src="imagUrl(data.jlfm)"
mode="aspectFill"
class="cover-thumbnail"
></image>
<rich-text class="jl-excerpt" :nodes="data.jlms"></rich-text>
</view>
<view class="card-footer">
<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> </view>
<view class="card-body"> </template>
<image v-if="item.jlfm" :src="item.jlfm" mode="aspectFill" class="cover-thumbnail"></image> <template #bottom>
<text class="jl-excerpt" v-html="item.jlms"></text> <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> </view>
<view class="card-footer"> </template>
<text class="footer-item">发布者: {{ item.jsxm }}</text> </BasicListLayout>
<text class="footer-item">{{ formatTime(item.jlFbtime) }}</text>
<text class="footer-item" v-if="item.bjmc">范围: {{ item.njmc+item.bjmc }}</text>
</view>
</view>
</view>
<view v-else class="empty-list">暂无数据</view>
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {ref, onMounted} from "vue"; import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
import {BASE_URL} from "@/config"; import { mobilejllistApi } from "@/api/base/server";
import { imagUrl } from "@/utils";
import BasicDragButton from "@/components/BasicDragButton/DragButton.vue";
interface JlItem { interface JlItem {
id: string; id: string;
@ -49,39 +66,10 @@ interface JlItem {
jsxm?: string; jsxm?: string;
} }
const jlList = ref<JlItem[]>([]); // 使 BasicListLayout
const total = ref(0); const [register, { reload }] = useLayout({
api: mobilejllistApi, // api使使 query
const fetchJlList = async () => { componentProps: {},
try {
const response = await uni.request({
url: `${BASE_URL}/mobile/jl/list`,
method: "GET",
data: {pageNo: 1, pageSize: 10},
header: {"Content-Type": "application/json"}
});
if (response.statusCode === 200 && response.data) {
const result = response.data;
const pageData = result.data || result;
if (pageData.result && Array.isArray(pageData.result.rows)) {
jlList.value = pageData.result.rows;
total.value = pageData.result.total || 0;
} else {
jlList.value = [];
total.value = 0;
}
} else {
jlList.value = [];
total.value = 0;
}
} catch (e) {
jlList.value = [];
total.value = 0;
}
};
onMounted(() => {
fetchJlList();
}); });
// //
@ -114,9 +102,12 @@ const getStatusText = (status: string) => {
// //
const formatTime = (timeStr: string) => { const formatTime = (timeStr: string) => {
if (!timeStr) return ''; if (!timeStr) return "";
const date = new Date(timeStr); const date = new Date(timeStr);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
2,
"0"
)}-${String(date.getDate()).padStart(2, "0")}`;
}; };
</script> </script>
@ -215,11 +206,8 @@ const formatTime = (timeStr: string) => {
} }
} }
// FAB // FAB - DragButton
.fab-button { .fab-button {
position: fixed;
right: 20px;
bottom: 40px; //
width: 50px; width: 50px;
height: 50px; height: 50px;
background-color: #4477ee; background-color: #4477ee;
@ -228,12 +216,7 @@ const formatTime = (timeStr: string) => {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
z-index: 10;
} }
.empty-list { /* 空列表样式已由 BasicListLayout 组件处理,移除此样式 */
text-align: center;
color: #999;
margin-top: 40px;
}
</style> </style>

View File

@ -15,7 +15,7 @@
<view class="cover-upload-wrapper"> <view class="cover-upload-wrapper">
<CustomUpload <CustomUpload
field="coverImage" field="coverImage"
:value="formData.coverImage" :value="formData.coverImage ? imagUrl(formData.coverImage) : ''"
@select="handleCoverSelected" @select="handleCoverSelected"
@close="handleCoverClosed" @close="handleCoverClosed"
> >
@ -80,45 +80,35 @@
<view class="add-icon" <view class="add-icon"
><uni-icons type="plusempty" size="20" color="#ccc"></uni-icons ><uni-icons type="plusempty" size="20" color="#ccc"></uni-icons
></view> ></view>
<text class="placeholder-text" <text class="placeholder-text">添加图文/视频/文件</text>
>添加图文/视频/文件/公众号/小程序等</text
>
</view> </view>
</view> </view>
</view> </view>
<view class="info-card"> <view class="info-card">
<picker <view class="card-header picker-header" @click="showClassTree">
mode="selector" <text class="section-title">按名单填写</text>
:range="combinedClassRange" <view class="target-class">
:value="selectedClassIndex" <text :class="{ placeholder: !formData.targetClass }">{{
@change="onClassPickerChange" formData.targetClass || "请选择班级"
> }}</text>
<view class="card-header picker-header"> <uni-icons type="right" size="16" color="#999"></uni-icons>
<text class="section-title">按名单填写</text>
<view class="target-class">
<text :class="{ placeholder: !formData.targetClass }">{{
formData.targetClass || "请选择班级"
}}</text>
<uni-icons type="right" size="16" color="#999"></uni-icons>
</view>
</view> </view>
</picker> </view>
<view class="name-tags"> <view class="name-tags">
<text <text
v-for="name in formData.targetNames" v-for="(name, index) in displayNames"
:key="name" :key="name + index"
class="name-tag" class="name-tag"
>{{ name }}</text >{{ name }}</text
> >
<button </view>
v-if="formData.targetNames.length > 0" <view
size="mini" v-if="formData.targetNames.length > maxDisplayCount"
type="default" class="more-btn-container"
class="modify-btn" >
@click="handleModifyNames" <button size="mini" class="more-btn-full" @click="showAllStudents">
> 更多({{ formData.targetNames.length - maxDisplayCount }})
修改
</button> </button>
</view> </view>
</view> </view>
@ -165,17 +155,64 @@
<!-- Bottom slot --> <!-- Bottom slot -->
<template #bottom> <template #bottom>
<view class="bottom-actions"> <view class="bottom-actions">
<button class="action-btn draft-btn" @click="saveDraft">保存草稿</button> <button class="action-btn draft-btn" @click="saveDraft">
<button class="action-btn preview-btn" @click="previewNotice"> 保存草稿
预览 </button>
</button> <button class="action-btn preview-btn" @click="previewNotice">
<button class="action-btn publish-btn" @click="publishNotice"> 预览
立即发布 </button>
</button> <button class="action-btn publish-btn" @click="publishNotice">
</view> 立即发布
</button>
</view>
</template> </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> </BasicLayout>
</template> </template>
@ -183,6 +220,10 @@
import { ref, reactive, computed } from "vue"; import { ref, reactive, computed } from "vue";
import { onLoad } from "@dcloudio/uni-app"; import { onLoad } from "@dcloudio/uni-app";
import CustomUpload from "/src/components/BasicUpload/CustomUpload.vue"; 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 { interface Attachment {
name: string; name: string;
@ -200,6 +241,8 @@ interface FormData {
targetClass: string; targetClass: string;
targetNames: string[]; targetNames: string[];
targetStudentIds: string[]; targetStudentIds: string[];
targetNjIds: string[]; // ID
targetBjIds: string[]; // ID
signatureRequired: boolean; signatureRequired: boolean;
startTime: string; startTime: string;
endTime: string; endTime: string;
@ -215,6 +258,8 @@ const formData = reactive<FormData>({
targetClass: "", targetClass: "",
targetNames: [], targetNames: [],
targetStudentIds: [], targetStudentIds: [],
targetNjIds: [],
targetBjIds: [],
signatureRequired: false, signatureRequired: false,
startTime: "", startTime: "",
endTime: "", endTime: "",
@ -225,38 +270,40 @@ const signatureStatusText = computed(() => {
return formData.signatureRequired ? "启用" : "不启用"; return formData.signatureRequired ? "启用" : "不启用";
}); });
const classList = ref([ //
{ id: "g1c1", name: "一年级1班" }, const treeData = ref([]);
{ id: "g1c2", name: "一年级2班" }, const treeRef = ref();
{ 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 combinedClassRange = computed(() => { //
return classList.value.map((cls) => cls.name); const maxDisplayCount = 24; // 244×6
const showStudentModal = ref(false);
// 24
const displayNames = computed(() => {
return formData.targetNames.slice(0, maxDisplayCount);
}); });
const selectedClassIndex = computed(() => { //
const index = classList.value.findIndex( const loadTreeData = async () => {
(cls) => cls.name === formData.targetClass try {
); const res = await findAllNjBjTree();
return index >= 0 ? index : 0; 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[]> => { const fetchStudentsByClass = async (className: string): Promise<string[]> => {
console.log(`模拟获取班级 [${className}] 的学生列表...`); console.log(`模拟获取班级 [${className}] 的学生列表...`);
@ -281,40 +328,42 @@ const fetchStudentsByClass = async (className: string): Promise<string[]> => {
return mockStudents; return mockStudents;
}; };
onLoad((options) => { 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: "发布通知" });
}
});
const handleCoverSelected = (e: any) => { const handleCoverSelected = async (e: any) => {
console.log("选择封面 (CustomUpload):", e);
if (e.tempFilePaths && e.tempFilePaths.length > 0) { if (e.tempFilePaths && e.tempFilePaths.length > 0) {
formData.coverImage = e.tempFilePaths[0]; const tempFilePath = e.tempFilePaths[0];
console.log("封面临时路径:", formData.coverImage);
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 { } else {
console.error("无法从选择事件中获取封面路径:", e); console.error("无法从选择事件中获取封面路径:", e);
} }
}; };
const handleCoverClosed = (field: string) => { const handleCoverClosed = (field: string) => {
console.log(`删除封面 (CustomUpload): field=${field}`);
if (field === "coverImage") { if (field === "coverImage") {
formData.coverImage = null; formData.coverImage = null;
} }
@ -324,47 +373,74 @@ const addAttachment = () => {
uni.chooseFile({ uni.chooseFile({
count: 5, count: 5,
type: "all", type: "all",
success: (res) => { success: async (res) => {
const tempFiles = res.tempFiles; const tempFiles = res.tempFiles;
if (Array.isArray(tempFiles) && tempFiles.length > 0) { if (Array.isArray(tempFiles) && tempFiles.length > 0) {
tempFiles.forEach((file: any) => { uni.showLoading({ title: "上传中..." });
let fileType = "file";
const fileName = file.name || "";
const fileExtension = fileName.split(".").pop()?.toLowerCase();
if ( try {
["png", "jpg", "jpeg", "gif", "bmp", "webp"].includes( for (const file of tempFiles) {
fileExtension || "" const fileInfo = file as any; //
) let fileType = "file";
) { const fileName = fileInfo.name || "";
fileType = "image"; const fileExtension = fileName.split(".").pop()?.toLowerCase();
} else if (
["mp4", "mov", "avi", "wmv", "flv"].includes(fileExtension || "") if (
) { ["png", "jpg", "jpeg", "gif", "bmp", "webp"].includes(
fileType = "video"; fileExtension || ""
} else if ( )
["mp3", "wav", "aac", "ogg"].includes(fileExtension || "") ) {
) { fileType = "image";
fileType = "audio"; } else if (
["mp4", "mov", "avi", "wmv", "flv"].includes(fileExtension || "")
) {
fileType = "video";
} else if (
["mp3", "wav", "aac", "ogg"].includes(fileExtension || "")
) {
fileType = "audio";
}
if (
fileInfo.type &&
typeof fileInfo.type === "string" &&
(fileInfo.type.startsWith("image/") ||
fileInfo.type.startsWith("video/") ||
fileInfo.type.startsWith("audio/"))
) {
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: originalPath, //
size: fileInfo.size,
});
} else {
uni.showToast({ title: `${fileName} 上传失败`, icon: "error" });
}
} }
if ( uni.showToast({ title: "附件上传完成", icon: "success" });
file.type && } catch (error) {
typeof file.type === "string" && console.error("附件上传失败:", error);
(file.type.startsWith("image/") || uni.showToast({ title: "附件上传失败", icon: "error" });
file.type.startsWith("video/") || } finally {
file.type.startsWith("audio/")) uni.hideLoading();
) { }
fileType = file.type.split("/")[0];
}
formData.attachments.push({
name: fileName,
type: fileType,
url: file.path,
size: file.size,
});
});
} else { } else {
console.log("未选择任何文件或返回结果异常,或 tempFiles 不是数组"); console.log("未选择任何文件或返回结果异常,或 tempFiles 不是数组");
} }
@ -391,38 +467,124 @@ const getAttachmentIcon = (type: string): string => {
const previewAttachment = (attachment: Attachment) => { const previewAttachment = (attachment: Attachment) => {
console.log("预览附件:", 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 showClassTree = () => {
const selectedClass = classList.value[index]; if (treeRef.value) {
if (selectedClass && selectedClass.name !== formData.targetClass) { treeRef.value._show();
formData.targetClass = selectedClass.name; }
};
//
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.targetNames = [];
formData.targetStudentIds = []; formData.targetStudentIds = [];
formData.targetNjIds = [];
formData.targetBjIds = [];
try { try {
const students = await fetchStudentsByClass(formData.targetClass); uni.showLoading({ title: "获取学生列表中..." });
formData.targetNames = students;
// IDID
const njIds: string[] = [];
const bjIds: string[] = [];
selectedItems.forEach((item) => {
// parents
if (item.parents && item.parents.length > 0) {
const njId = item.parents[0].key; // IDparents[0].key
const bjId = item.key; // IDitem.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)];
// IDIDformData
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) { } catch (error) {
console.error("获取学生列表失败:", 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( const onTreeCancel = () => {
(cls) => cls.name === formData.targetClass console.log("取消选择班级");
); };
if (!selectedClassObj) {
uni.showToast({ title: "请先选择班级", icon: "none" }); //
return; const showAllStudents = () => {
} showStudentModal.value = true;
const classId = selectedClassObj.id; };
uni.navigateTo({
url: `/pages/view/notice/selectStudents?classId=${classId}`, //
}); const closeStudentModal = () => {
showStudentModal.value = false;
}; };
const handleSignatureChange = (e: any) => { const handleSignatureChange = (e: any) => {
@ -464,13 +626,25 @@ const previewNotice = () => {
const publishNotice = () => { const publishNotice = () => {
if (!validateForm()) return; if (!validateForm()) return;
console.log("发布通知", formData);
uni.showLoading({ title: "发布中..." }); // IDID
setTimeout(() => { const publishData = {
uni.hideLoading(); ...formData,
uni.showToast({ title: "发布成功 (模拟)", icon: "success" }); njIds: formData.targetNjIds.join(","), // ID
uni.navigateBack(); bjIds: formData.targetBjIds.join(","), // ID
}, 1000); };
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> </script>
@ -496,10 +670,10 @@ const publishNotice = () => {
} }
.form-container { .form-container {
padding: 12px; padding: 12px;
box-sizing: border-box; box-sizing: border-box;
/* Add padding-bottom if content gets hidden by bottom bar */ /* Add padding-bottom if content gets hidden by bottom bar */
/* padding-bottom: 70px; */ /* padding-bottom: 70px; */
} }
.info-card { .info-card {
@ -734,8 +908,7 @@ const publishNotice = () => {
position: relative; position: relative;
min-height: 30px; min-height: 30px;
.name-tag, .name-tag {
.modify-btn {
font-size: 13px; font-size: 13px;
padding: 5px 0; padding: 5px 0;
border-radius: 4px; border-radius: 4px;
@ -746,29 +919,10 @@ const publishNotice = () => {
flex-basis: calc((100% - 50px) / 6); flex-basis: calc((100% - 50px) / 6);
height: 28px; height: 28px;
line-height: 18px; line-height: 18px;
}
.name-tag {
background-color: #f4f4f5; background-color: #f4f4f5;
color: #909399; 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 { .loading-spinner {
position: absolute; position: absolute;
top: 5px; 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 { .list-item-card {
padding: 0; padding: 0;
.uni-datetime-picker, .uni-datetime-picker,
@ -841,7 +1015,7 @@ const publishNotice = () => {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
padding: 12px 15px; padding: 12px 15px;
background-color: #ffffff; background-color: #ffffff;
border-top: 1px solid #e5e5e5; border-top: 1px solid #e5e5e5;
@ -887,7 +1061,76 @@ const publishNotice = () => {
} }
.target-class text.placeholder { .target-class text.placeholder {
color: #909399; 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> </style>