form表单提交数据后去掉遮罩问题

前情提要

有一个文件下载功能,实现是用form表单的submit方法提交数据到后台,后台返回文件流。但是在数据比较多的时候查询和生成文件都比较耗时,所以想加一个遮罩,等文件下载完后再去掉遮罩,以避免在此期间操作页面。

思路
  • 提交数据前添加遮罩
  • 后台在返回文件之后添加一个cookie值
  • 前台在发出请求之后用一个定时器取读取cookie中的值
  • 取到后台放入cookie中的值则清除遮罩和定时任务
代码如下:
  1. response中添加cookie
    		Cookie cookie = new Cookie("FLAG", "true");
            cookie.setPath("/");
            cookie.setMaxAge(60 * 10);
            response.addCookie(cookie);
    
  2. js定时任务获取cookie值并清除遮罩和定时任务
    var removeing = '';//声明全局定时器变量,方便后续清除定时器用
    function excel(){
        //添加遮罩……
        frm.action = "XX/XX/XX.do" ;
        frm.submit();//提交form表单数据。调用后台接口
        removeing = setInterval('remove()', 1000);//调用定时器方法
    }
    //清除遮罩方法
    function remove() {
    	//获取cookie中的值
        var flag = document.cookie.split('FLAG=')[1];
        console.log(flag)
        if (flag==='true') {
            //清除遮罩方法……
            clearInterval(removeing);//清除定时器方法
        }
    }
    
