1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072 |
- <template>
- <main class="index_main newsDetail">
- <HomePageHead></HomePageHead>
- <HomePageNavigation></HomePageNavigation>
-
- <!-- 面包屑导航 -->
- <div class="breadcrumb">
- <div class="inner">
- <span class="location">当前位置:</span>
- <el-breadcrumb :separator-icon="ArrowRight">
- <el-breadcrumb-item>
- <NuxtLink to="/">首页</NuxtLink>
- </el-breadcrumb-item>
-
- <el-breadcrumb-item> {{ title }}</el-breadcrumb-item>
- </el-breadcrumb>
- </div>
- </div>
- <div class="breadcrumb_title">
- <div>{{ remark }}</div>
- </div>
- <el-skeleton v-if="pageLoading" :rows="24" :animated="true" style="margin: 20px;">
- <template #template>
- <div class="custom-skeleton-multi">
- <span
- v-for="(item, idx) in skeletonChars"
- :key="idx"
- class="custom-skeleton-char"
- :style="{
- top: item.top + '%',
- left: item.left + '%',
- fontSize: item.fontSize + 'px',
- opacity: item.opacity,
- transform: `rotate(${item.rotate}deg)`
- }"
- >政讯通</span>
- </div>
- </template>
- </el-skeleton>
- <el-form v-else :model="formData" :rules="rules_js" ref="formRef" label-width="120px" class="form_box">
- <el-form-item
- v-for="(per_obj,per_index) in table_head.value"
- :key="per_index"
- :prop="getFieldName(per_obj)"
- :label="per_obj.title + ':'"
- :required="per_obj.is_check === 1"
- >
- <!-- 文本文字1 -->
- <el-input
- v-if="checkFieldType(per_obj, 1)"
- v-model="formData[getFieldName(per_obj)]"
- :placeholder="`请输入${per_obj.title}`"
- />
-
- <!-- 多行textarea 2-->
- <el-input
- v-if="checkFieldType(per_obj, 2)"
- v-model="formData[getFieldName(per_obj)]"
- type="textarea"
- :autosize="{ minRows: 2, maxRows: 4 }"
- :placeholder="`请输入${per_obj.title}`"
- />
-
- <!-- 单选按钮 3 -->
- <el-radio-group
- v-if="checkFieldType(per_obj, 3)"
- v-model="formData[getFieldName(per_obj)]">
- <el-radio
- v-for="per_3_obj in radio_arr_fun(per_obj.option_value)"
- :key="`${getFieldName(per_obj)}_${per_3_obj[1]}`"
- :label="per_3_obj[1]">
- {{ per_3_obj[0] }}
- </el-radio>
- </el-radio-group>
-
- <!-- 下拉选择 4 -->
- <el-select
- v-if="checkFieldType(per_obj, 4)"
- placeholder="请选择"
- v-model="formData[getFieldName(per_obj)]"
- style="width: 100%"
- >
- <el-option
- v-for="per_4_obj in select_arr_fun(per_obj.option_value)"
- :key="`${getFieldName(per_obj)}_${per_4_obj.value}`"
- :label="per_4_obj.label"
- :value="per_4_obj.value">
- </el-option>
- </el-select>
-
- <!-- 复选框5 -->
- <el-checkbox-group
- v-if="checkFieldType(per_obj, 5)"
- v-model="formData[getFieldName(per_obj)]"
- @change="(value) => handleCheckboxChange(getFieldName(per_obj), value)"
- >
- <el-checkbox
- v-for="per_5_obj in checkbox_arr_fun(per_obj.option_value)"
- :key="`${getFieldName(per_obj)}_${per_5_obj.value}`"
- :label="per_5_obj.value">
- {{ per_5_obj.label }}
- </el-checkbox>
- </el-checkbox-group>
-
- <!-- 日期选择器 6 -->
- <el-date-picker
- v-if="checkFieldType(per_obj, 6)"
- v-model="formData[getFieldName(per_obj)]"
- type="date"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- placeholder="选择日期"
- style="width: 100%"
- :locale="zhCn">
- </el-date-picker>
- <!-- 单文件上传 7 (新) -->
- <el-upload
- v-if="checkFieldType(per_obj, 7)"
- :ref="(el) => uploadRefs[getFieldName(per_obj)] = el"
- :action="`${$webUrl}/public/uploadFile`"
- :limit="1"
- :on-exceed="(files) => handleExceed(files, getFieldName(per_obj))"
- :on-success="(res, file) => handleFileSuccess(res, file, getFieldName(per_obj))"
- :on-remove="() => handleFileRemove(getFieldName(per_obj))"
- :file-list="fileLists[getFieldName(per_obj)] || []"
- >
- <el-button type="primary">点击上传文件</el-button>
- <template #tip>
- <div class="el-upload__tip">
- 只能上传一个文件,新文件将覆盖旧文件。
- </div>
- </template>
- </el-upload>
- <!-- img上传 8 -->
- <el-upload
- v-if="checkFieldType(per_obj, 8)"
- class="avatar-uploader"
- :action="`${$webUrl}/public/uploadFile`"
- :show-file-list="false"
- :on-success="(res) => handleAvatarSuccess(res, getFieldName(per_obj))"
- :before-upload="beforeAvatarUpload"
- >
- <img v-if="formData[getFieldName(per_obj)]" :src="formData[getFieldName(per_obj)]" class="avatar" >
- <div v-else class="avatar-uploader-placeholder">
- <img src="http://img.bjzxtw.org.cn/master/image/noImage.png" class="avatar-placeholder-img" alt="上传头像">
- <span class="upload-tip">点击上传</span>
- </div>
- </el-upload>
- </el-form-item>
-
- <!-- 验证码 -->
- <el-form-item v-if="showCaptcha" prop="code" label="验证码:">
- <div class="captcha-wrapper">
- <el-input v-model="formData.code" placeholder="请输入验证码" @keyup.enter="submitForm"></el-input>
- <img v-if="captchaImage" :src="captchaImage" @click="refreshCaptcha" alt="验证码" class="captcha-img" title="点击刷新">
- </div>
- </el-form-item>
- <el-form-item class="form-actions">
- <el-button type="primary" @click="submitForm" :loading="submitLoading">提交</el-button>
- <el-button @click="resetForm">重置</el-button>
- </el-form-item>
- </el-form>
- <HomeFoot></HomeFoot>
- </main>
- <el-dialog v-model="dialogVisible" title="提示" width="300px" :close-on-click-modal="false" :show-close="false" align-center>
- <div style="text-align:center;">表单提交成功!</div>
- <template #footer>
- <div class="dialog-footer-center">
- <el-button type="primary" @click="onDialogConfirm" class="dialog-confirm-btn">确认</el-button>
- </div>
- </template>
- </el-dialog>
- </template>
- <style scoped>
- @charset "utf-8";
- * {
- margin: 0;
- padding: 0;
- font-family: "微软雅黑", "microsoft yahei";
- }
- ul,
- ol {
- list-style: none;
- }
- a:active {
- text-decoration: none;
- }
- a:hover {
- text-decoration: none;
- }
- a:visited {
- text-decoration: none;
- }
- a:link {
- text-decoration: none;
- }
- a:focus {
- text-decoration: none;
- }
- body {
- position: relative;
- }
- .clearfix {
- overflow: hidden;
- }
- .clearfix_2::after {
- content: '';
- display: block;
- height: 0;
- visibility: hidden;
- clear: both;
- }
- .hiddenColor {
- visibility: hidden;
- }
- .hand {
- cursor: pointer;
- }
- .aTag_parent {
- position: relative;
- }
- .aTag_parent>a,
- .aTag {
- display: block;
- width: 100%;
- height: 100%;
- position: absolute;
- z-index: 99;
- border: 0px;
- top: 0px;
- left: 0px;
- background: rgba(0, 0, 0, 0);
- }
- .dot1 {
- display: block;
- word-break: keep-all;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- .dot2 {
- overflow: hidden;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 2;
- }
- .dot3{
- overflow: hidden;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 3;
- }
- input,
- img {
- border: none;
- }
- .cover100 img {
- display: block;
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- .back100 {
- background-size: 100% 100%;
- background-repeat: no-repeat;
- }
- article,
- aside,
- footer,
- header,
- time,
- video,
- main,
- nav,
- h4,
- h3,
- section {
- display: block;
- }
- .index_main {
- margin: 0 auto;
- }
- .slow_6 {
- -webkit-transition: all .6s;
- -moz-transition: all .6s;
- -ms-transition: all .6s;
- -o-transition: all .6s;
- transition: all .6s;
- }
- .form_box {
- width: 1200px;
- margin: 0px auto 20px auto;
- /* border: dashed 1px #000; */
- padding: 20px;
- }
-
- .form_box :deep(.avatar-uploader) {
- border: 1px dashed var(--el-border-color);
- border-radius: 6px;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- width: 178px;
- height: 178px;
- }
- .form_box :deep(.avatar-uploader:hover) {
- border-color: var(--el-color-primary);
- }
- .form_box :deep(.avatar-uploader .avatar) {
- width: 100%;
- height: 100%;
- display: block;
- }
- .form_box :deep(.avatar-uploader .el-upload) {
- width: 100%;
- height: 100%;
- }
- .form_box :deep(.el-button--primary) {
- padding: 0 11px;
- }
- @media screen and (min-width:1200px) {
- /*pc_1440*/
- @media screen and (max-width:1440px) {
- /*1200*/
- }
- .pc_none {
- display: none;
- }
- }
- @media screen and (max-width:599px) {}
- @media screen and (max-width:320px) {}
- .form_box .el-form-item {
- margin-bottom: 20px!important;
- }
- .avatar-uploader-placeholder {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- width: 100%;
- height: 100%;
- }
- .avatar-placeholder-img {
- width: 50px;
- height: 50px;
- opacity: 0.5;
- }
- .upload-tip {
- margin-top: 8px;
- color: #8c939d;
- font-size: 12px;
- }
- .form-actions :deep(.el-form-item__content) {
- justify-content: center;
- }
- .form-actions .el-button + .el-button {
- margin-left: 20px;
- padding: 0 11px;
- }
- .captcha-wrapper {
- display: flex;
- align-items: center;
- width: 100%;
- }
- .captcha-img {
- margin-left: 10px;
- cursor: pointer;
- height: 32px; /* 与el-input默认高度对齐 */
- border-radius: 4px;
- }
- .form_box :deep(.el-checkbox) {
- margin-right: 20px;
- }
- .form_box :deep(.el-radio) {
- margin-right: 20px;
- }
- /* 弹窗footer按钮居中 */
- .dialog-footer-center {
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .dialog-confirm-btn {
- padding: 0 32px;
- }
- .custom-skeleton-multi {
- position: relative;
- width: 100%;
- height: 700px;
- background: #f5f6fa;
- border-radius: 8px;
- overflow: hidden;
- }
- .custom-skeleton-char {
- position: absolute;
- color: #e5e6eb;
- font-weight: bold;
- letter-spacing: 10px;
- user-select: none;
- pointer-events: none;
- transition: all 0.3s;
- }
- .breadcrumb{
-
- width: 1200px !important;
- margin: 20px auto 0px auto !important;
-
- }
- .breadcrumb_title{
- width: 1200px;
- margin: 20px auto 0px auto;
- background-color:#0E6EBE ;
- color:white;
- line-height: 28px;
- }
- .breadcrumb_title div{
- font-size: 16px;
- /* font-weight: bold; */
- padding: 5px 20px;
- display: inline-block;
- vertical-align: middle;
- letter-spacing: 3px; /* 添加字间距,可以根据需要调整数值 */
- }
- </style>
- <style lang="less" scoped>
- .breadcrumb {
- width: 100%;
- height: 22px;
- margin-top: 40px;
- font-family: Microsoft YaHei, Microsoft YaHei;
- font-weight: 400;
- font-size: 20px;
- color: #666666;
- line-height: 23px;
- text-align: left;
- font-style: normal;
- text-transform: none;
- .el-breadcrumb::v-deep {
- display: inline-block;
- vertical-align: -4px;
- }
- :deep(.el-breadcrumb__inner a),
- :deep(.el-breadcrumb__inner.is-link) {
- color: #666666;
- font-weight: 400;
- text-decoration: none;
- transition: var(--el-transition-color);
- }
- span {
- font-family: Microsoft YaHei, Microsoft YaHei;
- font-weight: 400;
- font-size: 20px;
- color: #666666;
- line-height: 23px;
- text-align: left;
- font-style: normal;
- text-transform: none;
- }
- span:hover {
- color: #666666;
- }
- .location {
- margin-right: 20px;
- width: 100px;
- height: 22px;
- font-family: Microsoft YaHei, Microsoft YaHei;
- font-weight: 400;
- font-size: 20px;
- color: #666666;
- line-height: 23px;
- text-align: left;
- font-style: normal;
- text-transform: none;
- }
- }
- </style>
- <script setup>
- import { ArrowRight } from '@element-plus/icons-vue'
- //页面是否已经加载完毕
- const pageLoading = ref(true)
- const submitLoading = ref(false)
- const showCaptcha = ref(false)
- const captchaImage = ref('')
- const captchaId = ref('')
- const dialogVisible = ref(false)
- const title = ref('ceshi')
- const remark = ref('nice')
- const seoTitle = ref('')
- const seoKeywords = ref('')
- const seoDescription = ref('')
- //1.加载页面必备组件 start---------------------------------------->
- import { ref, onMounted, reactive, nextTick, onBeforeUpdate } from 'vue';
- import { useSeoMeta } from '#imports';
- import {ElBreadcrumb, ElBreadcrumbItem, ElForm, ElFormItem, ElInput, ElRadioGroup, ElRadio,
- ElCheckboxGroup, ElCheckbox, ElUpload, ElMessage,
- ElSelect, ElOption, ElDatePicker, ElButton, genFileId,ElDialog } from 'element-plus'
- const { $webUrl, $CwebUrl } = useNuxtApp();
- // 表单引用
- const formRef = ref(null)
- // 上传组件引用
- const uploadRefs = ref({});
- const fileLists = ref({});
- onBeforeUpdate(() => {
- uploadRefs.value = {};
- });
- // 动态验证规则
- const rules_js = ref({})
- const get_from_data_1 = reactive({
- value:{}
- });
- const get_from_data= reactive({
- value:{}
- });
- const chinese_calendar = reactive({});
-
- //列表头
- const table_head = reactive({
- value:[]
- });
- //列表内容
- const table_body = reactive({
- value:[]
- });
- // 表单数据 - 使用ref而不是reactive来避免响应式问题
- const formData = ref({})
- const route = useRoute()
- // 从路由获取 table_id,如果不存在则使用默认值
- const table_id = ref(route.query.table_id || 59)
- // 得到id
- const recive_id = reactive({
- value:route.query.id || route.params.id
- })
- // 工具函数定义
- function getFieldName(field) {
- if (field.field) return field.field;
- const possibleFieldNames = ['name', 'field_name', 'key', 'id'];
- for (const name of possibleFieldNames) {
- if (field[name]) return field[name];
- }
- return undefined;
- }
- // 检查字段类型的函数,支持数组格式
- function checkFieldType(field, type) {
- if (!field.field_type) return false;
- if (Array.isArray(field.field_type)) {
- return field.field_type.map(Number).includes(Number(type));
- }
- return Number(field.field_type) === Number(type);
- }
- // 检查是否为数组类型字段(field_type为5或包含5的数组)
- function isArrayTypeField(field) {
- return checkFieldType(field, 5);
- }
- // 生成动态验证规则
- function generateValidationRules() {
- const rules = {}
-
- table_head.value.forEach((field, index) => {
- const fieldRules = []
- const fieldName = getFieldName(field)
-
- // 必填验证
- if (field.is_check === 1) {
- fieldRules.push({
- required: true,
- message: `${field.title}不能为空`,
- trigger: ['blur', 'change']
- })
- }
-
- // 正则验证
- if (field.regular && field.regular.trim()) {
- try {
- const regex = parseRegExp(field.regular)
- fieldRules.push({
- validator: (rule, value, callback) => {
- if (value && !regex.test(value)) {
- callback(new Error(`${field.title}格式不正确`))
- } else {
- callback()
- }
- },
- trigger: ['blur', 'change']
- })
- } catch (error) {
- console.error(`正则表达式错误: ${field.regular}`, error)
- }
- }
-
- if (fieldRules.length > 0 && fieldName) {
- rules[fieldName] = fieldRules
- }
- })
-
- // 添加验证码规则
- if (showCaptcha.value) {
- rules['code'] = [
- { required: true, message: '验证码不能为空', trigger: 'blur' }
- ]
- }
- rules_js.value = rules
- }
- // 刷新验证码
- async function refreshCaptcha() {
- try {
- // 拼接 GET 参数
- const params = new URLSearchParams({ table_id: table_id.value });
- const url = `${$webUrl}/form/getWebGlobalTableFieldList?${params.toString()}`;
-
- const response = await fetch(url, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- 'Userurl': $CwebUrl,
- 'Origin': $CwebUrl
- }
- });
- const get_from_data = await response.json();
- // 只处理验证码相关的数据
- if (get_from_data.data?.table?.is_code === 1 && get_from_data.data?.code?.img) {
- showCaptcha.value = true
- captchaId.value = get_from_data.data.code.code_uniqid
- // 确保base64字符串包含正确的前缀
- if (get_from_data.data.code.img.startsWith('data:image')) {
- captchaImage.value = get_from_data.data.code.img
- } else {
- captchaImage.value = 'data:image/png;base64,' + get_from_data.data.code.img
- }
- // 清空验证码输入框
- formData.value.code = ''
- } else {
- showCaptcha.value = false
- captchaImage.value = ''
- captchaId.value = ''
- }
- } catch (error) {
- console.error('刷新验证码失败:', error);
- ElMessage.error('刷新验证码失败,请重试');
- }
- }
- useSeoMeta({
- title: seoTitle,
- meta: [
- { name: 'keywords', content: seoKeywords, tagPriority: 10 },
- { name: 'description', content: seoDescription, tagPriority: 10 }
- ]
- });
- async function get_from_data_fun() {
- pageLoading.value = true
- try {
- // 拼接 GET 参数
- const params = new URLSearchParams({ table_id: table_id.value });
- const url = `/form/getWebGlobalTableFieldList?${params.toString()}`;
- console.log("url:",url)
- const response = await requestDataPromise(url, {
- method: 'GET',
- query: {}
-
- });
- const get_from_data = response
- console.log("返回数据:",get_from_data,response)
- title.value = get_from_data.data.table.name
- remark.value = get_from_data.data.table.remark
- seoTitle.value = response.data.table.name + "_" + response.data.table.website_name + "_" + response.data.table.suffix
- seoKeywords.value = response.data.table.keywords + "_" + response.data.table.website_name + "_" + response.data.table.suffix
- seoDescription.value = response.data.table.description + "_" + response.data.table.website_name + "_" + response.data.table.suffix
-
- // 检查是否需要显示验证码(仅在初始化时)
- if (get_from_data.data?.table?.is_code === 1 && get_from_data.data?.code?.img) {
- showCaptcha.value = true
- captchaId.value = get_from_data.data.code.code_uniqid
- // 确保base64字符串包含正确的前缀
- if (get_from_data.data.code.img.startsWith('data:image')) {
- captchaImage.value = get_from_data.data.code.img
- } else {
- captchaImage.value = 'data:image/png;base64,' + get_from_data.data.code.img
- }
- } else {
- showCaptcha.value = false
- captchaImage.value = ''
- captchaId.value = ''
- }
- // 赋值表头和表体
- table_head.value = get_from_data.data?.fields || [];
- table_body.value = get_from_data.data?.table || [];
- get_from_data_1.value = get_from_data;
- // 统一 field_type 为数字或数字数组
- table_head.value.forEach(field => {
- if (typeof field.field_type === 'string') {
- if (field.field_type.includes(',')) {
- field.field_type = field.field_type.split(',').map(Number);
- } else {
- field.field_type = Number(field.field_type);
- }
- }
- });
- // 如果API返回的数据为空,使用默认数据
- if (table_head.value.length === 0) {
- table_head.value = []
- }
- // 详细检查每个字段的结构
- table_head.value.forEach((field, index) => {
- if (field.option_value) {
- }
- })
- // 初始化表单数据
- table_head.value.forEach(field => {
- const fieldName = getFieldName(field)
- if (!fieldName) {
- console.warn(`字段 ${field.title} 无法确定字段名,跳过初始化`)
- return
- }
-
- // 根据字段类型初始化不同的默认值
- if (isArrayTypeField(field)) {
- // 数组类型字段(field_type为5或包含5的数组)初始化为空数组
- formData.value[fieldName] = []
- } else if (checkFieldType(field, 7) || checkFieldType(field, 8)) {
- formData.value[fieldName] = ''
- fileLists.value[fieldName] = []
- }
- else {
- // 其他类型初始化为空字符串
- formData.value[fieldName] = ''
- }
- })
- // 单独初始化验证码字段
- if (showCaptcha.value) {
- formData.value.code = ''
- }
-
- // 生成验证规则
- generateValidationRules()
- pageLoading.value = false
- } catch (error) {
- console.error('请求失败:', error);
-
- // 使用默认数据
- table_head.value = []
-
- // 初始化默认数据
- table_head.value.forEach(field => {
- const fieldName = getFieldName(field)
- if (isArrayTypeField(field)) {
- formData.value[fieldName] = []
- } else if (checkFieldType(field, 7) || checkFieldType(field, 8)) {
- formData.value[fieldName] = ''
- fileLists.value[fieldName] = []
- }
- else {
- formData.value[fieldName] = ''
- }
- })
-
- // 单独初始化验证码字段
- if (showCaptcha.value) {
- formData.value.code = ''
- }
- generateValidationRules()
- pageLoading.value = false
- ElMessage.warning('API请求失败,使用默认数据')
- }
- }
- get_from_data_fun();
- // 提交表单
- async function submitForm() {
- if (!formRef.value) {
- ElMessage.error('表单引用不存在')
- return
- }
-
- try {
- submitLoading.value = true
-
- // 手动检查必填字段
- const requiredFields = table_head.value.filter(field => field.is_check === 1)
-
- const missingFields = requiredFields.filter(field => {
- const fieldName = getFieldName(field)
- if (!fieldName) {
- console.warn(`字段 ${field.title} 无法确定字段名`)
- return true
- }
-
- const value = formData.value[fieldName]
- const isEmpty = value === '' || value === null || value === undefined || (Array.isArray(value) && value.length === 0)
- return isEmpty
- })
-
- if (missingFields.length > 0) {
- ElMessage.error(`请填写必填字段: ${missingFields.map(f => f.title).join(', ')}`)
- return
- }
-
- // 表单验证 - 使用正确的验证方式
- await formRef.value.validate(async (valid, fields) => {
- if (valid) {
- // 构建提交数据
- const otherDataPayload = { 'table_id': table_id.value };
- const dataToSubmit = { ...formData.value };
- if (showCaptcha.value) {
- otherDataPayload.code = dataToSubmit.code;
- otherDataPayload.code_uniqid = captchaId.value;
- delete dataToSubmit.code;
- }
- const submitData = {
- otherData: otherDataPayload,
- data: dataToSubmit
- }
-
- // 这里可以调用实际的提交接口
- const response = await fetch(`${$webUrl}/form/addWebGlobalTableData`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Userurl': $CwebUrl,
- 'Origin': $CwebUrl
- },
- body: JSON.stringify(submitData)
- })
- const result = await response.json();
- if(result.code==200){
- dialogVisible.value = true
- return
- }else{
- ElMessage.error(result.message)
- return
- }
-
- } else {
- ElMessage.error('请检查表单填写是否正确')
- }
- })
-
- } catch (error) {
- console.error('提交失败:', error)
- ElMessage.error('提交失败,请重试')
- } finally {
- submitLoading.value = false
- }
- }
- // 重置表单
- async function resetForm() {
- await get_from_data_fun();
- ElMessage.success('表单已重置');
- }
- // 下拉选择对象转数组
- function select_arr_fun(option_obj){
- if (!option_obj || typeof option_obj !== 'object') return []
-
- let new_arr = []
-
- // 遍历对象,key为value,value为label
- Object.keys(option_obj).forEach(key => {
- let the_in_obj = {}
- the_in_obj.label = option_obj[key]
- the_in_obj.value = +key // 转换为数字
- new_arr.push(the_in_obj)
- })
-
- return new_arr
- }
- // 单选按钮对象转数组
- function radio_arr_fun(option_obj) {
- if (!option_obj || typeof option_obj !== 'object') return []
-
- let new_arr = []
-
- // 遍历对象,key为value,value为label
- Object.keys(option_obj).forEach(key => {
- new_arr.push([option_obj[key], key]) // [label, value] 格式
- })
-
- return new_arr
- }
- // 复选框对象转数组
- function checkbox_arr_fun(option_obj) {
- if (!option_obj || typeof option_obj !== 'object') return []
-
- let new_arr = []
-
- // 遍历对象,key为value,value为label
- Object.keys(option_obj).forEach(key => {
- let the_in_obj = {}
- the_in_obj.label = option_obj[key]
- the_in_obj.value = String(key) // 确保值为字符串类型
- new_arr.push(the_in_obj)
- })
-
- return new_arr
- }
- // 文件上传相关
- // 文件超出限制时的处理
- const handleExceed = (files, fieldName) => {
- const upload = uploadRefs.value[fieldName];
- if (upload) {
- upload.clearFiles();
- const file = files[0];
- file.uid = genFileId();
- upload.handleStart(file);
- upload.submit();
- }
- };
- // 普通文件上传成功
- const handleFileSuccess = (res, file, fieldName) => {
- if (res.data && res.data.imgUrl) {
- formData.value[fieldName] = res.data.imgUrl;
- if (fileLists.value[fieldName]) {
- fileLists.value[fieldName] = [{
- name: file.name,
- url: res.data.imgUrl
- }];
- }
- }
- };
- // 文件移除
- const handleFileRemove = (fieldName) => {
- formData.value[fieldName] = '';
- if(fileLists.value[fieldName]) {
- fileLists.value[fieldName] = [];
- }
- };
- // img上传 8
- const handleAvatarSuccess = (res, fieldName) => {
- if (res.data && res.data.imgUrl) {
- formData.value[fieldName] = res.data.imgUrl
- }
- }
- const beforeAvatarUpload = (file) => {
- const isJPG = file.type === 'image/jpeg'
- const isPNG = file.type === 'image/png'
- const isLt2M = file.size / 1024 / 1024 < 2
- if (!isJPG && !isPNG) {
- ElMessage.error('只能上传 JPG/PNG 格式!')
- return false
- }
- if (!isLt2M) {
- ElMessage.error('图片大小不能超过 2MB!')
- return false
- }
- return (isJPG || isPNG) && isLt2M
- }
- // 页面加载时获取数据
- onMounted(async () => {
- await get_from_data_fun()
-
- // 确保表单引用存在
- await nextTick()
-
- if (formRef.value) {
- } else {
- }
- })
- // 复选框变化处理
- function handleCheckboxChange(field, value) {
- // 这里可以根据需要添加更多的逻辑处理
- }
- function parseRegExp(str) {
- if (typeof str === 'string' && str.startsWith('/') && str.lastIndexOf('/') > 0) {
- const lastSlash = str.lastIndexOf('/');
- const pattern = str.slice(1, lastSlash);
- const flags = str.slice(lastSlash + 1);
- return new RegExp(pattern, flags);
- }
- return new RegExp(str);
- }
- function onDialogConfirm() {
- dialogVisible.value = false;
- resetForm();
- }
- const skeletonChars = Array.from({ length: 16 }).map(() => ({
- top: Math.random() * 80 + 5, // 5%~85%
- left: Math.random() * 80 + 5, // 5%~85%
- fontSize: Math.random() * 60 + 60, // 60~120px
- opacity: Math.random() * 0.4 + 0.3, // 0.3~0.7
- rotate: Math.random() * 60 - 30 // -30~30deg
- }));
- </script>
|