增加二次关联学生界面

This commit is contained in:
ywyonui 2025-06-24 20:33:42 +08:00
parent e85d41d714
commit 9e68d93eaa
4 changed files with 465 additions and 4 deletions

View File

@ -6,6 +6,11 @@ import { get, post } from "@/utils/request";
export const loginRegisterJzApi = async (params: any) => {
return await post("/open/login/registerJz", params);
};
export const glxsApi = async (params: any) => {
return await post("/open/login/glxs", params);
};
export const xkAddXkqdApi = async (params: any) => {
return await post("/mobile/xk/addXkqd", params);
};

View File

@ -33,6 +33,14 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/base/home/glxs",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path": "pages/system/login/login",
"style": {

View File

@ -0,0 +1,436 @@
<template>
<BasicLayout>
<view class="page-container">
<view class="notice-box">
<text class="notice-text"
>特别提示家中家庭成员可多人关联可接收孩子在校情况学业情况等</text
>
</view>
<view
v-for="(student, index) in students"
:key="index"
class="form-section mb-15"
>
<view v-if="index > 0" class="remove-btn" @click="removeStudent(index)">
<u-icon name="minus-circle" color="#ff4d4f" size="18"></u-icon>
</view>
<view class="avatar-section">
<view class="avatar-uploader-container-rect">
<CustomUpload
@select="(event:any) => afterRead(event, index)"
@close="handleAvatarClose(index)"
:sourceType="['camera', 'album']"
:value="imagUrl(student.xstx)"
>
<view class="avatar-placeholder">
<view class="wh-full flex-col-center">
<svg
t="1729656215869"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="5302"
width="32"
height="32"
>
<path
d="M851.552 890.88 172.448 890.88c-74.592 0-135.296-60.672-135.296-135.296L37.152 370.752c0-74.624 60.672-135.328 135.296-135.328l132.16 0L302.912 195.904c0-34.624 28.192-62.816 62.816-62.816l302.016 0c29.408 0 53.312 23.904 53.312 53.312l0 49.024 130.464 0c74.592 0 135.296 60.672 135.296 135.328l0 384.832C986.816 830.208 926.144 890.88 851.552 890.88zM172.448 283.456c-48.128 0-87.296 39.168-87.296 87.328l0 384.832c0 48.128 39.168 87.296 87.296 87.296l679.104 0c48.128 0 87.296-39.168 87.296-87.296L938.848 370.752c0-48.16-39.168-87.328-87.296-87.328L716.8 283.424c-24.096 0-43.712-19.616-43.712-43.712L673.088 186.4c0-2.944-2.368-5.312-5.312-5.312l-302.016 0c-8.16 0-14.816 6.656-14.816 14.816L350.944 237.12c0 25.536-20.768 46.304-46.304 46.304L172.448 283.424zM512 755.84c-107.04 0-194.08-87.072-194.08-194.08S404.992 367.68 512 367.68s194.08 87.072 194.08 194.08S619.04 755.84 512 755.84zM512 415.68c-80.576 0-146.08 65.536-146.08 146.08S431.456 707.84 512 707.84s146.08-65.536 146.08-146.08S592.576 415.68 512 415.68zM816.8 438.016c-25.568 0-46.336-20.768-46.336-46.336s20.768-46.336 46.336-46.336 46.336 20.768 46.336 46.336S842.368 438.016 816.8 438.016zM816.8 390.016l-1.664 1.664c0 0.896 0.736 1.664 1.664 1.664L816.8 390.016z"
fill="#cdcdcd"
p-id="5303"
></path>
</svg>
</view>
</view>
</CustomUpload>
</view>
<text class="avatar-upload-note">上传学生人像用于校园进出</text>
</view>
<view class="student-info-form">
<u--form label-width="auto">
<u-form-item
label="姓名"
:prop="`students[${index}].xsxm`"
required
borderBottom
>
<u--input
v-model="student.xsxm"
placeholder="请输入学生姓名"
border="none"
inputAlign="right"
></u--input>
</u-form-item>
<!-- <u-form-item
label="与学生关系"
:prop="`students[${index}].jzxsgxId`"
required
borderBottom
>
<view @click="openDicPicker(student)" class="flex-row flex-1 justify-end">
<view v-if="!student.jzxsgxId" style="color: rgb(192, 196, 204);">请选择与学生关系</view>
<view v-else>{{ student.jzxsgxmc }}</view>
</view>
</u-form-item> -->
<u-form-item
label="身份证号"
:prop="`students[${index}].xssfzh`"
required
borderBottom
>
<u--input
v-model="student.xssfzh"
placeholder="请输入学生身份证号"
border="none"
inputAlign="right"
></u--input>
</u-form-item>
</u--form>
</view>
</view>
<view class="add-child-btn mb-15" @click="addMoreChildren">
<u-icon name="plus" color="#416AF2" size="20"></u-icon>
<text class="add-child-btn-text">新增多孩</text>
</view>
</view>
<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="submit" />
</view>
</view>
</template>
</BasicLayout>
</template>
<script lang="ts" setup>
import { hideLoading, showLoading, showToast } from "@/utils/uniapp";
import { ref } from "vue";
import { attachmentUpload } from "@/api/system/upload";
import CustomUpload from "/src/components/BasicUpload/CustomUpload.vue";
import { useForm } from "@/components/BasicForm/hooks/useForm";
import { dicApi } from "@/api/system/dic";
import { glxsApi } from "@/api/base/server";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import {imagUrl} from "@/utils";
const { getGlobal, getAppCode } = useDataStore();
const { getUser, setUser, setCurXs } = useUserStore();
const dicOptions = ref<any>([[[]]]);
const dicPickerRef = ref();
const dicVal = ref<number[]>([]);
const students = ref([
{
xsxm: "",
xssfzh: "",
xstx: "",
jzxsgxId: "",
jzxsgxmc: ""
},
]);
const curXs = ref(students.value[0]);
const openDicPicker = (xs: any) => {
curXs.value = xs;
dicVal.value = [0];
for (let i = 0; i < dicOptions.value[0].length; i++) {
if (xs.jzxsgxId == dicOptions.value[0][i].dictionaryValue) {
dicVal.value = [i];
break;
}
}
dicPickerRef.value.open();
};
const dicChanged = (dicArr: any) => {
console.log(dicArr);
const dic = dicOptions.value[0][dicArr[0]];
curXs.value.jzxsgxId = dic.dictionaryValue;
curXs.value.jzxsgxmc = dic.dictionaryCode;
}
async function afterRead(event: any, index: number) {
if (!event.tempFilePaths || event.tempFilePaths.length === 0) {
showToast({ title: "图片选择失败", icon: "none" });
return;
}
const tempFilePath = event.tempFilePaths[0];
showLoading({ title: "上传中" });
try {
const res = await attachmentUpload(tempFilePath);
const result = res.result;
if (result && result.length > 0 && result[0].filePath) {
students.value[index].xstx = result[0].filePath;
console.log(`Student ${index} avatar uploaded:`, result[0].filePath);
showToast({ title: "上传成功" });
} else {
showToast({ title: "上传失败,请重试", icon: "none" });
console.error("Upload result format error:", result);
}
} catch (error) {
showToast({ title: "上传出错", icon: "none" });
console.error("Upload error:", error);
} finally {
hideLoading();
}
}
function handleAvatarClose(index: number) {
students.value[index].xstx = "";
}
function addMoreChildren() {
students.value.push({
xsxm: "",
xssfzh: "",
xstx: "",
jzxsgxId: "",
jzxsgxmc: ""
});
}
function removeStudent(index: number) {
if (students.value.length > 1) {
students.value.splice(index, 1);
} else {
showToast({ title: "至少需要一个子女信息", icon: "none" });
}
}
async function submit() {
for (const student of students.value) {
if (!student.xstx) {
showToast({ title: "请上传子女照片", icon: "none" });
return;
}
if (!student.xsxm) {
showToast({ title: "请输入子女姓名", icon: "none" });
return;
}
if (!student.xssfzh) {
showToast({ title: "请输入子女身份证号", icon: "none" });
return;
}
}
showLoading({ title: "提交中" });
try {
for (let i = 0; i < students.value.length; i++) {
students.value[i].jzxsgxId = getUser.jzxsgxId;
}
const res = await glxsApi({
xsList: students.value,
jzId: getUser.jzId,
openId: getGlobal.openId,
appCode: getAppCode,
});
hideLoading();
setUser(res.result);
for (let i = 0; i < res.result.xsList.length; i++) {
if (res.result.xsList[i].sfzh == students.value[0].xssfzh) {
setCurXs(res.result.xsList[i]);
break;
}
}
uni.reLaunch({
url: "/pages/base/home/index",
});
} catch (error) {
console.log(error);
}
}
onMounted(async () => {
console.log("glxs");
// const resDic = await dicApi({ pid: 1622287061 });
// dicOptions.value = [resDic.result];
// formSchema[1].componentProps.options = resDic.result;
// setSchema(formSchema);
});
</script>
<style lang="scss" scoped>
.page-container {
padding: 15px; /* Consistent padding */
}
.notice-box {
background-color: #fff1f0; /* Slightly lighter red */
padding: 12px 18px;
border-radius: 8px;
margin-bottom: 15px;
}
.notice-text {
color: #fa541c; /* Adjusted red color */
font-size: 13px;
}
.form-section {
background-color: #ffffff;
border-radius: 10px;
padding: 20px 20px 0 20px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.06);
/* Added margin-bottom directly here for spacing between sections */
margin-bottom: 5px;
position: relative;
}
.avatar-section {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 25px; /* Increased margin */
}
/* Keep avatar uploader styles relevant to CustomUpload */
/* Replace with rectangular styles */
.avatar-uploader-container-rect {
/* Assuming uni.rpx units based on class names like wi-180, he-240 */
width: 180rpx;
height: 240rpx;
margin: 0 auto 10px auto; /* mx-auto mb-10 */
border-radius: 6px; /* r-md approximation */
border: 1px solid #cccccc;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
background-color: #fafafa;
}
/* Remove old circular styles */
/* .avatar-uploader-container { ... } */
.avatar-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
cursor: pointer;
}
/* Keep inner placeholder for centering SVG */
.avatar-placeholder-inner {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.avatar-image {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Remove old hint style */
/* .avatar-upload-hint { ... } */
.avatar-upload-note {
color: #999;
font-size: 13px;
}
.student-info-form {
margin-bottom: 20px; /* Restore original margin */
}
.form-title {
display: block;
font-size: 16px; /* Slightly larger title */
font-weight: 600; /* Bolder */
margin-bottom: 15px; /* Space below title */
}
/* Restore remove button style if needed, or adapt */
/* Updated remove button style */
.remove-btn {
position: absolute;
top: 10px; /* Closer to top edge */
right: 10px; /* Closer to right edge */
cursor: pointer;
z-index: 10;
/* Optional: add padding for easier clicking */
// padding: 5px;
}
.add-child-btn {
background-color: #ffffff;
border-radius: 10px;
padding: 15px; /* Increased padding */
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px; /* Increased margin */
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.06);
cursor: pointer;
}
.add-child-btn-text {
color: #416af2;
margin-left: 8px;
font-size: 15px;
font-weight: 500;
}
/* Adjust uview form item styles */
::v-deep .u-form-item {
margin-bottom: 0; /* Remove default margin if any */
}
::v-deep .u-form-item__body {
padding: 15px 0 !important; /* Adjusted padding */
/* Align items vertically if label wraps */
// align-items: flex-start;
}
::v-deep .u-form-item__body__left {
/* Allow label to take necessary width, adjust as needed */
// flex: 0 0 80px;
}
::v-deep .u-form-item__body__left__text {
font-size: 15px;
color: #333;
line-height: 1.5; /* Improve line spacing if label wraps */
/* Ensure required asterisk is red and BEFORE the text */
display: flex; /* Use flex to control order */
align-items: center; /* Vertically center asterisk and text */
span {
color: #f56c6c;
/* Order asterisk first */
order: -1;
margin-right: 4px;
/* Adjust vertical alignment if needed */
// line-height: 1;
// display: inline-block;
// vertical-align: middle;
}
}
::v-deep .u-input {
text-align: right; /* Align input text to the right */
}
::v-deep .u-border-bottom {
/* Ensure border spans full width if needed, or adjust */
// left: 0 !important;
// right: 0 !important;
}
</style>

View File

@ -21,10 +21,16 @@
</view>
</view>
</view>
<view class="switch-btn" @click="showXsSelector" v-if="xsList && xsList.length > 1">
<u-icon name="arrow-down" size="12" color="#fff"></u-icon>
<text>切换</text>
</view>
<view class="btn-group">
<view class="switch-btn" @click="goToGlxs">
<u-icon name="arrow-down" size="12" color="#fff"></u-icon>
<text>新增学生</text>
</view>
<view class="switch-btn" @click="showXsSelector" v-if="xsList && xsList.length > 1">
<u-icon name="arrow-down" size="12" color="#fff"></u-icon>
<text>切换</text>
</view>
</view>
</view>
</view>
@ -220,6 +226,12 @@ let pageParams = ref({
appCode: getAppCode
})
const goToGlxs = () => {
uni.navigateTo({
url: "/pages/base/home/glxs",
});
}
//
function handleMenuClick(item: any) {
console.log("点击菜单:", item.title);