<template> <div class="app-container"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form-item label="姓名" prop="name"> <el-input v-model="queryParams.name" placeholder="请输入姓名" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model="queryParams.age" placeholder="请输入年龄" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="用车开始时间" prop="carUseStartTime"> <el-date-picker clearable v-model="queryParams.carUseStartTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车开始时间"> </el-date-picker> </el-form-item> <el-form-item label="用车结束时间" prop="carUseEndTime"> <el-date-picker clearable v-model="queryParams.carUseEndTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车结束时间"> </el-date-picker> </el-form-item> <el-form-item label="创建时间" prop="createdAt"> <el-date-picker clearable v-model="queryParams.createdAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择创建时间"> </el-date-picker> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> </el-form-item> </el-form> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:car:add']" >新增</el-button> </el-col> <el-col :span="1.5"> <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['system:car:edit']" >修改</el-button> </el-col> <el-col :span="1.5"> <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:car:remove']" >删除</el-button> </el-col> <el-col :span="1.5"> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:car:export']" >导出</el-button> </el-col> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> </el-row> <el-table v-loading="loading" :data="carList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column label="${comment}" align="center" prop="id" /> <el-table-column label="姓名" align="center" prop="name" /> <el-table-column label="年龄" align="center" prop="age" /> <el-table-column label="用车开始时间" align="center" prop="carUseStartTime" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.carUseStartTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="用车结束时间" align="center" prop="carUseEndTime" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.carUseEndTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="创建时间" align="center" prop="createdAt" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:car:edit']" >修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:car:remove']" >删除</el-button> </template> </el-table-column> </el-table> <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 添加或修改用户用车信息对话框 --> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form-item label="姓名" prop="name"> <el-input v-model="form.name" placeholder="请输入姓名" /> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model="form.age" placeholder="请输入年龄" /> </el-form-item> <el-form-item label="用车开始时间" prop="carUseStartTime"> <el-date-picker clearable v-model="form.carUseStartTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车开始时间"> </el-date-picker> </el-form-item> <el-form-item label="用车结束时间" prop="carUseEndTime"> <el-date-picker clearable v-model="form.carUseEndTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择用车结束时间"> </el-date-picker> </el-form-item> <el-form-item label="创建时间" prop="createdAt"> <el-date-picker clearable v-model="form.createdAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择创建时间"> </el-date-picker> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> </div> </template> <script> import { listCar, getCar, delCar, addCar, updateCar } from "@/api/system/car" export default { name: "Car", data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 用户用车信息表格数据 carList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, name: null, age: null, carUseStartTime: null, carUseEndTime: null, createdAt: null }, // 表单参数 form: {}, // 表单校验 rules: { name: [ { required: true, message: "姓名不能为空", trigger: "blur" } ], age: [ { required: true, message: "年龄不能为空", trigger: "blur" } ], carUseStartTime: [ { required: true, message: "用车开始时间不能为空", trigger: "blur" } ], carUseEndTime: [ { required: true, message: "用车结束时间不能为空", trigger: "blur" } ], } } }, created() { this.getList() }, methods: { /** 查询用户用车信息列表 */ getList() { this.loading = true listCar(this.queryParams).then(response => { this.carList = response.rows this.total = response.total this.loading = false }) }, // 取消按钮 cancel() { this.open = false this.reset() }, // 表单重置 reset() { this.form = { id: null, name: null, age: null, carUseStartTime: null, carUseEndTime: null, createdAt: null } this.resetForm("form") }, /** 搜索按钮操作 */ handleQuery() { this.queryParams.pageNum = 1 this.getList() }, /** 重置按钮操作 */ resetQuery() { this.resetForm("queryForm") this.handleQuery() }, // 多选框选中数据 handleSelectionChange(selection) { this.ids = selection.map(item => item.id) this.single = selection.length!==1 this.multiple = !selection.length }, /** 新增按钮操作 */ handleAdd() { this.reset() this.open = true this.title = "添加用户用车信息" }, /** 修改按钮操作 */ handleUpdate(row) { this.reset() const id = row.id || this.ids getCar(id).then(response => { this.form = response.data this.open = true this.title = "修改用户用车信息" }) }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { if (this.form.id != null) { updateCar(this.form).then(response => { this.$modal.msgSuccess("修改成功") this.open = false this.getList() }) } else { addCar(this.form).then(response => { this.$modal.msgSuccess("新增成功") this.open = false this.getList() }) } } }) }, /** 删除按钮操作 */ handleDelete(row) { const ids = row.id || this.ids this.$modal.confirm('是否确认删除用户用车信息编号为"' + ids + '"的数据项?').then(function() { return delCar(ids) }).then(() => { this.getList() this.$modal.msgSuccess("删除成功") }).catch(() => {}) }, /** 导出按钮操作 */ handleExport() { this.download('system/car/export', { ...this.queryParams }, `car_${new Date().getTime()}.xlsx`) } } } </script> 生成增删改查的文件
07-11
<template> <div class="app-container"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form-item label="状态" prop="status"> <el-select v-model="queryParams.status"> <el-option v-for="dict in dict.type.status" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> <el-form-item label="排查时间" prop="regDate"> <el-date-picker v-model="regDate" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" /> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> </el-form-item> </el-form> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['safety:pitfall:record:add']">新增</el-button> </el-col> <el-col :span="1.5"> <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['safety:pitfall:record:edit']">修改</el-button> </el-col> <el-col :span="1.5"> <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['safety:pitfall:record:remove']">删除</el-button> </el-col> <el-col :span="1.5"> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['safety:pitfall:record:export']">导出</el-button> </el-col> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> </el-row> <el-table v-loading="loading" :data="RECORDList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <!-- <el-table-column label="记录ID" align="center" prop="recordId" /> --> <!-- <el-table-column label="任务ID" align="center" prop="taskId" /> --> <!-- <el-table-column label="企业ID" align="center" prop="enterpriseId" /> --> <!-- <el-table-column label="企业名称" align="center" prop="companyName"> <template slot-scope="scope"> <el-button type="text" @click="$ emit('tap', scope.row)">{{ scope.row.companyName }}</el-button> </template> --> <el-button type=“text” @click=“handleMore(scope.row)”> {{ scope.row.riskEventName }} <el-button size=“mini” type=“text” icon=“el-icon-s-promotion” @click=" ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …: { companyId: store.getters.companyId }, }) " v-hasPermi=“[‘safety:pitfall:record:edit’]”>整改 <el-button size=“mini” type=“text” icon=“el-icon-edit” @click=“handleUpdate(scope.row)” v-hasPermi=“[‘safety:pitfall:record:edit’]”>修改 <el-button size=“mini” type=“text” icon=“el-icon-delete” @click=“handleDelete(scope.row)” v-hasPermi=“[‘safety:pitfall:record:remove’]”>删除 <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 添加或修改隐患排查任务记录对话框 --> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" size="small" label-width="150px"> <el-form-item label="任务名称" prop="taskId"> <el-select v-model="form.taskId" clearable filterable> <el-option v-for="dict in taskList" :key="dict.taskId" :label="dict.riskEventName" :value="dict.taskId" /> </el-select> </el-form-item> <el-form-item label="状态" prop="status"> <el-select v-model="form.status"> <el-option v-for="dict in dict.type.status" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> <el-form-item label="负责人名称" prop="userName"> <el-input v-model="form.userName" /> </el-form-item> <el-form-item label="排查时间" prop="createTime"> <el-date-picker v-model="form.createTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> <!-- 关联行业详情 --> <el-drawer :title="detail.title" :visible.sync="detail.show" direction="rtl"> <div style="margin: 0 20px"> <el-descriptions :column="1" size='small' border> <el-descriptions-item label="任务名称"> {{ detail.record.riskEventName }} </el-descriptions-item> <el-descriptions-item label="企业名称"> <el-button type="text" size="small" @click=" $ router.push('/safety/enterprise/' + detail.record.companyId) "> {{ detail.record.companyName }} </el-button> </el-descriptions-item> <el-descriptions-item label="风险分析单元"> {{ detail.record.riskUnit }} </el-descriptions-item> <el-descriptions-item label="管控措施分类"> {{ detail.record.controlCategory }} </el-descriptions-item> <el-descriptions-item label="管控措施描述"> {{ detail.record.controlDesc }} </el-descriptions-item> <el-descriptions-item label="排查内容"> {{ detail.record.inspectionContent }} </el-descriptions-item> <el-descriptions-item label="巡检周期"> {{ detail.record.inspectionCycle }} </el-descriptions-item> <el-descriptions-item label="工作日类型"> <dict-tag :options="dict.type.workday_type" :value="detail.record.workdayType" /> </el-descriptions-item> <el-descriptions-item label="工作开始时间"> {{ detail.record.workEndTime }} </el-descriptions-item> <el-descriptions-item label="工作结束时间"> {{ detail.record.workEndTime }} </el-descriptions-item> <el-descriptions-item label="任务类型"> <dict-tag :options="dict.type.task_type" :value="detail.record.taskType" /> </el-descriptions-item> <el-descriptions-item label="包保任务对应项"> {{ detail.record.relatedItem }} </el-descriptions-item> <el-descriptions-item label="状态"> <dict-tag :options="dict.type.status" :value="detail.record.status" /> </el-descriptions-item> <el-descriptions-item label="创建时间"> {{ detail.record.createTime }} </el-descriptions-item> <el-descriptions-item label="更新时间"> {{ detail.record.updateTime }} </el-descriptions-item> </el-descriptions> </div> </el-drawer> </div> </template> <script> import dayjs from "dayjs"; import { listRECORD, getRECORD, delRECORD, addRECORD, updateRECORD, } from "@/api/system/riskInspectionTaskRecord"; import { taskList } from "@/api/system/TASK"; export default { name: "record", dicts: ["status"], data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 隐患排查任务记录表格数据 RECORDList: [], // 关联任务列表 taskList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, regDate: [], // 查询参数 queryParams: { pageNum: 1, pageSize: 10, taskId: null, enterpriseId: null, enterpriseName: null, riskEventName: null, userId: null, userName: null, status: null, createTime: null, }, // 表单参数 form: {}, // 表单校验 rules: { taskId: [ { required: true, message: "任务ID不能为空", trigger: "blur" }, ], enterpriseId: [ { required: true, message: "企业ID不能为空", trigger: "blur" }, ], enterpriseName: [ { required: true, message: "企业名称不能为空", trigger: "blur" }, ], riskEventName: [ { required: true, message: "风险事件名称不能为空", trigger: "blur" }, ], // userId: [ // { required: true, message: "负责人id不能为空", trigger: "blur" } // ], // userName: [ // { required: true, message: "负责人名称不能为空", trigger: "blur" } // ], }, detail: { show: false, title: "详情", record: {}, }, }; }, async created() { await this.getTaskList(); this.getList(); }, methods: { handleMore({ riskEventName, taskId }) { const record = this.taskList.find((item) => item.taskId === taskId); this.detail = { show: true, title: riskEventName + "详情", record, }; }, getTaskList() { return new Promise((resolve, reject) => { taskList().then((response) => { this.taskList = response.data; resolve(); }); }); }, /** 查询隐患排查任务记录列表 */ getList() { this.loading = true; listRECORD(this.queryParams).then((response) => { this.RECORDList = response.rows; console.log(this.RECORDList) this.total = response.total; this.loading = false; }); }, // 取消按钮 cancel() { this.open = false; this.reset(); }, // 表单重置 reset() { this.form = { recordId: null, taskId: null, enterpriseId: null, enterpriseName: null, riskEventName: null, userId: null, userName: null, status: null, createTime: null, }; this.resetForm("form"); }, /** 搜索按钮操作 */ handleQuery() { this.queryParams.pageNum = 1; const [startTime, endTime] = this.regDate; this.queryParams.createStartTime = startTime ? dayjs(startTime).startOf("day").format("YYYY-MM-DD HH:mm:ss") : null; this.queryParams.createEndTime = endTime ? dayjs(endTime).endOf("day").format("YYYY-MM-DD HH:mm:ss") : null; this.getList(); }, /** 重置按钮操作 */ resetQuery() { this.regDate = [] this.resetForm("queryForm"); this.handleQuery(); }, // 多选框选中数据 handleSelectionChange(selection) { this.ids = selection.map((item) => item.recordId); this.single = selection.length !== 1; this.multiple = !selection.length; }, /** 新增按钮操作 */ handleAdd() { this.reset(); this.open = true; this.title = "添加隐患排查任务记录"; }, /** 修改按钮操作 */ handleUpdate(row) { this.reset(); const recordId = row.recordId || this.ids; getRECORD(recordId).then((response) => { this.form = response.data; this.open = true; this.title = "修改隐患排查任务记录"; }); }, /** 提交按钮 */ submitForm() { this.$ refs["form"].validate((valid) => { if (valid) { if (this.form.recordId != null) { updateRECORD(this.form).then((response) => { this.$ modal.msgSuccess("修改成功"); this.open = false; this.getList(); }); } else { addRECORD(this.form).then((response) => { this.$ modal.msgSuccess("新增成功"); this.open = false; this.getList(); }); } } }); }, /** 删除按钮操作 */ handleDelete(row) { const recordIds = row.recordId || this.ids; this.$ modal .confirm( '是否确认删除隐患排查任务记录编号为"' + recordIds + '"的数据项?' ) .then(function () { return delRECORD(recordIds); }) .then(() => { this.getList(); this.$ modal.msgSuccess("删除成功"); }) .catch(() => { }); }, /** 导出按钮操作 */ handleExport() { if (this.RECORDList.length === 0) { this.$ modal.msgWarning("没有数据可导出"); return; } try { const XLSX = require("xlsx"); // 明确指定需要导出的字段及对应的中文表头 const exportFields = [ { key: 'riskEventName', label: '任务名称' }, { key: 'userName', label: '负责人名称' }, { key: 'status', label: '状态' }, { key: 'createTime', label: '排查时间' }, ]; // 生成表头 const headers = exportFields.map(field => field.label); // 生成数据行 const rows = this.RECORDList.map(item => { return exportFields.map(field => { // 处理可能不存在的字段或null值 const value = item[field.key] || ''; // 特殊处理日期格式(根据实际需要调整) if (field.key === 'regDate' && value) { return dayjs(value).format('YYYY-MM-DD'); } return value; }); }); // 合并表头和数据 const exportData = [headers, ...rows]; // 创建 workbook 和 worksheet const wb = XLSX.utils.book_new(); const ws = XLSX.utils.aoa_to_sheet(exportData); // 设置列宽(可选) const colWidths = [ { wch: 40 }, { wch: 25 }, { wch: 15 }, { wch: 30 }, ]; ws['!cols'] = colWidths; XLSX.utils.book_append_sheet(wb, ws, "排查任务记录"); XLSX.writeFile(wb, `排查任务记录_${new Date().getTime()}.xlsx`); } catch (error) { console.error("导出失败:", error); this.$ modal.msgError("导出失败,请稍后重试"); } } }, }; </script>前端哪里需要改能解决上面那个报错
07-18
<script setup> import { ref, reactive, onMounted, computed } from 'vue'; import { onShow } from '@dcloudio/uni-app'; // 响应式数据 const surveyList = ref([]); const total = ref(0); const loading = ref(false); const formData = reactive({ dcWjTitle: '', dcId: [], dcDept: '', state: null }); const bdrOptions = ref([]); const bdrLoading = ref(false); const pagination = reactive({ current: 1, size: 10, total: 0 }); const showBdrPlaceholder = ref(true); const handleBdrFocus = () => { showBdrList.value = true; showBdrPlaceholder.value = false; // 输入框获得焦点时隐藏占位文字 filterBdrOptions(); }; // 选择被测评人 const handleBdrSelect = (item) => { formData.dcId = [item.value]; showBdrList.value = false; bdrSearchKeyword.value = ''; showBdrPlaceholder.value = false; // 选择后不显示占位文字 }; // 新增的搜索选择器相关变量 const bdrSearchKeyword = ref(''); const showBdrList = ref(false); const filteredBdrOptions = ref([]); // 状态选择器相关变量 const stateOptions = ref([ { label: '全部', value: null }, { label: '已提交', value: 1 }, { label: '未提交', value: 0 } ]); const showStateList = ref(false); // 计算选中的被测评人标签 const selectedBdrLabel = computed(() => { if (formData.dcId.length === 0) return ''; const selected = bdrOptions.value.find(b => b.value === formData.dcId[0]); return selected ? selected.label : ''; }); // 获取状态标签 const getStateLabel = (value) => { const state = stateOptions.value.find(s => s.value === value); return state ? state.label : '全部'; }; // 过滤选项 const filterBdrOptions = () => { if (!bdrSearchKeyword.value) { filteredBdrOptions.value = [...bdrOptions.value]; return; } const keyword = bdrSearchKeyword.value.toLowerCase(); filteredBdrOptions.value = bdrOptions.value.filter(item => item.label.toLowerCase().includes(keyword) ); }; // 选择状态 const handleStateSelect = (state) => { formData.state = state.value; showStateList.value = false; }; // 切换下拉列表显示 const toggleBdrList = () => { showBdrList.value = !showBdrList.value; if (showBdrList.value) { filterBdrOptions(); } }; // 切换状态列表显示 const toggleStateList = () => { showStateList.value = !showStateList.value; }; // 获取问卷数据 const fetchSurveyData = async () => { try { loading.value = true; // 获取 token const token = uni.getStorageSync('token'); if (!token) { uni.showToast({ title: '请先登录', icon: 'none' }); uni.redirectTo({ url: '/pages/login/login' }); return; } // 准备请求参数 const params = { pageNum: pagination.current, pageSize: pagination.size, dcWjTitle: formData.dcWjTitle, dcId: formData.dcId.join(','), dcDept: formData.dcDept, state: formData.state }; // 发送请求 const res = await uni.request({ url: 'http://172.26.26.43/dev-api/wjdc/wj/listTx', method: 'GET', data: params, header: { 'Authorization': `Bearer ${token}` } }); // 错误处理 if (res.statusCode !== 200) { throw new Error(`请求失败,状态码: ${res.statusCode}`); } // 处理响应数据 const response = res.data; if (response.code === 200) { surveyList.value = response.rows || []; total.value = response.total || 0; pagination.total = response.total || 0; } else { throw new Error(response.msg || 'API返回错误'); } } catch (error) { console.error('请求错误:', error); uni.showToast({ title: error.message || '加载失败', icon: 'none', duration: 3000 }); } finally { loading.value = false; } }; // 获取被测评人列表 const fetchBdrList = async () => { try { const token = uni.getStorageSync('token'); if (!token) { uni.showToast({ title: '请先登录', icon: 'none' }); return; } const res = await uni.request({ url: 'http://172.26.26.43/dev-api/wjdc/wj/getBdrList', method: 'GET', header: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, timeout: 8000 }); if (res.statusCode !== 200) { throw new Error(`HTTP错误: ${res.statusCode}`); } const response = res.data; let data = []; if (Array.isArray(response)) { data = response; } else if (response.data) { data = response.data; } else if (response.rows) { data = response.rows; } else { throw new Error('无效的API响应格式'); } if (!Array.isArray(data)) { throw new Error('响应数据格式错误'); } bdrOptions.value = data.map(item => ({ label: item.dcName || '未知名称', value: item.dcId || item.id || null })); // 初始化过滤后的选项 filteredBdrOptions.value = [...bdrOptions.value]; } catch (error) { console.error('获取被测评人失败:', error); let errorMsg = '获取被测评人失败'; if (error.message.includes('401')) { errorMsg = '认证失败,请重新登录'; uni.redirectTo({ url: '/pages/login/login' }); } else if (error.message.includes('timeout')) { errorMsg = '请求超时,请检查网络'; } else if (error.message.includes('404')) { errorMsg = 'API地址不存在'; } uni.showToast({ title: errorMsg, icon: 'none', duration: 3000 }); } }; // 搜索按钮处理 const handleSearch = () => { pagination.current = 1; fetchSurveyData(); }; // 重置按钮处理 const handleReset = () => { formData.dcWjTitle = ''; formData.dcId = []; formData.dcDept = ''; formData.state = null; bdrSearchKeyword.value = ''; showBdrList.value = false; showStateList.value = false; handleSearch(); showBdrPlaceholder.value = true; // 重置后显示占位文字 }; // 编辑/查看问卷 const handleView = (item) => { uni.navigateTo({ url: `/pages/operation/operation?id=${item.dcWjId}` }); }; // 分页大小改变 const handleSizeChange = (e) => { pagination.size = e.detail.value; fetchSurveyData(); }; // 页码改变 const handlePageChange = (page) => { pagination.current = page; fetchSurveyData(); }; // 刷新数据 const refreshData = () => { pagination.current = 1; fetchSurveyData(); }; // 页面显示时加载数据 onShow(() => { fetchSurveyData(); fetchBdrList(); }); </script> <template> <view class="container"> <!-- 搜索表单区域 --> <view class="search-card"> <!-- 问卷标题单独一行 --> <view class="form-group"> <text class="form-label">问卷标题:</text> <input v-model="formData.dcWjTitle" placeholder="请输入问卷标题" class="form-input" /> </view> <!-- 被测评人和部门在同一行 --> <view class="form-row"> <!-- 被测评人选择器 --> <view class="form-group form-group-half"> <text class="form-label">被测评人:</text> <view class="search-select-container"> <!-- 搜索输入框 --> <input :value="bdrSearchKeyword" :placeholder="showBdrPlaceholder ? '搜索被测评人' : ''" class="search-input" @focus="handleBdrFocus" @input="handleBdrInput" /> <!-- 下拉列表 --> <view v-if="showBdrList" class="dropdown-list"> <scroll-view scroll-y="true" class="dropdown-scroll"> <view v-for="(item, index) in filteredBdrOptions" :key="index" class="dropdown-item" :class="{ 'selected': formData.dcId[0] === item.value }" @click="handleBdrSelect(item)" > {{ item.label }} </view> <view v-if="filteredBdrOptions.length === 0" class="empty-option"> 无匹配结果 </view> </scroll-view> </view> <!-- 已选项显示 --> <view v-if="formData.dcId.length > 0 && !showBdrList" class="selected-display"> {{ selectedBdrLabel }} </view> <!-- 下拉箭头 --> <view class="dropdown-icon" @click="toggleBdrList"> <text>▼</text> </view> <!-- 遮罩层 --> <view v-if="showBdrList" class="dropdown-mask" @click="showBdrList = false" ></view> </view> </view> <!-- 人员部门 --> <view class="form-group form-group-half"> <text class="form-label">人员部门:</text> <input v-model="formData.dcDept" placeholder="请输入部门" class="form-input" /> </view> </view> <!-- 提交状态 --> <view class="form-group"> <text class="form-label">提交状态:</text> <view class="search-select-container"> <!-- 状态选择框 --> <view class="state-select-box" @click="toggleStateList" > <text class="selected-state"> {{ getStateLabel(formData.state) }} </text> <view class="dropdown-icon"> <text>▼</text> </view> </view> <!-- 状态下拉列表 --> <view v-if="showStateList" class="dropdown-list state-dropdown"> <view v-for="(state, index) in stateOptions" :key="index" class="dropdown-item" :class="{ 'selected': formData.state === state.value }" @click="handleStateSelect(state)" > {{ state.label }} </view> </view> <!-- 遮罩层 --> <view v-if="showStateList" class="dropdown-mask" @click="showStateList = false" ></view> </view> </view> <!-- 按钮组 --> <view class="button-group"> <button class="search-button" @click="handleSearch">搜索</button> <button class="reset-button" @click="handleReset">重置</button> </view> </view> <!-- 数据显示区域 --> <view class="data-card"> <view class="card-header"> <button class="refresh-button" @click="refreshData">刷新数据</button> </view> <!-- 加载状态 --> <view v-if="loading" class="loading-container"> <view class="loading-spinner"></view> <text class="loading-text">加载中...</text> </view> <!-- 数据展示 --> <view v-else> <view v-for="(item, index) in surveyList" :key="index" class="data-card-item"> <view class="card-header-section"> <view class="card-title">{{ item.dcWjTitle }}</view> </view> <view class="card-body-section"> <view class="card-row"> <text class="card-label">被测评人:</text> <text class="card-value">{{ item.dcName }}</text> </view> <view class="card-row"> <text class="card-label">部门:</text> <text class="card-value">{{ item.dcDept }}</text> </view> <view class="card-row"> <text class="card-label">创建时间:</text> <text class="card-value">{{ item.createTime }}</text> </view> <view class="card-row"> <text class="card-label">提交时间:</text> <text class="card-value">{{ item.updateTime || '-' }}</text> </view> </view> <view class="card-footer-section"> <view class="status-container"> <view :class="['status-tag', item.state === '1' ? 'status-submitted' : 'status-not-submitted']"> {{ item.state === '1' ? '已提交' : '未提交' }} </view> <view class="score">总分: {{ item.score || '0' }}</view> </view> <button class="view-button" @click="handleView(item)">编辑/查看</button> </view> </view> <!-- 空数据提示 --> <view v-if="surveyList.length === 0" class="empty"> <text>暂无数据</text> </view> </view> <!-- 分页控件 --> <view class="pagination-container"> <picker mode="selector" :range="['5', '10', '20', '50']" @change="handleSizeChange" class="page-size-picker" > <view class="picker"> 每页 {{ pagination.size }} 条 </view> </picker> <view class="pagination-buttons"> <button :disabled="pagination.current === 1" @click="handlePageChange(pagination.current - 1)" class="page-button prev-button" > 上一页 </button> <text class="page-info"> 第 {{ pagination.current }} 页 / 共 {{ Math.ceil(pagination.total / pagination.size) }} 页 </text> <button :disabled="pagination.current >= Math.ceil(pagination.total / pagination.size)" @click="handlePageChange(pagination.current + 1)" class="page-button next-button" > 下一页 </button> </view> <text class="total-records">共 {{ pagination.total }} 条记录</text> </view> </view> </view> </template> <style scoped> .container { padding: 20rpx; background-color: #f5f5f5; min-height: 100vh; } /* 新增样式 */ .form-row { display: flex; gap: 20rpx; margin-bottom: 30rpx; } .form-group-half { flex: 1; min-width: 0; /* 防止内容溢出 */ } /* 调整搜索选择器容器高度 */ .search-select-container { position: relative; height: 80rpx; } /* 调整搜索输入框高度 */ .search-input { height: 80rpx; } /* 调整状态选择框高度 */ .state-select-box { height: 80rpx; } /* 搜索卡片样式 */ .search-card { background: #fff; border-radius: 16rpx; padding: 30rpx; margin-bottom: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05); } .form-group { margin-bottom: 30rpx; } .form-label { display: block; margin-bottom: 10rpx; font-size: 28rpx; color: #606266; font-weight: 500; } .form-input, .form-picker { width: 100%; height: 80rpx; padding: 0 20rpx; border: 1px solid #dcdfe6; border-radius: 8rpx; font-size: 28rpx; background-color: #fff; box-sizing: border-box; } .picker { height: 80rpx; line-height: 80rpx; color: #606266; } .button-group { display: flex; gap: 20rpx; margin-top: 20rpx; } .search-button, .reset-button { flex: 1; height: 80rpx; line-height: 80rpx; font-size: 30rpx; border-radius: 8rpx; text-align: center; } .search-button { background-color: #409eff; color: #fff; } .reset-button { background-color: #f5f7fa; color: #606266; border: 1px solid #dcdfe6; } /* 数据卡片样式 */ .data-card { background: #fff; border-radius: 16rpx; padding: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05); } .card-header { margin-bottom: 30rpx; } .refresh-button { background-color: #409eff; color: #fff; height: 70rpx; line-height: 70rpx; font-size: 28rpx; border-radius: 8rpx; } /* 数据卡片项 */ .data-card-item { background: #fff; border-radius: 16rpx; padding: 30rpx; margin-bottom: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05); border: 1px solid #ebeef5; } .card-header-section { padding-bottom: 20rpx; border-bottom: 1px solid #f0f2f5; margin-bottom: 20rpx; } .card-title { font-size: 34rpx; font-weight: bold; color: #303133; line-height: 1.4; word-break: break-word; } .card-body-section { margin-bottom: 20rpx; } .card-row { display: flex; margin-bottom: 15rpx; font-size: 28rpx; } .card-label { color: #606266; width: 150rpx; } .card-value { color: #303133; flex: 1; word-break: break-word; } .card-footer-section { display: flex; justify-content: space-between; align-items: center; padding-top: 20rpx; border-top: 1px solid #f0f2f5; } .status-container { display: flex; align-items: center; gap: 20rpx; } .status-tag { padding: 8rpx 20rpx; border-radius: 40rpx; font-size: 24rpx; font-weight: 500; } .status-submitted { background-color: #f0f9eb; color: #67c23a; border: 1px solid #e1f3d8; } .status-not-submitted { background-color: #fef0f0; color: #f56c6c; border: 1px solid #fde2e2; } .score { font-size: 28rpx; color: #e6a23c; font-weight: 500; } .view-button { background-color: #409eff; color: #fff; height: 60rpx; line-height: 60rpx; padding: 0 30rpx; font-size: 26rpx; border-radius: 40rpx; } /* 分页样式 */ .pagination-container { margin-top: 40rpx; display: flex; flex-direction: column; align-items: center; gap: 20rpx; } .page-size-picker { width: 200rpx; height: 60rpx; border: 1px solid #dcdfe6; border-radius: 8rpx; text-align: center; line-height: 60rpx; font-size: 26rpx; } .pagination-buttons { display: flex; align-items: center; gap: 20rpx; } .page-button { height: 60rpx; line-height: 60rpx; padding: 0 30rpx; font-size: 26rpx; border-radius: 8rpx; background-color: #f5f7fa; color: #606266; border: 1px solid #dcdfe; } .page-button:disabled { opacity: 0.5; } .prev-button::before { content: "← "; } .next-button::after { content: " →"; } .page-info { font-size: 26rpx; color: #606266; } .total-records { font-size: 26rpx; color: #909399; } /* 加载状态样式 */ .loading-container { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 80rpx 0; } .loading-spinner { width: 80rpx; height: 80rpx; border: 8rpx solid #f3f3f3; border-top: 8rpx solid #3498db; border-radius: 50%; animation: spin 1s linear infinite; margin-bottom: 30rpx; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading-text { color: #666; font-size: 28rpx; } /* 空数据提示 */ .empty { text-align: center; padding: 100rpx 0; color: #999; font-size: 32rpx; } /* 新增的搜索选择器样式 */ .search-select-container { position: relative; width: 100%; } .search-input { width: 100%; height: 80rpx; padding: 0 60rpx 0 20rpx; border: 1px solid #dcdfe6; border-radius: 8rpx; font-size: 28rpx; background-color: #fff; box-sizing: border-box; } .dropdown-icon { position: absolute; right: 20rpx; top: 50%; transform: translateY(-50%); pointer-events: none; font-size: 24rpx; color: #606266; } .dropdown-list { position: absolute; top: 100%; left: 0; right: 0; max-height: 400rpx; background: #fff; border: 1px solid #dcdfe6; border-radius: 8rpx; z-index: 1000; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1); margin-top: 10rpx; } .dropdown-scroll { max-height: 400rpx; } .dropdown-item { padding: 20rpx; font-size: 28rpx; color: #333; border-bottom: 1px solid #f0f2f5; } .dropdown-item.selected { background-color: #f5f7fa; color: #409eff; font-weight: 500; } .dropdown-item:last-child { border-bottom: none; } .dropdown-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: transparent; z-index: 999; } .empty-option { padding: 20rpx; text-align: center; color: #999; font-size: 28rpx; } .selected-display { position: absolute; top: 0; left: 0; right: 60rpx; height: 80rpx; padding: 0 20rpx; line-height: 80rpx; color: #303133; pointer-events: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* 状态选择器样式 */ .state-select-box { position: relative; width: 100%; height: 80rpx; padding: 0 60rpx 0 20rpx; border: 1px solid #dcdfe6; border-radius: 8rpx; font-size: 28rpx; background-color: #fff; display: flex; align-items: center; box-sizing: border-box; } .selected-state { color: #303133; } .state-dropdown { max-height: 300rpx; } </style> 我想要修改搜索板块的布局,我想要提交状态板块和搜索、重置按钮在同一行,不至于太宽
07-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值