让DcatAdmin再放光芒系列-接入element-plus组件为我所用

前言

Element Plus 基于 Vue 3,面向设计师和开发者的组件库。设想,如果能把 Element Plus各种组件集成到dcat为我所用,那将为dcat增添新活力。
希望集成后,与dcat原来的使用方法保持不变。也不需要去折腾vue3,或打包前端代码

提前看效果

让DcatAdmin再放光芒系列-接入element-plus组件为我所用

// 表单组件使用
$form->elDatePicker('test10','el-date-picker10')->value(["2024-12-19 11:55:24","2024-12-21 11:55:24"]);

在线演示 提前观看效果

一键看效果
扫码登陆后打开:jikeadmin.saishiyun.net/admin/dcat...

开始实现 共分三步

  1. 创建组件模板

    模板公共文件

    存放路径 common/vue-manager.blade.php
<script>
class VueManager {
    static instances = new Map();

    static createApp(id, component, options = {}) {
        const container = document.getElementById(id);
        if (!container) return null;

        // 如果已存在实例,先卸载
        if (this.instances.has(id)) {
            this.instances.get(id).unmount();
            this.instances.delete(id);
        }

        // 创建新实例
        const app = Vue.createApp(component);

        // 使用 Element Plus
        app.use(ElementPlus, {
            locale: ElementPlusLocaleZhCn,
            ...options
        });

        // 挂载并保存实例
        app.mount(`#${id}`);
        this.instances.set(id, app);

        return app;
    }

    static destroyApp(id) {
        if (this.instances.has(id)) {
            this.instances.get(id).unmount();
            this.instances.delete(id);
        }
    }
}

window.VueManager = VueManager;
</script>

模板文件

存放路径:el-date-picker.blade.php

@php
    $vueDelimiters = ['@{{', '}}'];
@endphp
@once
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/element-plus/dist/index.css" />
<script src="//cdn.jsdelivr.net/npm/vue@3"></script>
<script src="//cdn.jsdelivr.net/npm/element-plus"></script>
<script src="//cdn.jsdelivr.net/npm/@element-plus/icons-vue"></script>
<script src="//cdn.jsdelivr.net/npm/element-plus/dist/locale/zh-cn.min.js"></script>
@endonce

@include('admin::common.vue-manager')

<style>
    /* 完全重写这个图标 */
    .el-input__suffix-inner .icon-arrow-down:before {
        content: "" !important;
        font-family: element-icons !important;
        display: inline-block !important;
    }
</style>

<div class="{{$viewClass['form-group']}}">
    <div class="{{$viewClass['label']}} control-label">
        <span>{!! $label !!}</span>
    </div>

    <div class="{{$viewClass['field']}}" id="{{ $vid }}">
        @include('admin::form.error')
        <div class="input-group">
            <el-date-picker
                    v-model="value"
                    :type="type"
                    :shortcuts="shortcuts"
                    :size="size"
                    :format="format"
                    :value-format="valueFormat"
                    :disabled-date="disabledDate"
                    :placeholder="placeholder"
                    :start-placeholder="startPlaceholder"
                    :end-placeholder="endPlaceholder"
                    :range-separator="rangeSeparator"
                    :disabled="disabled"
                    :clearable="clearable"
                    @change="handleChange"
            />
        </div>
        <input type="hidden" name="{{$name}}" :value="JSON.stringify(formValue)" />
        @include('admin::form.help-block')
    </div>
</div>
<script>
    Dcat.ready(function () {
        const App3 = {
            data() {
                return {
                    value: @json($value ?? null),
                    type: 'datetimerange',
                    size: 'default',
                    format: 'YYYY-MM-DD HH:mm:ss',
                    valueFormat: 'YYYY-MM-DD HH:mm:ss',
                    placeholder: '请选择日期时间',
                    startPlaceholder: '开始日期',
                    endPlaceholder: '结束日期',
                    rangeSeparator: '至',
                    disabled: false,
                    clearable: true,
                    shortcuts: [
                        {
                            text: '最近一周',
                            value: () => {
                                const end = new Date()
                                const start = new Date()
                                start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
                                return [start, end]
                            },
                        },
                        {
                            text: '最近一个月',
                            value: () => {
                                const end = new Date()
                                const start = new Date()
                                start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
                                return [start, end]
                            },
                        },
                        {
                            text: '最近三个月',
                            value: () => {
                                const end = new Date()
                                const start = new Date()
                                start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
                                return [start, end]
                            },
                        },
                    ],
                }
            },
            computed: {
                formValue() {
                    return this.value;
                }
            },
            methods: {
                handleChange(value) {
                    this.value = value;
                    this.updateFormValue();
                },
                updateFormValue() {
                    const input = document.querySelector('input[name="{{ $name }}"]');
                    if (input) {
                        input.value = JSON.stringify(this.formValue);
                        const event = new Event('change', { bubbles: true });
                        input.dispatchEvent(event);
                        $(input).trigger('change');
                    }
                },
                disabledDate(time) {
                    return false;
                },
            },
            mounted() {
                this.updateFormValue();
                console.log('Vue mounted, formValue:', this.formValue);
            },
        };

        const app3 = Vue.createApp(App3);
        app3.use(ElementPlus, {
            locale: ElementPlusLocaleZhCn,
        });
        app3.mount("#{{ $vid }}");
    });
</script>
  1. 创建表单组件字段
namespace Dcat\Admin\Form\Field;
use Dcat\Admin\Form\Field;
class ElDatePicker extends Field
{
    protected $view = 'admin::form.el-date-picker';

    /**
     * 获取元素ID
     *
     * @return string
     */
    public function getElementId()
    {
        return 'score-' . $this->getFormElementId();
    }

    /**
     * 处理输入值
     *
     * @param mixed $value
     * @return mixed
     */
    public function formatValue($value)
    {
        // 如果是字符串,尝试解析 JSON
        if (is_string($value)) {
            $value = json_decode($value, true);
        }

        return $value;
    }


    protected function formatAttributes()
    {
        /*$form = WidgetsForm::make();
        $form->data(['name'=> 123]);
        $form->text('name','名字');*/
        $this->addVariables([
            'vid' => $this->getElementId(),
            'value' => $this->formatValue($this->value) ?? $this->default ?? [],
            'forms' => '',
        ]);

        return parent::formatAttributes();
    }
} 
  1. 然后注册
    \Dcat\Admin\Form::extend('elDatePicker',  ElDatePicker::class);

dcat-admin 并未停止不前,plus版 持续更新 保持活力

dcat-plus admin (plus版)沿用 dcat-admn 最新代码,并让dcat-admin 保持活力。已支持到Laravel11,并新增多个组件。

本作品采用《CC 协议》,转载必须注明作者和本文链接
Dcat-Admin (plus版)是汇聚Filament,Laravel-admin , Dcat-admin 优点于一身的基于Laravel + Bootstrap 的极速开发框架
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 5

:+1: 支持

2个月前 评论

支持一下

2个月前 评论
Dcatplus-杨光 (楼主) 1个月前

cdn.jsdelivr.net 资源移到到本地, 要pending很久

1个月前 评论
Dcatplus-杨光 (楼主) 1个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
Dcat-plus Admin @ 速码邦
文章
30
粉丝
49
喜欢
166
收藏
143
排名:455
访问:2.0 万
私信
所有博文
社区赞助商