在 Wordpress 中使用 Vue

134 阅读7分钟

一、使用 pods 插件创建自定义字段

这里直接导入自定义内容字段和自定义分类

{
    "@meta": {
        "version": "3.1.4",
        "build": 1710169300
    },
    "settings": {
        "types_only": "0",
        "watch_changed_fields": "0",
        "metadata_integration": "1",
        "metadata_override_get": "0",
        "media_modal_fields": "0",
        "session_auto_start": "0",
        "dynamic_features_allow": "1",
        "dynamic_features_enabled": [
            "display",
            "form"
        ],
        "show_access_restricted_messages": "0",
        "show_access_admin_notices": "1",
        "dynamic_features_allow_sql_clauses": "0",
        "display_callbacks": "customized",
        "display_callbacks_allowed": "esc_attr,esc_html",
        "wisdom_opt_out": "1",
        "active_components": [
            "migrate-packages",
            "templates"
        ]
    },
    "pods": [
        {
            "name": "notice",
            "id": 8,
            "label": "\u901a\u544a",
            "description": "",
            "type": "post_type",
            "storage": "meta",
            "label_singular": "\u901a\u544a",
            "public": "1",
            "show_ui": "1",
            "rest_enable": "1",
            "supports_title": "1",
            "supports_editor": "1",
            "_migrated_28": "0",
            "pick_object": "custom-simple",
            "required": "0",
            "write_all": "notice",
            "rest_api_field_mode": "value",
            "read_all": "1",
            "pfat_enable": "0",
            "pfat_single": "0",
            "pfat_filter_single": "the_content",
            "pfat_archive": "0",
            "pfat_filter_archive": "the_excerpt",
            "pfat_run_outside_loop": "0",
            "supports_thumbnail": "1",
            "built_in_taxonomies_notice_categories": "1",
            "publicly_queryable": "1",
            "exclude_from_search": "0",
            "capability_type": "post",
            "capability_type_extra": "1",
            "disable_create_posts": "0",
            "has_archive": "0",
            "hierarchical": "0",
            "can_export": "1",
            "rewrite": "1",
            "rewrite_with_front": "1",
            "rewrite_feeds": "0",
            "rewrite_pages": "1",
            "query_var": "1",
            "default_status": "draft",
            "supports_author": "1",
            "supports_excerpt": "1",
            "supports_comments": "1",
            "supports_quick_edit": "1",
            "revisions_to_keep_limit": "0",
            "delete_with_user": "1",
            "capability_type_custom": "notice",
            "show_in_menu": "1",
            "menu_position": "0",
            "show_in_nav_menus": "1",
            "show_in_admin_bar": "1",
            "groups": [
                {
                    "name": "e69bb4e5a49ae5ad97e6aeb5",
                    "id": 9,
                    "label": "\u66f4\u591a\u5b57\u6bb5",
                    "description": "",
                    "weight": 0,
                    "fields": [
                        {
                            "name": "notice_require",
                            "id": 10,
                            "label": "\u901a\u544a\u9700\u6c42",
                            "description": "",
                            "weight": 0,
                            "type": "text",
                            "sister_id": "-- \u8bf7\u9009\u62e9 --",
                            "required": "0",
                            "text_allowed_html_tags": "strong em a ul ol li b i",
                            "text_max_length": "255",
                            "repeatable": "0",
                            "repeatable_format": "default",
                            "roles_allowed": "administrator",
                            "enable_conditional_logic": "0",
                            "rest_pick_response": "array",
                            "rest_pick_depth": "1",
                            "rest_write": "1",
                            "rest_read": "1"
                        },
                        {
                            "name": "notice_type",
                            "id": 11,
                            "label": "\u901a\u544a\u7c7b\u578b",
                            "description": "",
                            "weight": 1,
                            "type": "text",
                            "sister_id": "-- \u8bf7\u9009\u62e9 --",
                            "required": "0",
                            "text_allowed_html_tags": "strong em a ul ol li b i",
                            "text_max_length": "255",
                            "repeatable": "0",
                            "repeatable_format": "default",
                            "roles_allowed": "administrator",
                            "enable_conditional_logic": "0",
                            "rest_pick_response": "array",
                            "rest_pick_depth": "1",
                            "rest_read": "1",
                            "rest_write": "1"
                        },
                        {
                            "name": "notice_main_image",
                            "id": 12,
                            "label": "\u901a\u544a\u4e3b\u56fe",
                            "description": "",
                            "weight": 2,
                            "type": "file",
                            "sister_id": "-- \u8bf7\u9009\u62e9 --",
                            "required": "0",
                            "file_format_type": "multi",
                            "file_uploader": "attachment",
                            "file_type": "images",
                            "file_attachment_tab": "upload",
                            "file_upload_dir": "wp",
                            "file_edit_title": "1",
                            "file_show_edit_link": "1",
                            "file_linked": "0",
                            "file_limit": "0",
                            "file_field_template": "rows",
                            "file_add_button": "\u6dfb\u52a0\u6587\u4ef6",
                            "file_modal_title": "\u9644\u52a0\u4e00\u4e2a\u6587\u4ef6",
                            "file_modal_add_button": "\u6dfb\u52a0\u6587\u4ef6",
                            "file_wp_gallery_link": "file",
                            "file_wp_gallery_columns": "3",
                            "file_wp_gallery_size": "thumbnail",
                            "repeatable": "0",
                            "repeatable_format": "default",
                            "roles_allowed": "administrator",
                            "enable_conditional_logic": "0",
                            "rest_pick_response": "array",
                            "rest_pick_depth": "1",
                            "rest_read": "1",
                            "rest_write": "1"
                        },
                        {
                            "name": "contact_information",
                            "id": 13,
                            "label": "\u8054\u7cfb\u65b9\u5f0f",
                            "description": "",
                            "weight": 3,
                            "type": "text",
                            "sister_id": "-- \u8bf7\u9009\u62e9 --",
                            "required": "0",
                            "text_allowed_html_tags": "strong em a ul ol li b i",
                            "text_max_length": "255",
                            "repeatable": "0",
                            "repeatable_format": "default",
                            "roles_allowed": "administrator",
                            "enable_conditional_logic": "0",
                            "rest_pick_response": "array",
                            "rest_pick_depth": "1",
                            "rest_write": "1",
                            "rest_read": "1"
                        },
                        {
                            "name": "product_value",
                            "id": 14,
                            "label": "\u8d60\u54c1\u4ef7\u503c",
                            "description": "",
                            "weight": 4,
                            "type": "text",
                            "sister_id": "-- \u8bf7\u9009\u62e9 --",
                            "required": "0",
                            "text_allowed_html_tags": "strong em a ul ol li b i",
                            "text_max_length": "255",
                            "repeatable": "0",
                            "repeatable_format": "default",
                            "roles_allowed": "administrator",
                            "enable_conditional_logic": "0",
                            "rest_pick_response": "array",
                            "rest_pick_depth": "1",
                            "rest_write": "1",
                            "rest_read": "1"
                        },
                        {
                            "name": "product_weight",
                            "id": 15,
                            "label": "\u7269\u54c1\u91cd\u91cf",
                            "description": "",
                            "weight": 5,
                            "type": "text",
                            "sister_id": "-- \u8bf7\u9009\u62e9 --",
                            "required": "0",
                            "text_allowed_html_tags": "strong em a ul ol li b i",
                            "text_max_length": "255",
                            "repeatable": "0",
                            "repeatable_format": "default",
                            "roles_allowed": "administrator",
                            "enable_conditional_logic": "0",
                            "rest_pick_response": "array",
                            "rest_pick_depth": "1",
                            "rest_read": "1",
                            "rest_write": "1"
                        }
                    ]
                }
            ]
        },
        {
            "name": "notice_categories",
            "id": 16,
            "label": "\u901a\u544a\u5206\u7c7b",
            "description": "",
            "type": "taxonomy",
            "storage": "meta",
            "label_singular": "\u901a\u544a\u5206\u7c7b",
            "public": "1",
            "show_ui": "1",
            "hierarchical": "1",
            "rest_enable": "1",
            "_migrated_28": "0",
            "built_in_post_types_notice": "1",
            "groups": [
                {
                    "name": "e69bb4e5a49ae5ad97e6aeb5",
                    "id": 17,
                    "label": "\u66f4\u591a\u5b57\u6bb5",
                    "description": "",
                    "weight": 0,
                    "fields": []
                }
            ]
        }
    ]
}

