文件上传组件前端校验超128长度大小,不清楚怎么配置

原因是拼上后端返回的文件全路径后超出了字段的存储长度,后端通过注解@Field.String(size=1024)修改字段的存储长度后重新运行一遍服务。

Oinone社区 作者:oinone原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/9.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
oinone的头像oinone
上一篇 2023年6月20日 pm4:07
下一篇 2023年11月2日 pm1:58

相关推荐

  • 自定义视图部分区域渲染设计器的配置

    自定义视图与界面设计器配置对接 在日常开发中,我们经常会遇到自定义视图的需求。自定义视图不仅需要与平台机制结合,还要实现与界面设计器中配置的字段和动作的无缝对接。本文将介绍如何将自定义视图与界面设计器中配置的字段和动作的无缝对接,实现字段和动作的渲染。 用大白话来讲就是:当前页面一部分是自定义的,一部分是设计器生成的 代码地址 目录 自定义表单视图与字段、动作的结合 自定义表格视图与字段、动作的结合 自定义表单视图与字段、动作的结合 首先需要在界面设计器配置好对应界面,虽然配置的页面样式跟期望展示的 UI 的不一样,但是数据的分发、汇总以及动作的交互也是一致的,所以我们可以通过自定义的方式替换这个页面的 UI,但是数据以及动作,是完全可以通过平台的能力获取的。 注册表单对应的 SPI // CustomFormWidget.ts import CustomForm from './CustomForm.vue'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Form, widget: 'CustomFormWidget' }) ) export class CustomFormWidget extends FormWidget { public initialize(props: BaseElementObjectViewWidgetProps): this { super.initialize(props); this.setComponent(CustomForm); return this; } } <!– CustomForm.vue –> <template> <div class="custom-form-container"> <div class="custom-form-tip">自定义视图</div> </div> </template> <script lang="ts"> import { DslRender, DslRenderDefinition, PropRecordHelper } from '@kunlun/dependencies'; import { createVNode, defineComponent, onMounted, PropType, ref, VNode } from 'vue'; export default defineComponent({ inheritAttrs: false, props: { formData: { type: Object as PropType<Record<string, any>>, default: () => ({}) } } }); </script> 在上述的代码中,我们继承的是 FormWidget,那么这个页面会自动发起对应的请求,所有的数据都在 formData 中。 表单视图渲染动作 在最开始我们讲到过,当前页面是在界面设计器配置过,所有在CustomFormWidget里面是可以拿到当前页面配置的元数据信息,所以我们可以拿到界面设计器配置的字段跟动作 /// CustomFormWidget.ts @Widget.Method() protected renderActionVNodes() { // 从dsl中获取actionBar,actionBar里面包含了界面设计器配置的动作 const actionBar = this.metadataRuntimeContext.viewDsl?.widgets.find((w) => w.slot === 'actionBar'); if (actionBar) { // actionBar.widgets 就是界面设计器配置的动作,借助平台提供的DslRender.render方法,将对应的dsl转换成VNode return actionBar.widgets.map((w, index) => DslRender.render({ …w, __index: index }) ); } return null; } 因为 renderActionVNodes 方法返回的是 VNode,所以我们必须借助 vue 的 render 函数才能渲染。 <!– ActionRender.vue –> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ inheritAttrs: false, props: { renderActionVNodes: { type: Function, required: true } }, render() { return this.renderActionVNodes(); } });…

    2024年9月12日
    1.3K01
  • oinone的rsql与传统sql语法对照表

    rsql sql 描述 field01 == "name" field01 = "name" 等于 field01 != "name" field01 != "name" 不等于 field01 =gt= 1 field01 > 1 大于 field01 =ge= 1 field01 >= 1 大于等于 field01 =lt= 1 field01 < 1 小于 field01 =le= 1 field01 <= 1 小于等于 field01 =isnull=true field01 is null 字段为null field01 =notnull= 1 field01 is not null 字段不为null field01 =in= ("foo") field01 in ("foo") 多条件 field01 =out= ("foo") field01 not in ("foo") 不在多条件中 field01 =cole= field02 field01 = field02 字段作为查询参数 field01 =colnt= field02 field01 != field02 字段作为查询参数 field01 =like="foo" field01 like "%foo%" 全模糊匹配,rsql语法中无需拼接通配符”%“ field01 =starts="foo" field01 like "foo%" 前缀模糊匹配,rsql语法中无需拼接通配符”%“ field01 =ends="foo" field01 like “%foo" 后缀模糊匹配,rsql语法中无需拼接通配符”%“ field01 =notlike="foo" field01 not like "%foo%" 全模糊不匹配,rsql语法中无需拼接通配符”%“ field01 =notstarts="foo" field01 not like "foo%" 前缀模糊不匹配,rsql语法中无需拼接通配符”%“ field01 =notends="foo" field01 not like “%foo" 后缀模糊不匹配,rsql语法中无需拼接通配符”%“ field01 =has=(ENUM_NAME1, ENUM_NAME2) 有多值枚举中的几个值 field01 =hasnt=(ENUM_NAME1,ENUM_NAME2) 没有多值枚举中的几个值 field01 =bit=ENUM_NAME1 有二进制枚举中的单个值 field01 =notbit=ENUM_NAME1 没有二进制枚举中的单个值 前端代码中使用工具类拼接rsql 该工具类在oinone的前端基础框架中提供 import { Condition } from '@kunlun/dependencies'; const rsqlCondition = new Condition('field01').equal('foo') .and(new Condition('field02').in(['bar'])) .and(new Condition('field03').notIn(['foo'])) .or(new Condition('field04').greaterThanOrEuqalTo(12)) .or(new Condition('field05').like('foo')) .or(new Condition('field06').notStarts('bar')) .or(new Condition('field07').isNull()) .or(new Condition('field08').notNull()) .and(new Condition('field09').bitEqual('BIT_ENUM_1')) .and(new Condition('field10').bitNotEqual('BIT_ENUM_2')) .and(new Condition('field11').has('ENUM_NAME_1')) .and(new Condition('field12').hasNot(['ENUM_NAME_2', 'ENUM_NAME_3'])); const rsqlStr = rsqlCondition.toString();…

    2023年11月1日
    4.0K00
  • 「前端」关闭源码依赖

    问题背景 在 5.x 版本的 oinone 前端架构中,我们开放了部分源码,但是导致以下性能问题: 1.构建耗时增加​​:Webpack 需要编译源码文件 2.​​加载性能下降​​:页面需加载全部编译产物 3.​​冷启动缓慢​​:开发服务器启动时间延长 以下方案通过关闭源码依赖。 操作步骤 1. 添加路径修正脚本 1: 在当前项目工程根目录中的scripts目录添加patch-package-entry.js脚本,内容如下: const fs = require('fs'); const path = require('path'); const targetPackages = [ '@kunlun+vue-admin-base', '@kunlun+vue-admin-layout', '@kunlun+vue-router', '@kunlun+vue-ui', '@kunlun+vue-ui-antd', '@kunlun+vue-ui-common', '@kunlun+vue-ui-el', '@kunlun+vue-widget' ]; // 递归查找目标包的 package.json function findPackageJson(rootDir, pkgName) { const entries = fs.readdirSync(rootDir); for (const entry of entries) { const entryPath = path.join(rootDir, entry); const stat = fs.statSync(entryPath); if (stat.isDirectory()) { if (entry.startsWith(pkgName)) { const [pkGroupName, name] = pkgName.split('+'); const pkgDir = path.join(entryPath, 'node_modules', pkGroupName, name); const pkgJsonPath = path.join(pkgDir, 'package.json'); if (fs.existsSync(pkgJsonPath)) { return pkgJsonPath; } } // 递归查找子目录 const found = findPackageJson(entryPath, pkgName); if (found) return found; } } return null; } // 从 node_modules/.pnpm 开始查找 const pnpmDir = path.join(__dirname, '../', 'node_modules', '.pnpm'); for (const pkgName of targetPackages) { const packageJsonPath = findPackageJson(pnpmDir, pkgName); if (packageJsonPath) { try { const packageJSON = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); if (packageJSON.main === 'index.ts') { const libName = packageJSON.name.replace('@', '').replace('/', '-'); packageJSON.main = `dist/${libName}.esm.js`; packageJSON.module = `dist/${libName}.esm.js`; const typings = 'dist/types/index.d.ts'; packageJSON.typings = typings; const [pwd] = packageJsonPath.split('package.json'); const typingsUrl = path.resolve(pwd, typings); const dir = fs.existsSync(typingsUrl); if (!dir)…

    2025年4月17日
    45600
  • OioProvider详解

    OioProvider OioProvider是平台的初始化入口。 示例入口 main.ts import { VueOioProvider } from '@kunlun/dependencies'; VueOioProvider(); 网络请求/响应配置 http 平台统一使用apollo作为统一的http请求发起服务,并使用GraphQL协议作为前后端协议。 参考文档: apollo-client graphql 配置方式 VueOioProvider({ http?: OioHttpConfig }); OioHttpConfig /** * OioHttp配置 */ export interface OioHttpConfig { /** * base url */ url: string; /** * 拦截器配置 */ interceptor?: Partial<InterceptorOptions>; /** * 中间件配置(优先于拦截器) */ middleware?: NetworkMiddlewareHandler | NetworkMiddlewareHandler[]; } 内置拦截器可选项 InterceptorOptions /** * 拦截器可选项 */ export interface InterceptorOptions { /** * 网络错误拦截器 */ networkError: NetworkInterceptor; /** * 请求成功拦截器 (success) */ requestSuccess: NetworkInterceptor; /** * 重定向拦截器 (success) */ actionRedirect: NetworkInterceptor; /** * 登录重定向拦截器 (error) */ loginRedirect: NetworkInterceptor; /** * 请求错误拦截器 (error) */ requestError: NetworkInterceptor; /** * MessageHub拦截器 (success/error) */ messageHub: NetworkInterceptor; /** * 前置拦截器 */ beforeInterceptors: NetworkInterceptor | NetworkInterceptor[]; /** * 后置拦截器 */ afterInterceptors: NetworkInterceptor | NetworkInterceptor[]; } 内置拦截器执行顺序: beforeInterceptors:前置拦截器 networkError:网络错误 actionRedirect:重定向 requestSuccess 请求成功 loginRedirect:登录重定向 requestError:请求错误 messageHub:MessageHub afterInterceptors:后置拦截器 NetworkInterceptor /** * <h3>网络请求拦截器</h3> * <ul> * <li>拦截器将按照注册顺序依次执行</li> * <li>当任何一个拦截器返回false时,将中断拦截器执行</li> * <li>内置拦截器总是优先于自定义拦截器执行</li> * </ul> * */ export interface NetworkInterceptor { /** * 成功拦截 * @param response 响应结果 */ success?(response: IResponseResult): ReturnPromise<boolean>; /** * 错误拦截 * @param response 响应结果 */ error?(response: IResponseErrorResult): ReturnPromise<boolean>; } 自定义路由配置 router 配置方式 VueOioProvider({ router?: RouterPath[]…

    2023年11月6日
    1.1K00
  • 自定义组件之手动渲染基础(v4)

    阅读之前 你应该: 了解DSL相关内容。母版-布局-DSL 渲染基础(v4) 了解SPI机制相关内容。组件SPI机制(v4.3.0) 了解组件相关内容。 Class Component(ts)(v4) 自定义组件之自动渲染(组件插槽的使用)(v4) 为什么需要手动渲染 在自定义组件之自动渲染(组件插槽的使用)(v4)文章中,我们介绍了带有具名插槽的组件可以使用DSL模板进行自动化渲染,并且可以用相对简单的方式与元数据进行结合。 虽然自动化渲染在实现基本业务逻辑的情况下,有着良好的表现,但自动化渲染方式也有着不可避免的局限性。 比如:当需要多个视图在同一个位置进行切换。 在我们的平台中,界面设计器的设计页面,在任何一个组件在选中后,需要渲染对应的右侧属性面板。每个面板的视图信息是保存在对应的元件中的。根据元件的不同,找到对应的视图进行渲染。在单个视图中使用自动化渲染是无法处理这一问题的,我们需要一种可以局部渲染指定视图的方式,来解决这一问题。 获取一个视图 使用ViewCache获取视图 export class ViewCache { /** * 通过模型编码和名称获取视图 * @param model 模型编码 * @param name 名称 * @param force 强制查询 * @return 运行时视图 */ public static async get(model: string, name: string, force = false): Promise<RuntimeView | undefined> /** * 通过模型编码、自定义名称和模板获取编译后的视图(此视图非完整视图,仅用于自定义渲染使用) * @param model 模型编码 * @param name 名称(用作缓存key) * @param template 视图模板 * @param force 强制查询 * @return 运行时视图 */ public static async compile( model: string, name: string, template: string, force = false ): Promise<RuntimeView | undefined> } ViewCache#get:用于服务端定义视图,客户端直接获取完整视图信息。 ViewCache#compile:用于客户端定义视图,通过服务端编译填充元数据相关信息,但不包含视图其他信息。 自定义一个带有具名插槽的组件,并提供切换视图的相关按钮 以下是一个自定义组件的完整示例,其使用ViewCache#compile方法获取视图。 view.ts const template1 = `<view> <field data="id" invisible="true" /> <field data="code" label="编码" /> <field data="name" label="名称" /> </view>`; const template2 = `<view> <field data="id" invisible="true" /> <field data="name" label="名称" /> <field data="code" label="编码" /> </view>`; export const templates = { template1, template2 }; ManualDemoWidget.ts import { BaseElementWidget, createRuntimeContextForWidget, FormWidget, RuntimeView, SPI, ViewCache, ViewType, Widget } from '@kunlun/dependencies'; import ManualDemo from './ManualDemo.vue'; import { templates } from './view'; @SPI.ClassFactory(BaseElementWidget.Token({ widget: 'ManualDemo' })) export class ManualDemoWidget extends BaseElementWidget { private formWidget: FormWidget | undefined; public…

    2023年11月1日
    93600

Leave a Reply

登录后才能评论