rkljw 1 napja
szülő
commit
b1205cb62c
1 módosított fájl, 1026 hozzáadás és 0 törlés
  1. 1026 0
      pages/index_form.vue

+ 1026 - 0
pages/index_form.vue

@@ -0,0 +1,1026 @@
+<template>
+    <main class="index_main">
+        <HomePageHead></HomePageHead>
+        <HomePageNavigation></HomePageNavigation>
+
+        <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%">
+                </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: 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;
+}
+</style>
+
+<script setup>
+//页面是否已经加载完毕
+const pageLoading = ref(true)
+const submitLoading = ref(false)
+const showCaptcha = ref(false)
+const captchaImage = ref('')
+const captchaId = ref('')
+const dialogVisible = ref(false)
+
+//1.加载页面必备组件 start---------------------------------------->
+import { ref, onMounted, reactive, nextTick, onBeforeUpdate } from 'vue';
+import { useSeoMeta } from '#imports';
+
+import { ElForm, ElFormItem, ElInput, ElRadioGroup, ElRadio,
+         ElCheckboxGroup, ElCheckbox, ElUpload, ElMessage,
+         ElSelect, ElOption, ElDatePicker, ElButton, genFileId } from 'element-plus'
+
+const { $webUrl, $CwebUrl } = useNuxtApp();
+
+// 表单引用
+const formRef = ref(null)
+
+// 上传组件引用
+const uploadRefs = ref({});
+const fileLists = ref({});
+
+onBeforeUpdate(() => {
+  uploadRefs.value = {};
+});
+
+let adImg = ref({}) 
+//广告1               
+let url = `${$webUrl}/web/getWebsiteAdvertisement?ad_tag=tsbb_index_1`
+const responseAd1 = await fetch(url, {
+    headers: {
+        'Content-Type': 'application/json',
+        'Userurl': $CwebUrl,
+        'Origin': $CwebUrl
+    }
+});
+const resultAd1 = await responseAd1.json();
+adImg.value = resultAd1.data[0];
+ 
+let adImg_2 = ref({}) 
+//广告_2
+let url_2 = `${$webUrl}/web/getWebsiteAdvertisement?ad_tag=tsbb_index_2`
+const responseAd_2 = await fetch(url_2, {
+    headers: {
+        'Content-Type': 'application/json',
+        'Userurl': $CwebUrl,
+        'Origin': $CwebUrl
+    }
+});
+const resultAd_2 = await responseAd_2.json();
+adImg_2.value = resultAd_2.data[0];
+
+// 动态验证规则
+const rules_js = ref({})
+
+const get_from_data_1 = 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('刷新验证码失败,请重试');
+    }
+}
+
+// 获取form所有数据
+async function get_from_data_fun() {
+    pageLoading.value = true
+    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
+            }
+        } 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 = [
+                {
+                    field: 'name',
+                    title: '姓名',
+                    field_type: 1,
+                    is_check: 1
+                },
+                {
+                    field: 'email',
+                    title: '邮箱',
+                    field_type: 1,
+                    is_check: 1
+                },
+                {
+                    field: 'hobbies',
+                    title: '爱好',
+                    field_type: [5],
+                    is_check: 0,
+                    option_value: {1: "阅读", 2: "运动", 3: "音乐", 4: "旅游"}
+                }
+            ]
+        }
+
+        // 详细检查每个字段的结构
+        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 = [
+            {
+                field: 'name',
+                title: '姓名',
+                field_type: 1,
+                is_check: 1
+            },
+            {
+                field: 'email',
+                title: '邮箱',
+                field_type: 1,
+                is_check: 1
+            },
+            {
+                field: 'hobbies',
+                title: '爱好',
+                field_type: [5],
+                is_check: 0,
+                option_value: {1: "阅读", 2: "运动", 3: "音乐", 4: "旅游"}
+            }
+        ]
+        
+        // 初始化默认数据
+        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请求失败,使用默认数据')
+    }
+}
+
+// 提交表单
+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>