二、使用 Vue3 和 Element Plus 创建自定义页面模版

这里通过 wp_create_nonce("wp_rest"); 获取用户登入状态 通过使用 /wp-json/wp/v2/media 接口上传图片文件数据

<?php
/*
Template Name: notece  Template
*/
get_header();
?>


<head>
    <script>
        window.isUserLoggedIn = <?php echo json_encode(is_user_logged_in()); ?>;
        window.wpseNonce = '<?php echo wp_create_nonce("wp_rest"); ?>';
    </script>
    <!-- Import style -->
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/element-plus/dist/index.css" />
    <!-- Import Vue 3 -->
    <script src="//cdn.jsdelivr.net/npm/vue@3"></script>
    <!-- Import component library -->
    <script src="//cdn.jsdelivr.net/npm/element-plus"></script>
    <script src="//cdn.jsdelivr.net/npm/@element-plus/icons-vue"></script>
    <script src="https://cdn.staticfile.org/axios/1.5.0/axios.min.js"></script>

    <style>
        .notice_body {
            width: 60%;
            margin: 0 auto;
            padding-top: 24px;
        }

        /* 单选择框切换样式 */
        .djcs_from_tonggao {
            width: 100%;
        }

        .djcs_margin_right {
            margin-right: 10px;
        }


        .el-radio-button__inner {
            background: #FFF;
            border: 1px solid #DCDFE6;
        }

        .el-radio-button:first-child .el-radio-button__inner {
            border-radius: 0;
        }

        .el-radio-button:last-child .el-radio-button__inner {
            border-radius: 0;
        }

        .el-radio-button .el-radio-button__inner {
            border-radius: 0px;
        }

        .el-upload--picture-card {
            width: 100px;
            height: 100px;
        }

        .el-progress-circle {
            display: none;
        }

        .el-upload-list--picture-card .el-upload-list__item {
            width: 100px;
            height: 100px;
        }

        .djcs_demand {
            border: 1px solid #d1d1d1;
            padding: 30px 60px 30px 0;
        }

        .djcs_demand_info {
            border: 1px solid #d1d1d1;
            border-bottom-width: 0px;
            padding: 10px 24px;

            line-height: 35px;
            font-size: 16px;
            font-weight: 700;
            color: #000;
        }

        .el-input--large .el-input__wrapper {
            padding: 1px 1px;
        }

        .djcs_button_notice {
            margin: 20px auto;
            --el-button-text-color: #ffffff !important;
        }



        .el-radio-button {
            --el-radio-button-checked-bg-color: #fee7ef;
            --el-radio-button-checked-border-color: #fa5f8b;
        }

        .el-radio-button__original-radio:checked+.el-radio-button__inner {
            box-shadow: none;
        }
    </style>
