Skip to content

Tab 表单

后端

这里使用的是内容管理的文章管理用做案例

php
namespace Modules\Cms\Dynamics;


use CatchForm\Builder;
use CatchForm\Components\Rules\Control;
use CatchForm\Form;
use CatchForm\Table\Table;
use Modules\Cms\Enums\CategoryType;
use Modules\Cms\Enums\Visible;
use Modules\Cms\Models\Category as CategoryModel;

class Resource extends Builder
{

    protected function form(): mixed
    {
        // TODO: Implement form() method.
        return Form::make(function (Form $form){
            $form->text('name', '名称')->required();

            $form->radio('type', '类型')->options([
                ['value' => 1, 'label' => '轮播图'],
                ['value' => 2, 'label' => '友情链接'],
                ['value' => 3, 'label' => '广告'],
            ])->required()->defaultValue(1)
            ->asButton()
            ->whenEqual(2, function (Control $control){
               $control->required('url');
            })
            ->whenNotEqual(2, function (Control $control){
                $control->hide('content');
            })
            ->whenNotEqual(2, function (Control $control){
                $control->required('content');
            });

            $form->upload('content', '上传图片');

            $form->url('url', '链接');

            $form->textarea('description', '描述');

            $form->radio('is_visible', '可见性')->options([
                ['value' => 1, 'label' => '可见'],
                ['value' => 2, 'label' => '隐藏'],
            ])->required()->asButton()->defaultValue(1);

            $form->radio('is_visible', '打开方式')->options([
                ['value' => 1, 'label' => '本窗口'],
                ['value' => 2, 'label' => '新窗口'],
            ])->required()->asButton()->defaultValue(1);
        });
    }

    protected function table(): mixed
    {
        // TODO: Implement table() method.
        return Table::make('/cms/resource')->columns(function (Table $table){
            $table->selection();

            $table->id();

            $table->column('name', '名称');

            $table->column('content', '图片')->image();

            $table->column('url', '链接')->link(true, '链接');

            $table->column('type', '类型')->tags(['danger', 'info', 'success'])
            // filter 支持注入动态方法,当然也可以通过后端转换
            ->filter(<<<FUNC
    (value) => {
      return value === 1 ? '轮播图' : value === 2 ? '友情链接' : '广告'
    }
FUNC
);

            $table->operate();
        })->search(function (Table $table){
            $table->text('名称', 'name');
        });
    }
}

前端

列表页面

vue
<template>
  <div v-loading="loading" class="min-h-96">
    <catch-table v-bind="table" v-if="!loading" ref="tableRef">
      <template #operation>
        <router-link to="/cms/articles/create">
          <Add text="创建文章" />
        </router-link>
        <el-button-group class="ml-2">
          <el-button
            plain
            class="border-gray-200"
            @click="searchType(item.value)"
            v-for="item in [
              { label: '文章', value: 1 },
              { label: '单页', value: 2 }
            ]"
            :key="item.value">
            {{ item.label }}
          </el-button>
        </el-button-group>
      </template>
      <template #_operate="scope">
        <router-link :to="'/cms/articles/create/' + scope.row.id">
          <Update />
        </router-link>
      </template>
    </catch-table>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { useDynamic } from '@/composables/useDynamic'
const { table, form, loading } = useDynamic('cms/post/dynamic/r')
const tableRef = ref()
const searchType = (val: number) => {
  tableRef.value.doSearch({
    type: val
  })
}
</script>

表单页面

vue
<template>
  <div class="w-full px-5 pt-5 pr-4 bg-white dark:bg-regal-dark">
    <catch-form ref="formRef" :is-page="true" :config="{ rules: form.rules, options: form.options, api: table.api, primary: primary }" v-if="!loading" :afterSubmit="afterSubmit" />
  </div>
</template>
<script lang="ts" setup>
// @ts-nocheck
import http from '@/support/http'
import { onMounted, ref, beforeMount, watch } from 'vue'
import { useDynamic } from '@/composables/useDynamic'
import router from '@/router'

const formRef = ref()
const { table, form, loading } = useDynamic('cms/post/dynamic/r')
// 作为单页使用的时候
// 编辑的时候 primary 要从页面的 route 里面获取 ID,所以这里的 primary 需要使用 ref 响应式
const primary = ref(null)
primary.value = router.currentRoute.value.params.id

const afterSubmit = () => {
  router.push({ path: '/cms/articles/post' })
}
</script>
<style scoped>
:deep(.fc-form-footer) {
  @apply flex justify-center !important;
}
</style>