🔱: [client] sync upgrade with 21 commits [trident-sync]

perf: 优化antdv4 示例授权页面tree的样式
build: publish success
chore: 1
chore: 1
chore: 1
fix: getFileName支持item参数

https://github.com/fast-crud/fast-crud/issues/385
fix: fs-form独立使用支持插槽

https://github.com/fast-crud/fast-crud/issues/389
fix: 修复三级以上路由页面无法缓存的问题

https://github.com/fast-crud/fast-crud/issues/394
perf: form.wrapper.buttons支持compute动态计算
feat: 表单支持变更关闭前提醒保存,form.wrapper支持beforeClose事件
fix: 修复图片裁剪按钮上下和左右相反的bug

https://github.com/fast-crud/fast-crud/issues/402
perf: alioss getAuthorization接口支持后台返回key

https://github.com/fast-crud/fast-crud/issues/405
perf: alioss getAuthorization接口支持后台返回key

https://github.com/fast-crud/fast-crud/issues/405
perf: fs-dict-tree支持插槽

https://github.com/fast-crud/fast-crud/issues/407
perf: 单选、多选、select、tree-select、table-select 都提供selected-change事件,可以获取选中的dict选项
feat: table-select 支持查看模式

https://github.com/fast-crud/fast-crud/issues/413
perf: 优化fs-admin可以在手机上操作
chore: pnpm workspace问题优化
docs: 1
chore: antdv4 支持主题色选择
...
This commit is contained in:
GitHub Actions Bot
2024-06-15 18:32:36 +00:00
parent 9caa4cd1d4
commit ad360e81cb
173 changed files with 3386 additions and 1108 deletions
@@ -1,5 +1,15 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes, dict } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
EditReq,
UserPageQuery,
UserPageRes,
dict,
utils
} from "@fast-crud/fast-crud";
import { SearchOutlined } from "@ant-design/icons-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -78,7 +88,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
title: "复杂输入",
component: {
render(context: any) {
console.log("context scope", context);
utils.logger.info("context scope", context);
return (
<a-input-group compact>
<a-input placeholder={"render1 input"} style="width: 50%" v-model={[context.form.render, "value"]} />
@@ -44,7 +44,14 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
title: "省",
type: "dict-select",
search: {
show: true
show: true,
valueChange({ form, value, getComponentRef }: any) {
form.city = undefined; // 将“city”的值置空
form.county = undefined; // 将“county”的值置空
if (value) {
getComponentRef("city").reloadDict(); // 执行city的select组件的reloadDict()方法,触发“city”重新加载字典
}
}
},
dict: dict({
url: "/mock/linkage/province",
@@ -53,8 +60,8 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}),
form: {
valueChange({ form, value, getComponentRef }) {
form.city = undefined; // 将“city”的值置空
form.county = undefined; // 将“county”的值置空
form.city = ""; // 将“city”的值置空
form.county = ""; // 将“county”的值置空
if (value) {
getComponentRef("city").reloadDict(); // 执行city的select组件的reloadDict()方法,触发“city”重新加载字典
}
@@ -84,7 +91,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
// 注释同上
valueChange({ value, form, getComponentRef }: ScopeContext) {
if (value) {
form.county = undefined; // 将county的value置空
form.county = ""; // 将county的value置空
const countySelect = getComponentRef("county");
if (form && form.province && form.city) {
countySelect.reloadDict(); // 重新加载字典项
@@ -96,6 +96,13 @@ mock.push({
const a = tree.filter((item) => {
return item.id === province;
});
if (a == null || a.length === 0) {
return {
code: 0,
msg: "success",
data: []
};
}
const list = omitChildren(a[0].children);
return {
code: 0,
@@ -113,10 +120,24 @@ mock.push({
const a = tree.filter((item) => {
return item.id === province;
});
if (a == null || a.length === 0) {
return {
code: 0,
msg: "success",
data: []
};
}
const city = parseInt(req.params.city);
const b = a[0].children.filter((item) => {
return item.id === city;
});
if (b == null || b.length === 0) {
return {
code: 0,
msg: "success",
data: []
};
}
const list = omitChildren(b[0].children);
return {
@@ -51,11 +51,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
};
const addRequest = async ({ form }: AddReq) => {
const id = await api.AddObj(form);
const { id } = await api.AddObj(form);
//本地添加
form.id = id;
localDataRef.value.unshift(form);
return id;
return form;
};
const delRequest = async ({ row }: DelReq) => {
@@ -25,6 +25,7 @@ export default function ({ crudExpose, context: { asideTableRef } }: CreateCrudO
const onCurrentRowChange = (id: number) => {
currentRow.value = id;
asideTableRef.value.crudBinding.search.initialForm = { gradeId: id };
asideTableRef.value.setSearchFormData({ form: { gradeId: id } });
asideTableRef.value.doRefresh();
};
@@ -90,7 +91,8 @@ export default function ({ crudExpose, context: { asideTableRef } }: CreateCrudO
// 嵌套表格字段
rules: [{ required: true, message: "请选择用户" }],
component: {
name: SubTable,
//局部引用子表格,要用shallowRef包裹
name: shallowRef(SubTable),
vModel: "modelValue",
gradeId: compute(({ form }) => {
return form.id;
@@ -10,7 +10,7 @@
<script lang="ts">
import { defineComponent, onMounted, watch } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "SubTable",
@@ -33,7 +33,7 @@ export default defineComponent({
return props.modelValue;
},
(value) => {
console.log("modelValue changed", value);
utils.logger.info("modelValue changed", value);
}
);
return {
@@ -1,6 +1,7 @@
import * as api from "./api.js";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
import { computed } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding } = crudExpose;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -29,7 +30,10 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
},
toolbar: {
columnsFilter: {
mode: "default"
mode: "default",
container: {
width: "500px"
}
}
},
actionbar: {
@@ -78,7 +82,12 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "dict-radio",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
}),
column: {
show: computed(() => {
return true;
})
}
},
disabled: {
title: "列设置禁用",
@@ -1,6 +1,7 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { computed, ref } from "vue";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { computed, ref, shallowRef } from "vue";
import ShallowComponent from "/@/views/crud/basis/compute-more/shallow-component.vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -22,13 +23,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
//普通的ref引用,可以动态切换配置
const defValueRef = ref("我是动态的默认值");
const defValueComputed = computed(() => {
return defValueRef.value;
});
return {
output: {
defValueRef,
defValueComputed
defValueRef
},
crudOptions: {
request: {
@@ -67,11 +64,39 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "text",
search: { show: true, value: null },
form: {
// form.value不支持asyncCompute
// 假如你的默认值异步获取的,那么你自己必须保证先异步计算完成之后,才能打开对话框。
// 因为在打开对话框时,默认值就必须得设置好。
// form.value不支持asyncCompute/Compute, 因为上下文动态计算要先有上下文,上下文需要先有form数据
value: defValueRef
}
},
switch: {
title: "切换动态组件",
type: "dict-radio",
dict: dict({
data: [
{ value: "radio", label: "radio" },
{ value: "select", label: "select" },
{ value: "shallow", label: "shallowComponent" }
]
})
},
componentName: {
title: "动态组件",
type: "dict-select",
search: { show: true, value: null },
dict: dict({
data: [
{ value: "1", label: "开启" },
{ value: "2", label: "关闭" }
]
}),
form: {
component: {
value: "2",
name: compute(({ form }) => {
return form.switch === "select" ? "fs-dict-select" : form.switch === "radio" ? "fs-dict-radio" : ShallowComponent;
})
}
}
}
}
}
@@ -0,0 +1,14 @@
<template>
<component :is="ui.tag.name" type="red">value : {{ modelValue || value }}</component>
</template>
<script setup lang="ts">
import { useUi } from "@fast-crud/ui-interface";
type ScProps = {
modelValue?: string;
value?: string;
};
const props = defineProps<ScProps>();
const { ui } = useUi();
</script>
@@ -33,6 +33,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
editRequest,
delRequest
},
toolbar: {
compact: false
},
table: {
scroll: {
x: 1500
@@ -184,6 +187,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
search: { show: false },
type: "text",
column: {
order: 1000,
fixed: "right",
component: {
name: "a-switch",
@@ -48,7 +48,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
column: {
component: {
//引用自定义组件
name: shallowRef(VmodelCounter),
name: VmodelCounter,
color: "blue",
slots: {
//插槽示例
@@ -68,7 +68,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
//form表单
component: {
//引用自定义组件
name: shallowRef(VmodelCounter),
name: VmodelCounter,
vModel: "modelValue",
color: "red",
on: {
@@ -1,7 +1,17 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/FsCrudFirst";
export function GetList(query: any) {
/**
* 定义行数据模型
*/
export type FirstRow = {
id?: number;
name?: string;
type?: number;
};
export function GetList(query: FirstRow) {
return request({
url: apiPrefix + "/page",
method: "get",
@@ -9,7 +19,7 @@ export function GetList(query: any) {
});
}
export function AddObj(obj: any) {
export function AddObj(obj: FirstRow) {
return request({
url: apiPrefix + "/add",
method: "post",
@@ -17,7 +27,7 @@ export function AddObj(obj: any) {
});
}
export function UpdateObj(obj: any) {
export function UpdateObj(obj: FirstRow) {
return request({
url: apiPrefix + "/update",
method: "post",
@@ -1,31 +1,34 @@
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery } from "@fast-crud/fast-crud";
import * as api from "./api";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
import { FirstRow } from "./api";
/**
* 定义context参数类型
*/
export type FirstContext = {
test?: number;
};
export default function ({ crudExpose, context }: CreateCrudOptionsProps<FirstRow, FirstContext>): CreateCrudOptionsRet<FirstRow> {
context.test = 111;
return {
crudOptions: {
// 自定义crudOptions配置
request: {
pageRequest,
addRequest,
editRequest,
delRequest
pageRequest: async (query: UserPageQuery<FirstRow>) => {
return await api.GetList(query);
},
addRequest: async ({ form }: AddReq) => {
return await api.AddObj(form);
},
editRequest: async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await api.UpdateObj(form);
},
delRequest: async ({ row }: DelReq) => {
return await api.DelObj(row.id);
}
},
//两个字段
columns: {
@@ -1,5 +1,5 @@
<template>
<fs-page>
<fs-page class="page-first">
<template #header>
<div class="title">第一个crud</div>
<div class="more">
@@ -7,13 +7,17 @@
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
<a-tour v-model:current="current" :open="open" :steps="steps" @close="handleOpen(false)" />
</fs-page>
</template>
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { defineComponent, onMounted, ref } from "vue";
import { useFs, utils } from "@fast-crud/fast-crud";
import createCrudOptions, { FirstContext } from "./crud";
import { TourProps } from "ant-design-vue";
import { FirstRow } from "./api";
//此处为组件定义
export default defineComponent({
@@ -32,15 +36,67 @@ export default defineComponent({
// =======以上为fs的初始化代码=========
// =======你可以简写为下面这一行========
const { crudRef, crudBinding, crudExpose, context } = useFs({ createCrudOptions, context: {} });
const { crudRef, crudBinding, crudExpose, context } = useFs<FirstRow, FirstContext>({ createCrudOptions, context: {} });
utils.logger.info("test", context.test);
function useTour() {
const open = ref<boolean>(false);
const current = ref(0);
//帮助向导
const steps: TourProps["steps"] = [
{
title: "查询",
description: "查询数据.",
target: () => {
return document.querySelector(".page-first .fs-search-btn-search") as HTMLElement;
}
},
{
title: "重置",
description: "重置查询条件.",
target: () => {
return document.querySelector(".page-first .fs-search-btn-reset") as HTMLElement;
}
},
{
title: "添加",
description: "打开添加对话框",
target: () => {
return document.querySelector(".page-first .fs-actionbar-btn-add") as HTMLElement;
}
},
{
title: "刷新列表",
description: "刷新列表",
target: () => {
return document.querySelector(".page-first .fs-toolbar-btn-refresh") as HTMLElement;
}
}
];
const handleOpen = (val: boolean): void => {
open.value = val;
};
return {
open,
current,
steps,
handleOpen
};
}
const tour = useTour();
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
tour.handleOpen(true);
});
return {
crudBinding,
crudRef
crudRef,
...tour
};
}
});
@@ -18,10 +18,10 @@ import _ from "lodash-es";
//此处为crudOptions配置
const createCrudOptions = function ({}: CreateCrudOptionsProps): CreateCrudOptionsRet {
//本地模拟后台crud接口方法 ----开始
const records = reactive([{ id: 1, name: "Hello World", type: 1 }]);
const records = [{ id: 1, name: "Hello World", type: 1 }];
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return {
records,
records: _.cloneDeep(records),
offset: 0, //后续transformRes会计算为currentPage
limit: 20, //后续transformRes会计算为pageSize
total: records.length
@@ -100,6 +100,26 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
},
text: {
title: "text",
type: "text",
search: { show: true }
},
text2: {
title: "text2",
type: "text",
search: { show: true }
},
text3: {
title: "text3",
type: "text",
search: { show: true }
},
text4: {
title: "text4",
type: "text",
search: { show: true }
}
}
}
@@ -6,7 +6,11 @@
<a target="_blank" href="http://fast-crud.docmirror.cn/guide/advance/layout.html">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
<a-button type="danger">actionbar-right插槽</a-button>
</template>
</fs-crud>
</fs-page>
</template>
@@ -0,0 +1,50 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/BasisPlugin";
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
data: query
});
}
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
}
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
}
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
}
export function GetObj(id: any) {
return request({
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
export function BatchDelete(ids: any) {
return request({
url: apiPrefix + "/batchDelete",
method: "post",
data: { ids }
});
}
@@ -0,0 +1,72 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
import { ref } from "vue";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
const selectedRowKeys: Ref<any[]> = ref([]);
context.selectedRowKeys = selectedRowKeys;
return {
crudOptions: {
settings: {
plugins: {
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
rowSelection: {
enabled: true,
order: -2,
before: true,
// handle: (pluginProps,useCrudProps)=>CrudOptions,
props: {
multiple: true,
crossPage: true,
selectedRowKeys,
onSelectedChanged(selected) {
utils.logger.info("已选择变化:", selected);
}
}
}
}
},
request: {
pageRequest,
addRequest,
editRequest,
delRequest
},
columns: {
id: {
title: "ID",
type: "number",
column: {
width: 50
},
form: {
show: false
}
},
text: {
title: "Text",
type: "text",
search: { show: true }
}
}
}
};
}
@@ -0,0 +1,63 @@
<template>
<fs-page>
<template #header>
<div class="title">
CrudOptionsPlugin
<span class="sub">用于合并CrudOptions做一些可配置化的公共参数此处演示使用rowSelectionPlugin生成行选择配置,支持跨页选择</span>
</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/settings.html#plugins">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #pagination-left>
<a-tooltip title="批量删除">
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
</a-tooltip>
</template>
</fs-crud>
</fs-page>
</template>
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import { message, Modal } from "ant-design-vue";
import { BatchDelete } from "./api";
export default defineComponent({
name: "BasisPlugin",
setup() {
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
const selectedRowKeys = context.selectedRowKeys;
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
});
const handleBatchDelete = () => {
if (selectedRowKeys.value?.length > 0) {
Modal.confirm({
title: "确认",
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
async onOk() {
await BatchDelete(selectedRowKeys.value);
message.info("删除成功");
crudExpose.doRefresh();
selectedRowKeys.value = [];
}
});
} else {
message.error("请先勾选记录");
}
};
return {
crudBinding,
crudRef,
handleBatchDelete
};
}
});
</script>
@@ -0,0 +1,22 @@
import mockUtil from "/src/mock/base";
const options: any = {
name: "BasisPlugin",
idGenerator: 0
};
const list = [
{
text: "张三",
radio: "1"
},
{
text: "李四",
radio: "2"
},
{
text: "王五",
radio: "0"
}
];
options.list = list;
const mock = mockUtil.buildMock(options);
export default mock;
@@ -1,6 +1,6 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/BasisReset";
const apiPrefix = "/mock/BasisValueChange";
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
@@ -15,14 +15,13 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { CrudOptions, DynamicType, useFs } from "@fast-crud/fast-crud";
import { CrudOptions, DynamicType, useFs, UseFsProps } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud.js";
import _ from "lodash-es";
export default defineComponent({
name: "BasisReset",
setup() {
const { crudBinding, crudRef, crudExpose, crudOptions, resetCrudOptions, appendBindingOptions } = useFs({ createCrudOptions, context: {} });
const { crudBinding, crudRef, crudExpose, context, crudOptions, resetCrudOptions, appendBindingOptions } = useFs({ createCrudOptions, context: { text: 111 } });
setTimeout(() => {
//合并新的crudOptions
@@ -1,7 +1,7 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options: any = {
name: "BasisReset",
name: "BasisValueChange",
idGenerator: 0
};
const list = [
@@ -0,0 +1,54 @@
//@ts-ignore
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/FsCrudFirst";
/**
* 定义行数据模型
*/
export type TsTestRow = {
id?: number;
name?: string;
type?: number;
compute?: string;
};
export function GetList(query: TsTestRow) {
return request({
url: apiPrefix + "/page",
method: "get",
data: query
});
}
export function AddObj(obj: TsTestRow) {
return request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
}
export function UpdateObj(obj: TsTestRow) {
return request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
}
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
}
export function GetObj(id: any) {
return request({
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
@@ -0,0 +1,79 @@
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery } from "@fast-crud/fast-crud";
import * as api from "./api";
import { TsTestRow } from "./api";
/**
* 定义context参数类型
*/
export type TsTestContext = {
test?: number;
};
export default function ({ crudExpose, context }: CreateCrudOptionsProps<TsTestRow, TsTestContext>): CreateCrudOptionsRet<TsTestRow> {
context.test = 111;
return {
crudOptions: {
// 自定义crudOptions配置
columns: {
name: {
title: "姓名",
type: "text",
search: { show: true },
column: {
resizable: true,
width: 200
}
},
type: {
title: "类型",
type: "dict-select",
dict: dict({
data: [
{ value: 1, label: "开始", color: "green" },
{ value: 0, label: "停止", color: "red" }
]
}),
valueResolve: ({ form }) => {
console.log("valueResolve", form.type);
},
valueBuilder: ({ row }) => {
console.log("valueBuilder", row.type);
}
},
compute: {
title: "compute",
type: "text",
form: {
component: {
show: compute(({ form }) => {
//自动带form ts提示
return form.type === 1;
}),
disabled: compute<boolean, TsTestRow>(({ form }) => {
//disabled属性 不在component配置的定义中,所有不带row、form的ts提示, 需要手动指定类型
return form.type === 1;
})
}
}
}
},
//两个字段
request: {
pageRequest: async (query: UserPageQuery) => {
return await api.GetList(query);
},
addRequest: async ({ form }: AddReq) => {
return await api.AddObj(form);
},
editRequest: async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await api.UpdateObj(form);
},
delRequest: async ({ row }: DelReq) => {
return await api.DelObj(row.id);
}
}
}
};
}
@@ -0,0 +1,47 @@
<template>
<fs-page class="page-first">
<template #header>
<div class="title">Ts定义测试</div>
<div class="more"></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import { useFs, utils } from "@fast-crud/fast-crud";
import createCrudOptions, { TsTestContext } from "./crud";
import { TsTestRow } from "./api";
//此处为组件定义
export default defineComponent({
name: "FsCrudTsTest",
setup() {
// // crud组件的ref
// const crudRef: Ref = ref();
// // crud 配置的ref
// const crudBinding: Ref<CrudBinding> = ref();
// // 暴露的方法
// const { crudExpose } = useExpose({ crudRef, crudBinding });
// // 你的crud配置
// const { crudOptions, customExport } = createCrudOptions({ crudExpose, customValue });
// // 初始化crud配置
// const { resetCrudOptions, appendCrudBinding } = useCrud({ crudExpose, crudOptions });
// =======以上为fs的初始化代码=========
// =======你可以简写为下面这一行========
const { crudRef, crudBinding, crudExpose, context } = useFs<TsTestRow, TsTestContext>({ createCrudOptions, context: {} });
utils.logger.info("test", context.test);
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
});
return {
crudBinding,
crudRef
};
}
});
</script>
@@ -0,0 +1,22 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options: any = {
name: "FsCrudFirst",
idGenerator: 0
};
const list = [
{
name: "张三",
type: 1
},
{
name: "李四",
type: 0
},
{
name: "王五"
}
];
options.list = list;
const mock = mockUtil.buildMock(options);
export default mock;
@@ -1,6 +1,17 @@
import * as api from "./api";
import { message } from "ant-design-vue";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, ValueChangeContext } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils,
ValueChangeContext
} from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -55,12 +66,12 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
vModel: "checked"
},
valueChange(context: ValueChangeContext) {
console.log("column value changed:", context);
utils.logger.info("column value changed:", context);
}
},
form: {
valueChange({ value, key, form }: ValueChangeContext) {
console.log("valueChanged,", key, value, form);
utils.logger.info("valueChanged,", key, value, form);
message.info(`valueChanged:${key}=${value}`);
}
}
@@ -70,7 +81,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "text",
form: {
valueChange({ value, key, form }: ValueChangeContext) {
console.log("valueChanged,", key, value, form);
utils.logger.info("valueChanged,", key, value, form);
message.info(`valueChanged:${key}=${value}`);
}
}
@@ -84,7 +95,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
form: {
valueChange: {
handle({ value, key, form, immediate }: ValueChangeContext) {
console.log("valueChange,", key, value, "isImmediate=", immediate);
utils.logger.info("valueChange,", key, value, "isImmediate=", immediate);
message.info(`valueChanged:${key}=${value},isImmediate=${immediate}`);
},
immediate: true
@@ -50,6 +50,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "button",
column: {
component: {
icon: "ion:search",
show: compute(({ value }) => {
//当value为null时,不显示
return value != null;
@@ -1,5 +1,6 @@
<template>
<fs-page>
<div class="title">按钮</div>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
@@ -1,6 +1,6 @@
import * as api from "./api";
import { requestForMock } from "/src/api/service";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils, useUi } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -19,6 +19,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
const { ui } = useUi();
return {
crudOptions: {
request: {
@@ -52,7 +53,18 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
dict: dict({
isTree: true,
url: "/mock/dicts/cascaderData?single"
})
}),
form: {
component: {
on: {
selectedChange({ $event }) {
utils.logger.info("onSelectedChange", $event);
const labels = $event.map((item) => item.label);
ui.message.info(`selected-change:${JSON.stringify(labels)}`);
}
}
}
}
},
lazyLoad: {
title: "懒加载",
@@ -65,9 +77,6 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
prototype: true,
getNodesByValues(values: any) {
//给cell展示组件调用,根据value值获取节点,每行都会请求一次
if (values == null) {
return [];
}
return requestForMock({
url: "/mock/tree/GetNodesByValues",
params: { values }
@@ -90,7 +99,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}
],
loadData: async (selectedOptions: any) => {
console.log("lazyLoad", selectedOptions);
utils.logger.info("lazyLoad", selectedOptions);
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils, useUi } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -18,6 +18,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
const { ui } = useUi();
return {
crudOptions: {
request: {
@@ -44,7 +45,20 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "dict-checkbox",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
}),
form: {
component: {
on: {
selectedChange({ form, $event }) {
// $event就是原始的事件值,也就是选中的 option对象
utils.logger.info("onSelectedChange", form, $event);
ui.message.info(`你选择了${JSON.stringify($event)}`);
// 你还可以将选中的label值赋值给表单里其他字段
// context.form.xxxLabel = context.$event.label
}
}
}
}
}
}
}
@@ -2,7 +2,6 @@ import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, ScopeContext, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
import dayjs from "dayjs";
console.log("utils", utils);
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -33,6 +32,11 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
scroll: { x: 3000 }
},
rowHandle: { fixed: "right" },
search: {
initialForm: {
// datetimerange: [dayjs().subtract(1, "month").startOf("day"), dayjs().endOf("day")]
}
},
columns: {
id: {
title: "ID",
@@ -54,7 +58,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
component: {}
},
valueBuilder({ value, row, key }) {
console.log("value builder:", key, value, row);
utils.logger.info("value builder:", key, value, row);
if (value != null) {
row[key] = dayjs(value);
}
@@ -76,7 +80,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}
},
valueBuilder({ value, row, key }) {
console.log("value builder:", key, value, row);
utils.logger.info("value builder:", key, value, row);
if (value != null) {
row[key] = dayjs(value);
}
@@ -121,7 +125,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
valueFormat: "YYYY-MM-DD HH:mm:ss", //输入值的格式
on: {
onChange(context: ScopeContext) {
console.log("change", context);
utils.logger.info("change", context);
}
}
}
@@ -187,7 +191,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
daterange: {
title: "日期范围",
type: "daterange",
search: { show: true, width: 300 },
search: { show: true, width: 300, col: { span: 6 } },
valueBuilder({ row, key }) {
if (!utils.strings.hasEmpty(row.daterangeStart, row.daterangeEnd)) {
row[key] = [dayjs(row.daterangeStart), dayjs(row.daterangeEnd)];
@@ -197,7 +201,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
datetimerange: {
title: "日期时间范围",
type: "datetimerange",
search: { show: true, width: 300 },
search: { show: true, width: 300, col: { span: 8 } },
valueBuilder({ row, key }) {
if (!utils.strings.hasEmpty(row.datetimerangeStart, row.datetimerangeEnd)) {
row[key] = [dayjs(row.datetimerangeStart), dayjs(row.datetimerangeEnd)];
@@ -104,7 +104,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
toolbarConfig: {},
editorConfig: {},
onOnChange(value: any) {
console.log("value changed", value);
utils.logger.info("value changed", value);
},
uploader: {
type: "form",
@@ -26,6 +26,15 @@
<input type="file" @change="fileUploaderChange" />
<a v-if="signedUrl" :href="signedUrl" target="_blank">下载</a>
</a-form-item>
<a-form-item label="表格选择">
<fs-table-select v-model="form.tableSelect" v-bind="tableSelectBinding" />
<fs-label label="切换value">
<a-radio-group v-model:value="form.tableSelect">
<a-radio :value="1">王小虎</a-radio>
<a-radio :value="2">id为2的记录</a-radio>
</a-radio-group>
</fs-label>
</a-form-item>
<a-form-item>
<a-button @click="submit">提交</a-button>
</a-form-item>
@@ -37,9 +46,11 @@
<script lang="ts" setup>
import { reactive, ref } from "vue";
import { message } from "ant-design-vue";
import { dict, useUi } from "@fast-crud/fast-crud";
import {dict, useUi, utils} from "@fast-crud/fast-crud";
import dayjs from "dayjs";
import { FsUploaderS3, loadUploader, useUploader } from "@fast-crud/fast-extends";
import createCrudOptionsText from "/@/views/crud/component/text/crud";
import * as textTableApi from "/@/views/crud/component/text/api";
defineOptions({
name: "ComponentIndependent"
@@ -49,7 +60,8 @@ const form = reactive({
avatar: undefined,
copyable: "可复制的内容",
select: 1,
humanizeTime: dayjs(new Date().getTime() - 100000)
humanizeTime: dayjs(new Date().getTime() - 100000),
tableSelect: null
});
const uploader = ref({
@@ -66,7 +78,7 @@ const cropperUploader = ref({
viewMode: 1
},
async onReady(context: any) {
console.log("onReady", context);
utils.logger.info("onReady", context);
context.zoom(-0.1);
context.zoom(-0.1);
context.zoom(-0.1);
@@ -81,6 +93,26 @@ const dictRef = dict({
]
});
const tableSelectBinding = ref({
dict: dict({
value: "id",
label: "name",
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
}),
crossPage: true,
valuesFormat: {
labelFormatter: (item: any) => {
return `${item.id}.${item.name}`;
}
},
select: {
placeholder: "点击选择"
},
createCrudOptions: createCrudOptionsText
});
const signedUrl = ref();
async function fileUploaderChange(event: any) {
const file = event.target.files[0];
@@ -90,7 +122,7 @@ async function fileUploaderChange(event: any) {
file,
fileName: file.name,
onProgress(progress: any) {
console.log("progress:" + progress.percent + "%");
utils.logger.info("progress:" + progress.percent + "%");
}
});
const { ui } = useUi();
@@ -104,6 +136,6 @@ async function fileUploaderChange(event: any) {
function submit() {
message.info("submit:" + JSON.stringify(form));
console.log("submit:", form);
utils.logger.info("submit:", form);
}
</script>
@@ -0,0 +1,50 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/ComponentPhone";
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
data: query
});
}
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
}
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
}
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
}
export function GetObj(id: any) {
return request({
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
export function GetByIds(ids: any) {
return request({
url: apiPrefix + "/byIds",
method: "post",
data: { ids }
});
}
@@ -0,0 +1,92 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, ScopeContext, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { SearchOutlined } from "@ant-design/icons-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
crudOptions: {
request: {
pageRequest,
addRequest,
editRequest,
delRequest
},
columns: {
id: {
title: "ID",
type: "number",
form: { show: false }
},
phone: {
title: "手机号码",
type: "phone",
search: { show: true }
},
phoneNumber: {
title: "区号手机号分开",
type: "phone",
valueBuilder({ row, key, value }) {
row[key] = {
callingCode: row.code || undefined,
phoneNumber: value || ""
};
},
valueResolve({ form, key, value }) {
if (value) {
form.code = value.callingCode;
form.phoneNumber = value.phoneNumber;
}
}
},
only: {
title: "仅某些国家",
type: "phone",
form: {
component: {
onlyCountries: ["CN", "US"]
},
helper: "仅CN,US"
}
},
ignore: {
title: "排除某些国家",
type: "phone",
form: {
component: {
ignoredCountries: ["jp"]
},
helper: "排除JP"
}
},
priority: {
title: "优先某些国家",
type: "phone",
form: {
component: {
priorityCountries: ["CN", "US"],
ignoredCountries: ["jp"]
},
helper: "优先CNUS,排除JP"
}
}
}
}
};
}
@@ -0,0 +1,37 @@
<template>
<fs-page>
<template #header>
<div class="title">
国际手机号输入
<span class="sub"> </span>
</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/api/components/extends/input/components/fs-phone-input">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
export default defineComponent({
name: "ComponentPhone",
setup() {
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
});
return {
crudBinding,
crudRef
};
}
});
</script>
@@ -0,0 +1,18 @@
import mockUtil from "/src/mock/base";
const options: any = {
name: "ComponentPhone",
idGenerator: 0
};
const list = [
{
phone: {
callingCode: "86",
phoneNumber: "12345678"
},
code: "86",
phoneNumber: "12424354"
}
];
options.list = list;
const mock = mockUtil.buildMock(options);
export default mock;
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi, utils } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -17,7 +17,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
const { ui } = useUi();
return {
crudOptions: {
request: {
@@ -44,7 +44,23 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "dict-radio",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
}),
form: {
valueChange({ value }) {
utils.logger.info("change", value);
},
component: {
on: {
selectedChange({ form, $event }) {
// $event就是原始的事件值,也就是选中的 option对象
utils.logger.info("onSelectedChange", form, $event);
ui.message.info(`你选择了${JSON.stringify($event)}`);
// 你还可以将选中的label值赋值给表单里其他字段
// context.form.xxxLabel = context.$event.label
}
}
}
}
},
button: {
title: "按钮样式",
@@ -1,6 +1,6 @@
import * as api from "./api";
import { requestForMock } from "/src/api/service";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, DictOnReadyContext, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, DictOnReadyContext, EditReq, UserPageQuery, UserPageRes, useUi, utils } from "@fast-crud/fast-crud";
import { ref } from "vue";
import _ from "lodash-es";
function useSearchRemote() {
@@ -11,7 +11,7 @@ function useSearchRemote() {
fetching: ref(false)
};
const fetchUser = _.debounce((value) => {
console.log("fetching user", value);
utils.logger.info("fetching user", value);
lastFetchId += 1;
const fetchId = lastFetchId;
@@ -76,6 +76,8 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
//dictRef.toMap();
}
const { ui } = useUi();
const { fetchUser, searchState } = useSearchRemote();
return {
dynamicUpdateDictOptions,
@@ -117,7 +119,24 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
statusLocal: {
title: "单选本地",
type: "dict-select",
dict: dictRef
dict: dictRef,
form: {
component: {
onChange(args: any) {
utils.logger.info("onChange", args);
},
on: {
selectedChange({ form, $event }) {
// $event就是原始的事件值,也就是选中的 option对象
utils.logger.info("onSelectedChange", form, $event);
ui.message.info(`你选择了${JSON.stringify($event)}`);
// 你还可以将选中的label值赋值给表单里其他字段
// context.form.xxxLabel = context.$event.label
}
}
},
helper: "selected-change事件可以获取选中的option对象"
}
},
statusRemote: {
title: "单选远程",
@@ -131,11 +150,6 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}),
form: {
rules: [{ required: true, message: "请选择一个选项" }]
},
column: {
component: {
type: "text"
}
}
},
filter: {
@@ -191,7 +205,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
dict: dict({
getData({ dict }) {
// 覆盖全局获取字典请求配置
console.log(`我是从自定义的getData方法中加载的数据字典`, dict);
utils.logger.info(`我是从自定义的getData方法中加载的数据字典`, dict);
return requestForMock({
url: "/mock/dicts/OpenStatusEnum?cache",
method: "get"
@@ -221,7 +235,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
// 此处dict配置会覆盖上面dict的属性
prototype: true, // form表单的dict设置为原型复制,每次初始化时都会重新loadDict
onReady({ dict }: DictOnReadyContext) {
console.log("字典请求ready", dict);
utils.logger.info("字典请求ready", dict);
dict.data[0].disabled = true; // 禁用某个选项, 还可以自己修改选项
}
}
@@ -242,7 +256,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
component: {
//监听 dict-change事件
onDictChange({ dict, form, key }: any) {
console.log("dict data changed", dict, key);
utils.logger.info("dict data changed", dict, key);
if (dict.data != null && form.firstDefault == null) {
form.firstDefault = dict.data[0].value;
}
@@ -1,5 +1,16 @@
import * as api from "./api";
import { dict, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery, UserPageRes, EditReq, DelReq, AddReq } from "@fast-crud/fast-crud";
import {
dict,
compute,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
UserPageQuery,
UserPageRes,
EditReq,
DelReq,
AddReq,
utils
} from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -98,7 +109,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
name: "fs-dict-switch",
vModel: "checked",
onChange: (value: any) => {
console.log("onChange", value);
utils.logger.info("onChange", value);
}
// onChange: compute((context) => {
// //动态onChange方法测试
@@ -132,7 +143,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
},
form: {
show: compute((context) => {
console.log("context", context);
utils.logger.info("context", context);
//根据cellSwitch字段显隐
return context.form.cellSwitch === true;
})
@@ -1,7 +1,8 @@
import * as api from "./api";
import * as textTableApi from "../text/api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi } from "@fast-crud/fast-crud";
import createCrudOptionsText from "../text/crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -20,6 +21,17 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
return await api.AddObj(form);
};
const crudOptionsOverride = {
table: {
scroll: {
x: 2000
}
},
rowHandle: {
fixed: "right"
}
};
const { ui } = useUi();
return {
crudOptions: {
request: {
@@ -40,6 +52,16 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
show: false
}
},
dynamicShow: {
title: "动态显隐",
type: "dict-switch",
dict: dict({
data: [
{ value: true, label: "显示" },
{ value: false, label: "隐藏" }
]
})
},
single: {
title: "单选",
search: { show: true },
@@ -47,19 +69,31 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
dict: dict({
value: "id",
label: "name",
//重要,根据value懒加载数据
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
}),
form: {
show: compute(({ form }) => {
return form.dynamicShow;
}),
component: {
crossPage: true,
valuesFormat: {
labelFormatter: (item: any) => {
return `${item.id}.${item.name}`;
}
},
select: {
placeholder: "点击选择"
},
createCrudOptions: createCrudOptionsText,
crudOptionsOverride: {
table: {
scroll: {
x: 2000
}
crudOptionsOverride,
on: {
selectedChange({ $event }) {
console.log("selectedChange", $event);
ui.message.info(`你选择了${JSON.stringify($event)}`);
}
}
}
@@ -72,6 +106,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
dict: dict({
value: "id",
label: "name",
//重要,根据value懒加载数据
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
@@ -80,15 +115,126 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
component: {
crossPage: true,
multiple: true,
valuesFormat: {
labelFormatter: (item: any) => {
return `${item.id}.${item.name}`;
}
},
select: {
placeholder: "点击选择"
},
createCrudOptions: createCrudOptionsText,
crudOptionsOverride: {
table: {
scroll: {
x: 2000
crudOptionsOverride: crudOptionsOverride
}
},
column: {
component: {
labelFormatter: (item: any) => {
return `${item.id}.${item.name}`;
}
}
}
},
valueType: {
title: "object类型",
search: { show: true },
type: "table-select",
dict: dict({
value: "id",
label: "name",
//重要,根据value懒加载数据
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
}),
column: {
component: {
valueType: "object"
}
},
form: {
helper: "这里提交的值是整个对象",
component: {
valueType: "object",
crossPage: true,
valuesFormat: {
labelFormatter: (item: any) => {
return `${item.id}.${item.name}`;
}
},
select: {
placeholder: "点击选择"
},
createCrudOptions: createCrudOptionsText,
crudOptionsOverride
}
}
},
//值是object类型
valueTypeMulti: {
title: "object类型多选",
search: { show: true },
type: "table-select",
dict: dict({
value: "id",
label: "name",
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
}),
column: {
component: {
valueType: "object"
}
},
form: {
helper: "这里提交的值是对象数组",
component: {
valueType: "object",
crossPage: true,
multiple: true,
valuesFormat: {
labelFormatter: (item: any) => {
return `${item.id}.${item.name}`;
}
},
select: {
placeholder: "点击选择"
},
createCrudOptions: createCrudOptionsText,
crudOptionsOverride
}
}
},
viewMode: {
title: "查看模式",
dict: dict({
value: "id",
label: "name"
}),
column: {
component: {
name: "fs-table-select",
//设置为查看模式
viewMode: true,
createCrudOptions: createCrudOptionsText,
crudOptionsOverride,
slots: {
default({ scope, value }) {
async function open() {
//打开时传入默认查询参数
const crudOptions = {
search: {
initialForm: {
classId: value
}
}
};
const { crudExpose } = await scope.open({ crudOptions });
// 这里还能通过crudExpose等返回值操作表格
}
},
rowHandle: {
fixed: "right"
return <a-button onClick={open}>:{value}</a-button>;
}
}
}
@@ -1,13 +1,33 @@
<template>
<fs-page>
<template #header>
<div class="title">table-select</div>
<div class="more">
<fs-label label="直接设置值">
<fs-table-select v-model="value" :dict="singleDictRef" :create-crud-options="createCrudOptionsText" />
<a-button @click="setValue"> 设置值 </a-button>
</fs-label>
<fs-label label="自定义插槽">
{{ value }}
<fs-table-select v-model="value" :dict="singleDictRef" :create-crud-options="createCrudOptionsText">
<template #default="scope">
<fs-button @click="scope.open()"> 选择 </fs-button>
</template>
</fs-table-select>
</fs-label>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script lang="ts">
import createCrudOptionsText from "../text/crud";
import { defineComponent, onMounted, ref } from "vue";
import createCrudOptions from "./crud.js";
import { useFs } from "@fast-crud/fast-crud";
import { dict, useFs } from "@fast-crud/fast-crud";
import * as textTableApi from "/@/views/crud/component/text/api";
export default defineComponent({
name: "ComponentTableSelect",
@@ -20,10 +40,25 @@ export default defineComponent({
});
const value = ref(null);
const singleDictRef = dict({
value: "id",
label: "name",
//重要,根据value懒加载数据
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
});
function setValue() {
value.value = 1;
}
return {
crudBinding,
crudRef,
value
value,
singleDictRef,
createCrudOptionsText,
setValue
};
}
});
@@ -6,11 +6,15 @@ const options: any = {
const list = [
{
single: 1,
multi: [1, 2]
multi: [1, 2],
valueType: { id: 1, name: "王小虎" },
viewMode: 1
},
{
single: 3,
multi: [1, 2, 3]
multi: [1, 2, 3],
dynamicShow: false,
viewMode: 2
},
{
single: 2
@@ -40,6 +40,7 @@ export function GetObj(id: any) {
params: { id }
});
}
export function GetByIds(ids: any) {
return request({
url: apiPrefix + "/byIds",
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, ScopeContext, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, ScopeContext, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
import { SearchOutlined } from "@ant-design/icons-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
@@ -29,6 +29,11 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
delRequest
},
columns: {
id: {
title: "ID",
type: "number",
form: { show: false }
},
name: {
title: "姓名",
type: "text", //虽然不写也能正确显示组件,但不建议省略它
@@ -37,8 +42,19 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
component: {
maxlength: 20
}
},
column: {
formatter(scope) {
utils.logger.info("formatter scope", scope);
return scope.value;
}
}
},
classId: {
title: "班级id",
type: "number", //虽然不写也能正确显示组件,但不建议省略它
search: { show: true }
},
trim: {
title: "trim空格",
type: "text", //虽然不写也能正确显示组件,但不建议省略它
@@ -150,7 +166,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
title: "复杂输入",
component: {
render(context: ScopeContext) {
console.log("context scope", context);
utils.logger.info("context scope", context);
return (
<a-input-group compact>
<a-input placeholder={"render1 input"} style="width: 50%" v-model={[context.form.render, "value"]} />
@@ -17,21 +17,24 @@ const list = [
address: "123123",
zip: "518000",
intro: "王小虎是element-plus的table示例出现的名字",
copy: "测试文本"
copy: "测试文本",
classId: 1
},
{
name: "张三",
date: "2016-05-04",
status: "1",
province: "2",
copy: "测试文本"
copy: "测试文本",
classId: 2
},
{
name: "李四",
date: 2232433534511,
status: "1",
province: "0",
copy: "测试文本"
copy: "测试文本",
classId: 3
},
{
name: "王五",
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi, utils } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -18,6 +18,26 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
return await api.AddObj(form);
};
const lazyloadDictRef = dict({
data: [
{
id: "0",
label: "Root",
value: "0"
}
]
});
const genTreeNode = (parentId: number, isLeaf = false) => {
const random = Math.random().toString(36).substring(2, 6);
return {
id: random,
pId: parentId,
value: random,
label: isLeaf ? "Tree Node" : "Expand to load",
isLeaf
};
};
const { ui } = useUi();
return {
crudOptions: {
request: {
@@ -45,7 +65,30 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
dict: dict({
isTree: true,
url: "/mock/dicts/cascaderData?single"
})
}),
form: {
valueChange({ getComponentRef }) {
const compRef = getComponentRef("tree");
console.log("tree ref:", compRef, compRef.$refs.treeRef);
},
component: {
on: {
selectedChange({ form, $event }) {
// $event就是原始的事件值,也就是选中的 option对象
utils.logger.info("onSelectedChange", form, $event);
ui.message.info(`你选择了${JSON.stringify($event.label)}`);
// 你还可以将选中的label值赋值给表单里其他字段
// context.form.xxxLabel = context.$event.label
}
},
slots: {
title({ scope }) {
//自定义选项text
return `${scope.label}(${scope.value})`;
}
}
}
}
},
multiple: {
title: "多选",
@@ -57,7 +100,27 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}),
form: {
component: {
"tree-checkable": true
"tree-checkable": true,
on: {
selectedChange({ form, $event }) {
// $event就是原始的事件值,也就是选中的 option对象
utils.logger.info("onSelectedChange", form, $event);
const labels = $event.map((item) => item.label);
ui.message.info(`你选择了${JSON.stringify(labels)}`);
// 你还可以将选中的label值赋值给表单里其他字段
// context.form.xxxLabel = context.$event.label
}
}
},
rules: [{ required: true, message: "请选择" }],
on: {
selectedChange({ form, $event }) {
// $event就是原始的事件值,也就是选中的 option对象
utils.logger.info("onSelectedChange", form, $event);
ui.message.info(`你选择了${JSON.stringify($event)}`);
// 你还可以将选中的label值赋值给表单里其他字段
// context.form.xxxLabel = context.$event.label
}
}
}
},
@@ -70,10 +133,25 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
url: "/mock/dicts/littlePca",
value: "code",
label: "name"
}),
})
},
lazy: {
title: "懒加载",
search: { show: false },
type: "dict-tree",
dict: lazyloadDictRef,
form: {
component: {
fieldNames: { label: "name", key: "code", value: "code" }
"tree-data-simple-mode": true,
loadData: (treeNode: any) => {
return new Promise((resolve: (value?: unknown) => void) => {
const { id } = treeNode.dataRef;
setTimeout(() => {
lazyloadDictRef.data = lazyloadDictRef.data.concat([genTreeNode(id, false), genTreeNode(id, true)]);
resolve();
}, 300);
});
}
}
}
}
@@ -44,6 +44,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "file-uploader",
form: {
component: {
multiple: true, //可选择多个
uploader: {
type: "alioss"
}
@@ -58,7 +59,8 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
uploader: {
type: "alioss"
}
}
},
helper: "可以同时选择多个文件"
}
},
cropper: {
@@ -44,10 +44,12 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "file-uploader",
form: {
component: {
multiple: true, //可选择多个
uploader: {
type: "cos"
}
}
},
helper: "可以同时选择多个文件"
}
},
pictureCard: {
@@ -41,7 +41,14 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
},
cropper: {
title: "头像裁剪上传",
type: "cropper-uploader"
type: "cropper-uploader",
form: {
component: {
uploader: {
type: "form"
}
}
}
},
avatar: {
title: "数量限制",
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
import { createUploaderRules } from "@fast-crud/fast-extends";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
@@ -33,7 +33,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
async onOpened() {
// 异步组件实例的获取
const componentRef = await crudExpose.getFormComponentRef("file", true);
console.log("componentRef", componentRef);
utils.logger.info("componentRef", componentRef);
}
}
},
@@ -56,9 +56,11 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
component: {
multiple: true, //可选择多个
uploader: {
type: "form"
type: "form",
keepName: true
}
}
},
helper: "可以同时选择多个文件"
},
column: {
component: {
@@ -155,20 +157,14 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
},
valueType: "key",
async buildUrl(value: any) {
return new Promise((resolve) => {
const url = "http://www.docmirror.cn:7070/api/upload/form/download?key=" + value;
resolve(url);
});
return "http://www.docmirror.cn:7070/api/upload/form/download?key=" + value;
}
}
},
column: {
component: {
async buildUrl(value: any) {
return new Promise((resolve) => {
const url = "http://www.docmirror.cn:7070/api/upload/form/download?key=" + value;
resolve(url);
});
return "http://www.docmirror.cn:7070/api/upload/form/download?key=" + value;
}
}
}
@@ -193,24 +189,19 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
valueType: "fileId",
async buildUrls(value: any[]) {
//批量构建url
return new Promise((resolve) => {
const urls: string[] = [];
for (const item of value) {
const url = "http://www.docmirror.cn:7070/api/upload/form/download?key=" + item;
urls.push(url);
}
resolve(urls);
});
const urls: string[] = [];
for (const item of value) {
const url = "http://www.docmirror.cn:7070/api/upload/form/download?key=" + item;
urls.push(url);
}
return urls;
}
}
},
column: {
component: {
async buildUrl(value: any) {
return new Promise((resolve) => {
const url = "http://www.docmirror.cn:7070/api/upload/form/download?key=" + value;
resolve(url);
});
return "http://www.docmirror.cn:7070/api/upload/form/download?key=" + value;
}
}
}
@@ -43,10 +43,12 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "file-uploader",
form: {
component: {
multiple: true, //可选择多个
uploader: {
type: "qiniu"
}
}
},
helper: "可以同时选择多个文件"
}
},
pictureCard: {
@@ -1,7 +1,8 @@
// @ts-ignore
import { S3Client, GetObjectCommand, PutObjectCommand, CreateBucketCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import {utils} from "@fast-crud/fast-crud";
// TODO 模拟server 你应该将此代码搬到你的server端
let bucketCreated = false;
export async function generateSignedUrl(bucket: string, key: string, type: "put" | "get" = "get") {
const client = new S3Client({
@@ -39,7 +40,7 @@ export async function generateSignedUrl(bucket: string, key: string, type: "put"
try {
url = await getSignedUrl(client, cmd);
} catch (err) {
console.log("Error getting signed URL ", err);
utils.logger.info("Error getting signed URL ", err);
}
return url;
@@ -1,8 +1,7 @@
import * as api from "./api";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
import dayjs from "dayjs";
import { computed, Ref, ref } from "vue";
import dayjs from "dayjs";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -23,71 +22,168 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const options: Ref = ref([]);
let arr = [
{
value: "1",
label: "test"
},
{
value: "1",
label: "test2"
}
];
for (let i = 0; i < 10; i++) {
arr = arr.concat(arr);
}
let i = 0;
for (const item of arr) {
i++;
item.value = i + "";
}
options.value = arr;
return {
crudOptions: {
table: {},
request: {
pageRequest,
addRequest,
editRequest,
delRequest
},
form: {
// 单列布局
col: { span: 24 },
labelCol: { span: 4 },
wrapperCol: { span: 18 }
},
toolbar: {},
rowHandle: {
fixed: "right"
buttons: {
edit: { show: true }
}
},
form: {
watch({ form }) {
form.totalAmount = form.users * form.months * form.licensePrice;
form.statementAmount = form.totalAmount - form.discountAmount;
form.statementPrice = form.statementAmount / form.months / form.users;
if (form.months && form.startTime) {
// form.endTime = dayjs(form.startTime).add(form.months, "month");
}
}
},
columns: {
id: {
title: "ID",
key: "id",
type: "text",
form: { show: false },
column: { show: false }
},
users: {
title: "用户数量",
type: "number",
column: {
width: 50
},
column: { width: 120 },
form: {
show: false
component: { min: 1, max: 10000 },
rules: [{ required: true, message: "用户数量不能为空" }]
}
},
statusRemote: {
title: "单选远程",
search: {
show: false
months: {
title: "月数",
type: "number",
column: { width: 100 },
form: {
component: { min: 1, max: 120 },
rules: [{ required: true, message: "采购月数不能为空" }]
}
},
licensePrice: {
title: "单用户价",
type: "number",
column: { width: 150 },
form: {
component: { min: 1, max: 99999 },
helper: "单个用户许可价格"
}
},
totalAmount: {
title: "总额",
type: "number",
search: { show: false },
column: { width: 150 },
form: {
component: { disabled: true }
}
},
discountAmount: {
title: "优惠",
type: "number",
column: { width: 150 },
addForm: {
value: 0
},
form: {
component: { min: 0, max: 9999999 },
rules: [{ required: true, message: "优惠金额不能为空" }]
}
},
statementAmount: {
title: "结算金额",
type: "number",
search: { show: false },
column: { width: 150 },
form: {
component: { disabled: true },
rules: [{ required: true, message: "结算金额不能为空" }],
helper: "结算金额 = 总额 - 优惠金额"
}
},
statementPrice: {
title: "结算单价",
type: "number",
column: { width: 150 },
form: {
component: { disabled: true },
helper: "结算单价 = 结算金额 / 月份 / 用户数"
}
},
startTime: {
title: "开始时间",
type: "date",
valueBuilder({ value, row, key }) {
if (value != null) {
row[key] = dayjs.unix(value);
}
},
valueResolve({ value, row, key }) {
if (value != null) {
row[key] = dayjs(value).unix();
}
},
form: {
rules: [{ required: true, message: "订阅起始日期不能为空" }],
component: {
format: "YYYY-MM-DD"
}
}
},
endTime: {
title: "结束时间",
type: "date",
valueResolve({ value, row, key }) {
if (value != null) {
row[key] = dayjs(value).unix();
}
},
form: {
component: {
format: "YYYY-MM-DD",
disabled: true
},
rules: [{ required: true, message: "订阅结束日期不能为空" }],
helper: "结束日期 = 开始日期 + 采购月份"
}
},
paymentStatus: {
title: "状态",
type: "dict-select",
column: { width: 100, align: "center" },
search: { show: true },
dict: dict({
url: "/mock/dicts/ManyOpenStatusEnum?from=dict1"
data: [
{ value: "0", label: "待支付", color: "error" },
{ value: "10", label: "部分支付", color: "warning" },
{ value: "20", label: "已支付", color: "success" }
]
}),
form: {
component: { mode: "multiple" },
rules: [{ required: true, message: "请选择一个选项" }]
},
column: {
width: 200
rules: [{ required: true, message: "支付状态不能为空" }]
}
},
description: {
title: "产品描述",
column: { show: false },
type: ["textarea"],
form: {
rules: [{ required: true, message: "描述不能为空" }],
col: {
span: 24
}
}
}
}
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, ValueChangeContext } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
import { requestForMock } from "../../../../api/service";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
@@ -80,7 +80,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
vModel: "checked"
},
valueChange({ form, value, getComponentRef }) {
console.log("form", value);
utils.logger.info("form", value);
const targetDict = getComponentRef("remote").getDict();
targetDict.url = form.modifyDict ? "/mock/dicts/moreOpenStatusEnum?remote" : "/mock/dicts/OpenStatusEnum?remote";
targetDict.reloadDict();
@@ -92,7 +92,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
vModel: "checked"
},
valueChange({ value, getComponentRef }) {
console.log("value", value);
utils.logger.info("value", value);
const targetDict = getComponentRef("remote").getDict();
targetDict.url = value ? "/mock/dicts/moreOpenStatusEnum?remote" : "/mock/dicts/OpenStatusEnum?remote";
targetDict.reloadDict();
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -55,7 +55,15 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
},
status: {
title: "本地字典",
search: { show: false },
search: {
show: true,
component: {
transformDictData(data: any[]) {
data.unshift({ value: "", label: "全部" });
return data;
}
}
},
dict: statusDict,
type: "dict-select"
},
@@ -67,7 +75,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
column: {
component: {
onDictChange(opts: any) {
console.log("字典变化:", opts);
utils.logger.info("字典变化:", opts);
}
}
}
@@ -82,7 +90,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
vModel: "checked"
},
valueChange({ form }) {
console.log("changed", form.modifyDict);
utils.logger.info("changed", form.modifyDict);
remoteDict.url = form.modifyDict ? "/mock/dicts/moreOpenStatusEnum?remote" : "/mock/dicts/OpenStatusEnum?remote";
// 由于remoteDict.cloneable =false,所以全局公用一个实例,修改会影响全部地方
remoteDict.reloadDict();
@@ -101,6 +109,28 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}
}
}
},
cache1: {
title: "全局缓存1",
search: { show: false },
dict: dict({
url: "/mock/dicts/OpenStatusEnum?cache_flat=1",
cache: true
}),
type: "dict-select"
},
cache2: {
title: "全局缓存2",
search: { show: false },
column: {
show: false
},
dict: dict({
url: "/mock/dicts/OpenStatusEnum?cache_flat=1",
immediate: false,
cache: true
}),
type: "dict-select"
}
}
}
@@ -19,7 +19,7 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
export default defineComponent({
@@ -33,7 +33,7 @@ export default defineComponent({
});
function onClick() {
console.log("this.ref", crudRef.value);
utils.logger.info("this.ref", crudRef.value);
}
return {
@@ -57,7 +57,7 @@ export function UpdateCell(id: number, key: string, value: any) {
data: { id, key, value }
});
}
export function UpdateColumn(data) {
export function UpdateColumn(data: any) {
return request({
url: apiPrefix + "/columnUpdate",
method: "post",
@@ -1,8 +1,7 @@
import * as api from "./api";
import { dict, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery, UserPageRes, EditReq, DelReq, AddReq } from "@fast-crud/fast-crud";
import { computed, reactive, ref } from "vue";
import _ from "lodash-es";
import { EditableEachCellsOpts } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditableEachCellsOpts, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { reactive, ref } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding } = crudExpose;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -46,7 +45,6 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
editing: false,
loading: false,
onSubmit: async () => {
console.log("onSubmit");
radioColumnEditor.loading = true;
try {
const data: any[] = [];
@@ -61,7 +59,6 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}
},
onCancel: () => {
console.log("cancel");
crudExpose.editable.cancel();
radioColumnEditor.editing = false;
},
@@ -111,7 +108,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
mode: "cell",
exclusive: true,
//排他式激活效果,将其他行的编辑状态触发保存
exclusiveEffect: "save",
exclusiveEffect: "save", //自动保存其他行编辑状态,cancel = 自动关闭其他行编辑状态
async updateCell(opts) {
const { row, key, value } = opts;
//如果是添加,需要返回{[rowKey]:xxx},比如:{id:2}
@@ -160,7 +157,10 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "dict-radio",
dict: radioDictRef,
column: {
width: 300
width: 300,
valueChange({ value, getComponentRef }) {
console.log("value changed:", value, getComponentRef("radio"));
}
}
},
name: {
@@ -5,7 +5,7 @@
单元格编辑
<span class="sub">单元格修改确认后直接提交到后台</span>
</div>
<div class="more"></div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/table.html#editable">文档</a></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
@@ -38,7 +38,7 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
@@ -57,17 +57,14 @@ export default defineComponent({
crudBinding,
crudRef,
active() {
crudExpose.editable.active();
crudExpose.editable.active({});
},
inactive() {
crudExpose.editable.inactive();
},
save() {
crudExpose.getTableRef().editable.submit(({ changed, removed, setData }: any) => {
console.log("changed", changed);
console.log("removed", removed);
console.log("table data:", crudBinding.value.data, crudExpose.getTableData());
utils.logger.info("table data:", crudBinding.value.data, crudExpose.getTableData());
// setData({ 0: {id:1} }); //设置data
message.success("保存,修改行:" + JSON.stringify(changed) + ";删除行:" + JSON.stringify(removed));
});
@@ -1,5 +1,6 @@
import * as api from "./api";
import { dict, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery, UserPageRes, EditReq, DelReq, AddReq } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding } = crudExpose;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -37,9 +38,18 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}
}
},
mode: {
//本地模式
name: "local",
isMergeWhenUpdate: true,
isAppendWhenAdd: true
},
table: {
editable: {
mode: "free"
enabled: true,
mode: "free",
activeDefault: true,
showAction: false
}
},
pagination: {
@@ -2,7 +2,7 @@
<fs-page>
<template #header>
<div class="title">可编辑</div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/expose.html">文档</a></div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/table.html#editable">文档</a></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
@@ -11,10 +11,14 @@
<a-radio-button :value="true">启用编辑</a-radio-button>
<a-radio-button :value="false">退出编辑</a-radio-button>
</a-radio-group>
<!-- <a-radio-group class="ml-1" v-model="crudBinding.table.editable.mode">-->
<!-- <a-radio-button label="free">自由模式</a-radio-button>-->
<!-- <a-radio-button label="row">行编辑模式</a-radio-button>-->
<!-- </a-radio-group>-->
<a-radio-group v-model:value="crudBinding.table.editable.showAction" class="ml-1">
<a-radio-button :value="true">显示操作按钮</a-radio-button>
<a-radio-button :value="false">不显示</a-radio-button>
</a-radio-group>
<a-radio-group v-model:value="crudBinding.table.editable.activeDefault" class="ml-1">
<a-radio-button :value="true">默认激活</a-radio-button>
<a-radio-button :value="false">默认不激活</a-radio-button>
</a-radio-group>
<template v-if="crudBinding.table.editable.enabled">
<fs-button class="ml-5" @click="save">保存</fs-button>
<fs-button class="ml-5" @click="log">log</fs-button>
@@ -25,9 +29,9 @@
</template>
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { defineComponent, onMounted, ref } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import { useFs, utils } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
@@ -38,14 +42,14 @@ export default defineComponent({
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
crudExpose.editable.enable({ mode: "free", activeDefault: true });
crudExpose.editable.enable({ mode: "free" });
});
return {
crudBinding,
crudRef,
active() {
crudExpose.editable.active();
crudExpose.editable.active({});
},
inactive() {
crudExpose.editable.inactive();
@@ -54,12 +58,13 @@ export default defineComponent({
const res = await crudExpose.editable.validate();
if (res !== true) {
console.error("validate error:", res);
message.error("validate error" + JSON.stringify(res));
return;
}
message.success("保存,修改行:" + JSON.stringify(crudBinding.value.data));
},
log() {
console.log("table data:", crudBinding.value.data, crudExpose.getTableData());
utils.logger.info("table data:", crudBinding.value.data, crudExpose.getTableData());
},
cancel() {
crudExpose.editable.resume();
@@ -1,5 +1,5 @@
import * as api from "./api";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -31,7 +31,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
table: {
editable: {
enabled: true,
mode: "row"
mode: "row",
exclusive: true, //排他式激活
exclusiveEffect: "save" //排他式激活时,其他行的编辑状态的处理方式
}
},
columns: {
@@ -68,7 +70,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
form: {
rules: {
async asyncValidator(context) {
console.log("context", context);
utils.logger.info("context", context);
return true;
},
message: "远程校验测试"
@@ -5,7 +5,7 @@
行编辑模式
<span class="sub">在表格内编辑每行数据</span>
</div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/expose.html">文档</a></div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/table.html#editable">文档</a></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
@@ -18,7 +18,7 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "EditableRow",
@@ -28,14 +28,14 @@ export default defineComponent({
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
crudExpose.editable.enable();
// crudExpose.editable.enable({});
});
return {
crudBinding,
crudRef,
log() {
console.log("table data:", crudBinding.value.data, crudExpose.getTableData());
utils.logger.info("table data:", crudBinding.value.data, crudExpose.getTableData());
}
};
}
@@ -2,7 +2,7 @@ import * as api from "./api";
import { dict, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery, UserPageRes, EditReq, DelReq, AddReq } from "@fast-crud/fast-crud";
import EditableRowSub from "/@/views/crud/editable/sub-crud/row/index.vue";
export default function (props: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding,crudRef } = props.crudExpose;
const { crudBinding, crudRef } = props.crudExpose;
const { crudExpose } = props;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
@@ -32,7 +32,7 @@ export default function (props: CreateCrudOptionsProps): CreateCrudOptionsRet {
form: {
wrapper: {
width: "80%"
},
}
},
columns: {
id: {
@@ -50,7 +50,7 @@ export default function (props: CreateCrudOptionsProps): CreateCrudOptionsRet {
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
}),
form:{
form: {
rules: [{ required: true, message: "请选择状态" }]
}
},
@@ -60,25 +60,25 @@ export default function (props: CreateCrudOptionsProps): CreateCrudOptionsRet {
form: {
component: {
name: EditableRowSub,
id:compute(({form})=>{
return form.id
id: compute(({ form }) => {
return form.id;
}),
on:{
async saveMain({form}){
on: {
async saveMain({ form }) {
//保存主表
const formRef = crudExpose.getFormRef()
const ret = await formRef.submit()
const formRef = crudExpose.getFormRef();
const ret = await formRef.submit();
//将form改为编辑模式
let formWrapperRef = crudExpose.getFormWrapperRef();
formWrapperRef.setFormData(ret.res)
crudRef.value.formWrapperRef.formOptions.mode = "edit"
crudRef.value.formWrapperRef.title="编辑"
const formWrapperRef = crudExpose.getFormWrapperRef();
formWrapperRef.setFormData(ret.res);
crudRef.value.formWrapperRef.formOptions.mode = "edit";
crudRef.value.formWrapperRef.title = "编辑";
}
}
},
col: {
span: 24
},
}
},
column: {
formatter: ({ row }) => {
@@ -18,7 +18,7 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import { useFs, utils } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
@@ -35,7 +35,7 @@ export default defineComponent({
crudBinding,
crudRef,
log() {
console.log("table data:", crudBinding.value.data);
utils.logger.info("table data:", crudBinding.value.data);
}
};
}
@@ -1,16 +1,8 @@
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet, DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes
} from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import * as api from "./api";
export default function ({ crudExpose,context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding } = crudExpose;
const {parentIdRef} = context
const { parentIdRef } = context;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
@@ -48,8 +40,8 @@ export default function ({ crudExpose,context }: CreateCrudOptionsProps): Create
},
search: {
show: false,
initialForm:{
parentId:parentIdRef
initialForm: {
parentId: parentIdRef
}
},
toolbar: {
@@ -63,7 +55,7 @@ export default function ({ crudExpose,context }: CreateCrudOptionsProps): Create
editable: {
enabled: true,
mode: "row",
activeDefault:false,
activeDefault: false
}
},
// pagination: { show: false, pageSize: 9999999 },
@@ -83,8 +75,8 @@ export default function ({ crudExpose,context }: CreateCrudOptionsProps): Create
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
}),
form:{
value:'1',
form: {
value: "1"
}
},
name: {
@@ -97,16 +89,16 @@ export default function ({ crudExpose,context }: CreateCrudOptionsProps): Create
]
}
},
parentId:{
parentId: {
title: "父Id",
type: "number",
search:{
show:true,
search: {
show: true
},
form:{
value:parentIdRef,
component:{
disabled:true
form: {
value: parentIdRef,
component: {
disabled: true
}
}
},
@@ -1,20 +1,16 @@
<template>
<div class="sub-table">
<div v-if="id>0" style="height: 500px; position: relative">
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
</div>
<div v-else>
<fs-button @click="saveMain">保存</fs-button> 保存后即可编辑子表
</div>
<div v-if="id > 0" style="height: 500px; position: relative">
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
</div>
<div v-else><fs-button @click="saveMain">保存</fs-button> 保存后即可编辑子表</div>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, watch,ref } from "vue";
import { defineComponent, onMounted, watch, ref } from "vue";
import createCrudOptions from "./crud";
import { useFs, useUi } from "@fast-crud/fast-crud";
import { useFs, useUi, utils } from "@fast-crud/fast-crud";
export default defineComponent({
name: "EditableSubCrudTarget",
@@ -22,50 +18,50 @@ export default defineComponent({
/**
* 主表id
*/
id:{
type:Number,
default:0
id: {
type: Number,
default: 0
},
disabled:{
type:Boolean,
default:false
},
readonly:{
type:Boolean,
default:false
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
}
},
emits: ["save-main"],
setup(props, ctx) {
const parentIdRef = ref(props.id)
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions ,context:{parentIdRef}});
// eslint-disable-next-line vue/no-setup-props-destructure
const parentIdRef = ref(props.id);
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { parentIdRef } });
const { ui } = useUi();
let formItemContext = ui.formItem.injectFormItemContext();
function emit(data:any) {
console.log("emit:", data);
function emit(data: any) {
utils.logger.info("emit:", data);
formItemContext.onBlur();
formItemContext.onChange();
}
function saveMain(){
ctx.emit("save-main",true)
function saveMain() {
ctx.emit("save-main", true);
}
watch(
() => {
return props.id;
},
(value: any) => {
if(value>0){
if (value > 0) {
crudExpose.setSearchFormData({
form:{parentId:value},
mergeForm:true,
triggerSearch:true
})
parentIdRef.value = value
form: { parentId: value },
mergeForm: true,
triggerSearch: true
});
parentIdRef.value = value;
}
},
{
@@ -76,24 +72,27 @@ export default defineComponent({
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
watch(()=>{
return props.disabled || props.readonly
},(value)=>{
if(value){
crudBinding.value.table.editable.readonly=true
crudBinding.value.actionbar.buttons.addRow.show=false
crudBinding.value.rowHandle.show=false
}else{
crudBinding.value.table.editable.readonly=false
crudBinding.value.actionbar.buttons.addRow.show=true
crudBinding.value.rowHandle.show=true
watch(
() => {
return props.disabled || props.readonly;
},
(value) => {
if (value) {
crudBinding.value.table.editable.readonly = true;
crudBinding.value.actionbar.buttons.addRow.show = false;
crudBinding.value.rowHandle.show = false;
} else {
crudBinding.value.table.editable.readonly = false;
crudBinding.value.actionbar.buttons.addRow.show = true;
crudBinding.value.rowHandle.show = true;
}
},
{
immediate: true
}
},{
immediate:true
})
);
});
return {
crudBinding,
crudRef,
@@ -67,6 +67,10 @@ export default function (props: CreateCrudOptionsProps): CreateCrudOptionsRet {
},
col: {
span: 24
},
valueResolve({ form }) {
//重要,移除$editable_id字段,返回干净的tableData数据
form.subTable = crudExpose.editable.getTableData(form.subTable);
}
},
column: {
@@ -1,4 +1,6 @@
import { CreateCrudOptionsProps, CreateCrudOptionsRet, dict } from "@fast-crud/fast-crud";
import { compute, CreateCrudOptionsProps, CreateCrudOptionsRet, dict } from "@fast-crud/fast-crud";
import createCrudOptionsText from "/@/views/crud/component/text/crud";
import * as textTableApi from "/@/views/crud/component/text/api";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding } = crudExpose;
@@ -33,7 +35,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
table: {
editable: {
enabled: true,
mode: "free"
mode: "free",
activeDefault: true,
showAction: false
}
},
pagination: { show: false, pageSize: 9999999 },
@@ -64,6 +68,27 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
]
}
},
tableSelect: {
title: "tableSelect",
type: "table-select",
dict: dict({
value: "id",
label: "name",
//重要,根据value懒加载数据
getNodesByValues: async (values: any[]) => {
return await textTableApi.GetByIds(values);
}
}),
form: {
show: compute(({ form }) => {
return form.dynamicShow;
}),
component: {
crossPage: true,
createCrudOptions: createCrudOptionsText
}
}
},
createdAt: {
column: {
show: false
@@ -7,7 +7,7 @@
<script lang="ts">
import { defineComponent, onMounted, watch } from "vue";
import createCrudOptions from "./crud";
import { useFs, useUi } from "@fast-crud/fast-crud";
import { useFs, useUi, utils } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
@@ -18,6 +18,14 @@ export default defineComponent({
default() {
return undefined;
}
},
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
}
},
emits: ["update:modelValue"],
@@ -26,8 +34,8 @@ export default defineComponent({
const { ui } = useUi();
let formItemContext = ui.formItem.injectFormItemContext();
function emit(data) {
console.log("emit:", data);
function emit(data: any) {
utils.logger.info("emit:", data);
ctx.emit("update:modelValue", data);
formItemContext.onBlur();
formItemContext.onChange();
@@ -36,6 +44,7 @@ export default defineComponent({
// 页面打开后获取列表数据
onMounted(() => {
// crudExpose.doRefresh();
watch(
() => {
return props.modelValue;
@@ -53,7 +62,26 @@ export default defineComponent({
}
);
crudExpose.editable.enable({ mode: "free", activeDefault: true });
watch(
() => {
return props.disabled || props.readonly;
},
(value) => {
if (value) {
crudBinding.value.table.editable.readonly = true;
crudBinding.value.actionbar.buttons.addRow.show = false;
crudBinding.value.rowHandle.show = false;
} else {
crudBinding.value.table.editable.readonly = false;
crudBinding.value.actionbar.buttons.addRow.show = true;
crudBinding.value.rowHandle.show = true;
}
},
{
immediate: true
}
);
// crudExpose.editable.enable({ mode: "free", activeDefault: true });
});
async function validate() {
@@ -1,8 +1,11 @@
<template>
<fs-page>
<template #header>
<div class="title">vModel编辑</div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/expose.html">文档</a></div>
<div class="title">
vModel编辑
<span class="sub">子表格作为主表的一个字段整体编辑整体提交</span>
</div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/table.html#editable">文档</a></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
@@ -15,7 +18,7 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
@@ -32,7 +35,7 @@ export default defineComponent({
crudBinding,
crudRef,
log() {
console.log("table data:", crudBinding.value.data);
utils.logger.info("table data:", crudBinding.value.data);
}
};
}
@@ -1,7 +1,10 @@
<template>
<fs-page>
<template #header>
<div class="title">行编辑模式</div>
<div class="title">
行编辑模式
<span class="sub">暂不支持树形结构</span>
</div>
<div class="more"><a target="_blank" href="http://fast-crud.docmirror.cn/api/expose.html">文档</a></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding" />
@@ -6,6 +6,11 @@ const options: any = {
const list = [
{
radio: "1"
// children: [
// {
// radio: "1"
// }
// ]
},
{
radio: "2"
@@ -22,6 +22,8 @@
<fs-button class="ml-1" @click="editCol">编辑列</fs-button>
<fs-button class="ml-1" @click="cancel">取消/恢复原状</fs-button>
<fs-button class="ml-1" @click="save">保存</fs-button>
<fs-button class="ml-1" @click="log">log</fs-button>
</template>
</template>
</fs-crud>
@@ -31,7 +33,7 @@
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
@@ -72,12 +74,14 @@ export default defineComponent({
},
save() {
crudExpose.getTableRef().editable.submit(({ changed, removed, setData }: any) => {
console.log("changed", changed);
console.log("removed", removed);
utils.logger.info("table data:", crudBinding.value.data, crudExpose.getTableData());
// setData({ 0: {id:1} }); //设置data
message.success("保存,修改行:" + JSON.stringify(changed) + ";删除行:" + JSON.stringify(removed));
});
},
log() {
console.log("table data:", crudBinding.value.data, crudExpose.getTableData());
},
cancel() {
crudExpose.editable.resume();
},
@@ -1,5 +1,15 @@
import * as api from "./api.js";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils
} from "@fast-crud/fast-crud";
import { ref } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
@@ -40,6 +50,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
class: clazz
};
},
onExpand(open: boolean, row: any) {
utils.logger.info("expand事件:", open, row);
},
slots: {
expandedRowRender: (scope: any) => {
return (
@@ -30,6 +30,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
},
toolbar: {
export: {
// columns: [{ key: "id", title: "ID" }],
columnBuilder: ({ col }) => {
// https://docs.sheetjs.com/docs/csf/features/#row-and-column-properties
if (col.key === "multi") {
@@ -1,5 +1,11 @@
<template>
<fs-page>
<template #header>
<div class="title">导出</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/toolbar.html#export">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #toolbar-left>
<fs-label lass="ml-5" label="导出方式">
@@ -1,5 +1,15 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils
} from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -30,7 +40,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
table: {
// 表头过滤改变事件
onFilterChange(filters: any) {
console.log("onFilterChange", filters);
utils.logger.info("onFilterChange", filters);
crudExpose.setSearchFormData({
form: {
remote: filters.remote
@@ -1,5 +1,16 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, ValueChangeContext } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils,
ValueChangeContext
} from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -66,7 +77,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
vModel: "checked"
},
valueChange(context) {
console.log("column value changed:", context);
utils.logger.info("column value changed:", context);
}
}
}
@@ -48,3 +48,11 @@ export function BatchDelete(ids: any[]) {
data: { ids }
});
}
export function ColumnUpdate(key: string, value: any) {
return request({
url: apiPrefix + "/columnUpdate",
method: "post",
data: { key, value }
});
}
@@ -1,5 +1,15 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils
} from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -46,7 +56,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
text: "自定义按钮",
show: true,
click() {
console.log("click");
utils.logger.info("click");
}
}
}
@@ -73,7 +83,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
order: 4,
show: true,
click(context) {
console.log("click", context);
utils.logger.info("click", context);
}
}
}
@@ -25,6 +25,7 @@
import { defineComponent, onMounted, reactive } from "vue";
import { message } from "ant-design-vue";
import FeatureLocalImportValueInput from "./local.vue";
import {utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "FeatureLocalImport",
components: { FeatureLocalImportValueInput },
@@ -36,7 +37,7 @@ export default defineComponent({
function submit() {
message.info("submit:" + JSON.stringify(form));
console.log("submit:", form);
utils.logger.info("submit:", form);
}
return {
form,
@@ -5,7 +5,7 @@
<script lang="ts">
import { defineComponent, onMounted, watch } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "FeatureLocalImportValueInput",
@@ -39,7 +39,7 @@ export default defineComponent({
// 通过crudBinding.value.data 可以获取表格实时数据
function showData() {
console.log("data:", crudBinding.value.data);
utils.logger.info("data:", crudBinding.value.data);
}
return {
@@ -22,9 +22,11 @@
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive } from "vue";
import { defineComponent, reactive } from "vue";
import { message } from "ant-design-vue";
import FeatureLocalModelValueInput from "./local.vue";
import {utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "FeatureLocalVModel",
components: { FeatureLocalModelValueInput },
@@ -36,7 +38,7 @@ export default defineComponent({
function submit() {
message.info("submit:" + JSON.stringify(form));
console.log("submit:", form);
utils.logger.info("submit:", form);
}
return {
form,
@@ -5,7 +5,7 @@
<script lang="ts">
import { defineComponent, onMounted, watch } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import {useFs, utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "FeatureLocalModelValueInput",
@@ -39,7 +39,7 @@ export default defineComponent({
// 通过crudBinding.value.data 可以获取表格实时数据
function showData() {
console.log("data:", crudBinding.value.data);
utils.logger.info("data:", crudBinding.value.data);
}
return {
@@ -14,7 +14,7 @@
<script lang="ts">
import { defineComponent, ref, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useExpose, useCrud, useFs } from "@fast-crud/fast-crud";
import {useExpose, useCrud, useFs, utils} from "@fast-crud/fast-crud";
export default defineComponent({
name: "FeatureLocal",
@@ -29,7 +29,7 @@ export default defineComponent({
});
// 通过crudBinding.value.data 可以获取表格实时数据
function showData() {
console.log("data:", crudBinding.value.data);
utils.logger.info("data:", crudBinding.value.data);
}
//初始化本地数据示例
@@ -1,5 +1,15 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils
} from "@fast-crud/fast-crud";
import { Modal } from "ant-design-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -47,10 +57,10 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
showSuccessMessage: true, //是否显示删除成功记录
refreshTable: true, //删除后刷新表格
onCanceled({ row }) {
console.log(`记录${row.id}取消删除`);
utils.logger.info(`记录${row.id}取消删除`);
},
onRemoved({ row }) {
console.log(`记录${row.id}已删除`);
utils.logger.info(`记录${row.id}已删除`);
}
}
},
@@ -31,7 +31,7 @@ export default defineComponent({
.fs-search-multi-line-buttons {
position: absolute;
bottom: -38px;
right: 160px;
right: 210px;
}
.ant-form-item-label:before {
border-bottom: 1px solid #eee;
@@ -1,6 +1,6 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { computed } from "vue";
import { computed, ref } from "vue";
import { message } from "ant-design-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
@@ -24,6 +24,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const statusRef = dict({
url: "/mock/dicts/OpenStatusEnum?single"
});
const formLayoutRef = ref("inline");
return {
crudOptions: {
request: {
@@ -38,9 +39,19 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
//查询默认值
radio: "1"
},
options: {
layout: formLayoutRef
},
container: {
action: {
col: {
span: 6
}
}
},
buttons: {
custom: {
text: "自定义",
text: "label上置",
show: true,
order: 3,
class: "fs-test",
@@ -51,7 +62,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
}
},
click() {
console.log("点击了自定义按钮");
formLayoutRef.value = formLayoutRef.value === "vertical" ? "inline" : "vertical";
}
}
}
@@ -61,7 +72,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
show: true,
type: "card",
options: computed(() => {
return statusRef.data;
return statusRef.data as TabsFilterOption[];
})
},
columns: {
@@ -95,7 +106,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "text",
search: {
show: true,
value: "1"
value: "2"
}
},
customRender: {
@@ -18,6 +18,18 @@ const list = [
{
radio: "0",
text: "3"
},
{
radio: "1",
text: "2"
},
{
radio: "1",
text: "3"
},
{
radio: "0",
text: "1"
}
];
options.list = list;
@@ -1,6 +1,6 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/FeatureSelection";
const apiPrefix = "/mock/FeatureSelectionRadio";
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
@@ -1,5 +1,15 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils
} from "@fast-crud/fast-crud";
import { ref } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -21,7 +31,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const selectedRowKey = ref();
const onSelectChange = (changed: any) => {
console.log("selection", changed);
utils.logger.info("selection", changed);
selectedRowKey.value = changed;
};
return {
@@ -50,7 +60,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
key: "id",
type: "number",
column: {
width: 50
width: 140
},
form: {
show: false
@@ -1,6 +1,6 @@
import mockUtil from "/src/mock/base";
const options: any = {
name: "FeatureSelection",
name: "FeatureSelectionRadio",
idGenerator: 0
};
const list = [
@@ -8,7 +8,8 @@ const list = [
radio: "1"
},
{
radio: "2"
radio: "2",
children: [{ radio: "2" }, { radio: "0", children: [{ radio: "1" }] }]
},
{
radio: "0"
@@ -1,7 +1,17 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import {
AddReq,
CreateCrudOptionsProps,
CreateCrudOptionsRet,
DelReq,
dict,
EditReq,
UserPageQuery,
UserPageRes,
utils
} from "@fast-crud/fast-crud";
import { ref } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
@@ -20,13 +30,13 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
};
const selectedRowKeys = ref([]);
context.selectedRowKeys = selectedRowKeys;
const onSelectChange = (changed: any) => {
console.log("selection", changed);
utils.logger.info("selection", changed);
selectedRowKeys.value = changed;
};
return {
selectedRowKeys, //返回给index.vue去使用
crudOptions: {
table: {
rowKey: "id",
@@ -47,7 +57,6 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
columns: {
id: {
title: "ID",
key: "id",
type: "number",
column: {
width: 50
@@ -56,13 +65,10 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
show: false
}
},
radio: {
title: "状态",
search: { show: true },
type: "dict-radio",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
text: {
title: "Text",
type: "text",
search: { show: true }
}
}
}
@@ -14,15 +14,17 @@
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from "vue";
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useExpose, useCrud, useFs } from "@fast-crud/fast-crud";
import { useFs } from "@fast-crud/fast-crud";
import { message, Modal } from "ant-design-vue";
import { BatchDelete } from "./api";
export default defineComponent({
name: "FeatureSelection",
setup() {
const { crudBinding, crudRef, crudExpose, selectedRowKeys } = useFs({ createCrudOptions });
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
const selectedRowKeys = context.selectedRowKeys;
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
@@ -5,12 +5,15 @@ const options: any = {
};
const list = [
{
text: "张三",
radio: "1"
},
{
text: "李四",
radio: "2"
},
{
text: "王五",
radio: "0"
}
];

Some files were not shown because too many files have changed in this diff Show More