</head>

<div id="app" class="notice_body">
    <el-form :model="form" :rules="rules" size="large" label-width="120px">

        <div class="djcs_demand_info">
            <el-text>
                <el-icon>
                    <Document />
                </el-icon>
                通告需求
            </el-text>
        </div>
        <el-form-item label="通告类型" class="djcs_demand">
            <el-radio-group v-model="form.notice_require" text-color="#fa5f8b">
                <el-radio-button label="买家秀" class="djcs_margin_right"></el-radio-button>
                <el-radio-button label="种草/口播视频"></el-radio-button>
            </el-radio-group>
        </el-form-item>
        <div class="djcs_demand_info">
            <el-text>
                <el-icon>
                    <Document />
                </el-icon>
                通告基础信息
            </el-text>
        </div>

        <div class="djcs_demand">
            <el-form-item label="费用提示">
                <el-text class="mx-1" size="large">发布通告后模特报名并报价,您再挑选人,每个模特报价不同。寄拍时平台收5元/单服务费,赠拍平台收3元/单服务费!</el-text>
            </el-form-item>

            <el-form-item label="通告类型">
                <el-radio-group v-model="form.notice_type" text-color="#fa5f8b">
                    <el-radio-button label="产品赠送" class="djcs_margin_right"></el-radio-button>
                    <el-radio-button label="产品需寄回"></el-radio-button>
                </el-radio-group>
            </el-form-item>
            <el-form-item label="通告标题" prop="title" style="width: 600px">
                <el-input v-model="form.title" placeholder="可填写产品名称" />
            </el-form-item>

            <el-form-item label="通告主图">
                <el-upload v-model:file-list="fileList" action="/wp-json/wp/v2/media" :headers="headers" :limit="6"
                    multiple list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove"
                    :on-success="handleFileListSuccess">
                    <el-icon>
                        <Plus />
                    </el-icon>
                </el-upload>
                <el-text class="mx-1" size="large">提示:主图展示在通告大厅,默认加载宝贝主图,可修改</el-text>
            </el-form-item>

            <el-form-item label="商品类目">
                <el-select v-model="form.notice_categories" clearable placeholder="请选择" style="width: 240px">
                    <el-option v-for="item in product_category" :key="item.id" :label="item.name" :value="item.id" />
                </el-select>
            </el-form-item>

            <el-form-item label="商品价值" v-if="form.notice_type=='产品赠送'">
                <el-input v-model="form.product_value" placeholder="请输入赠品价值" style="width: 240px">
                    <template #append></template>
                </el-input>
            </el-form-item>
            <el-form-item label="物品重量" v-else>
                <el-input v-model="form.product_weight" placeholder="请输入物品重量" style="width: 240px">
                    <template #append>kg</template>
                </el-input>
            </el-form-item>
            <el-form-item label="联系方式" style="width: 600px">
                <el-input v-model="form.contact_information" placeholder="请输入联系电话" />
            </el-form-item>
            <el-form-item label="通告要求" style="width: 600px">
                <el-input v-model="form.content" type="textarea" />
            </el-form-item>
        </div>
        <el-form-item>
            <el-button size="large" type="primary" color="#fa5f8b" @click="onSubmit" class="djcs_button_notice"
                :disabled="disabled">立即发布</el-button>
        </el-form-item>
    </el-form>

    <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" style="width: 100%;" alt="Preview Image" />
    </el-dialog>


</div>


<script>
    const {
        createApp,
        ref,
        computed,
        reactive,
        onMounted
    } = Vue

    const app = createApp({
        setup() {
            const message = ref('Hello vue!')

            const disabled = ref(false)
            clickEvent = (e) => {
                alert('点击事件')
                message.value = "new Hello"
            }

            const open2 = () => {
                ElementPlus.ElMessage({
                    message: 'Congrats, this is a success message.',
                    type: 'success',
                })
                console.log(ElementPlus.UploadUserFile)
            }

            const fileList = ref([])

            const dialogImageUrl = ref('')
            const dialogVisible = ref(false)
            const handlePictureCardPreview = (uploadFile) => {
                dialogImageUrl.value = uploadFile.url
                dialogVisible.value = true
            }

            const handleRemove = (uploadFile, uploadFiles) => {
                console.log(uploadFile, uploadFiles)
            }

            const headers = ref({
                'X-WP-Nonce': window.wpseNonce,
            })

            const product_category = ref([]);
            const form = reactive({
                options: [{
                    value: 'Option1',
                    label: '母婴',
                },
                {
                    value: 'Option2',
                    label: '儿童',
                }
                ],
                title: '',
                content: '',
                status: "publish",
                notice_require: '买家秀',
                notice_type: '产品赠送',
                notice_main_image: [],
                notice_categories: '',
                product_value: '',
                product_weight: '',
                contact_information: '',
                // notice_need: '',
                // notice_title: '',
            })

            const notice_main_image_ids = ref([]);
            const handleFileListSuccess = (res, file) => {
                form.notice_main_image.push(res.id)
                console.log(999, form.notice_main_image)
            }

            const rules = reactive({
                title: [{
                    required: true,
                    message: '商品名称不能为空',
                    trigger: 'blur'
                },
                {
                    min: 2,
                    max: 20,
                    message: '输入2-20个字符',
                    trigger: 'blur'
                },
                ],
            })



            const onSubmit = async () => {
                if (form.title === "") {

                    ElementPlus.ElMessage({
                        message: '通告标题不能为空'
                    })
                    return;
                }

                // 准备要发送的数据
                const postData = {
                    ...form,
                    // title: '1发布通告页面内容',
                    // content: JSON.stringify(form),
                    // status: "publish",
                     featured_media: form.notice_main_image[0],
                    // notice_main_image: form.notice_main_image,
                    // notice_require: '买家秀',
                    //"notice_categories":3
                };

                console.log(111, postData)
                // 设置请求URL
                const url = '/wp-json/wp/v2/notice';

                // 发送POST请求
                try {
                    // 如果后端API期待JSON格式的数据
                    const config = {
                        headers: {
                            'Content-Type': 'application/json',
                            'X-WP-Nonce': this.wpseNonce // 添加nonce头
                        },
                    };
                    const response = await axios.post(url, JSON.stringify(postData), config);

                    if (response.status === 201) {
                        ElementPlus.ElMessage({
                            message: '发布成功',
                            type: 'success',
                        })
                        disabled.value = true;
                        setTimeout(function () {
                            window.location.href = "/"
                        }, 1500);
                    }

                    // 处理响应数据
                    console.log(999, response);
                    // 根据需要执行其他操作...

                } catch (error) {
                    console.error('Error submitting form:', error.response.data);
                    ElementPlus.ElMessage.error(error.response.data.message)
                    // 错误处理...
                }

            }

            // 在组件挂载后发送请求
            onMounted(async () => {
                if (!window.isUserLoggedIn) {
                    ElementPlus.ElMessage({
                        message: '未登入'
                    })
                    setTimeout(function () {
                        window.location.href = "/"
                    }, 1500);

                }
                console.log(999, 'onMounted')
                try {
                    const response = await axios.get('/wp-json/wp/v2/notice_categories?parent=2&orderby=slug');
                    console.log(888, 'onMounted', response.data)
                    product_category.value = response.data;

                    console.log(888, 'onMounted', product_category.value)
                } catch (error) {
                    console.error('Failed to fetch data:', error);
                    // 可以在此处理错误逻辑
                }
            });
            return {
                ElementPlus,
                clickEvent,
                disabled,
                fileList,
                dialogImageUrl,
                dialogVisible,
                headers,
                rules,
                handlePictureCardPreview,
                handleRemove,
                handleFileListSuccess,
                form,
                product_category,
                onSubmit,
                open2,
                message
            }
        }
    })

    app.component('Plus', ElementPlusIconsVue.Plus)
    app.component('Document', ElementPlusIconsVue.Document)
    app.use(ElementPlus)
    app.mount('#app')
</script>

<?php get_footer(); ?>