提交 816db611 编写于 作者: RedPig97's avatar RedPig97

update:更新

上级 239662ae
<AppSpan <AppSpan
name="{{item.codeName}}" name="{{item.codeName}}"
{{!-- :value="data.{{item.psEditor.name}}" --}} {{!-- :value="data.{{item.psEditor.name}}" --}}
value="标签测试"
{{#if item.psEditor.codeList}} {{#if item.psEditor.codeList}}
codeListTag="{{item.psEditor.codeList.codeListTag}}" codeListTag="{{item.psEditor.codeList.codeListTag}}"
codeListType="{{item.psEditor.codeList.codeListType}}" codeListType="{{item.psEditor.codeList.codeListType}}"
......
<script setup lang="ts">
import { onBeforeMount, Ref, ref } from "vue";
import { IActionParam, IParam, handleEditorNavParams, typeOf, loadCodeListData, handleLevelCodeList } from "@ibiz-core";
interface DropdownListProps {
/**
* @description 编辑器名称
*/
name: string;
/**
* @description 编辑器值
*/
value: string;
/**
* @description 禁用
*/
disabled?: boolean;
/**
* @description 占位提示信息
*/
placeholder?: string;
/**
* @description 表单数据或表格行数据
*/
data?: IParam;
/**
* @description 上下文
*/
contextProp?: IParam;
/**
* @description 视图参数
*/
viewParamsProp?: IParam;
/**
* @description 局部上下文
*/
localContext?: IParam;
/**
* @description 局部视图参数
*/
localParam?: IParam;
/**
* @description 多选
*/
multiple?: boolean;
/**
* @description 代码表标识
*/
codeListTag?: string;
/**
* @description 代码表类型
*/
codeListType?: string;
/**
* @description 值分隔符
*/
valueSeparator?: string;
}
interface EditorEmit{
(name: 'editorEvent', value: IActionParam): void
}
const props = withDefaults(defineProps<DropdownListProps>(), {
multiple: false,
valueSeparator: ',',
})
const emit = defineEmits<EditorEmit>()
const { navContext, navViewParam } = handleEditorNavParams(props);
let curValue: Ref<any> = ref(
props.multiple ?
props.value?.split(props.valueSeparator) : props.value
);
let items: Ref<IParam[]> = ref([]);
const onChange = (select: any, option: any) => {
const value = typeOf(select) == 'array' ? select.join(props.valueSeparator) : select;
emit('editorEvent', { tag: props.name, action: "valueChange", data: value});
}
onBeforeMount(() => {
loadCodeListData(
props.codeListTag,
props.codeListType,
navContext,
navViewParam,
).then((codeListData: IParam[]) => {
items.value = handleLevelCodeList(codeListData);
})
})
</script>
<template>
<a-select
allowClear
:class="['app-editor-container', `app-dropdown-list-${name}`]"
v-model:value="curValue"
:options="items"
:mode="multiple ? 'multiple': 'combobox'"
:disabled="disabled"
@change="onChange"
:placeholder="placeholder">
</a-select>
</template>
<style scoped>
</style>
\ No newline at end of file
<script setup lang="ts">
import { IActionParam } from "@ibiz-core";
interface InputProps{
/**
* @description 编辑器名称
*/
name: string;
/**
* @description 编辑器值
*/
value: string | number;
/**
* @description 禁用
*/
disabled?: boolean;
/**
* @description 占位提示信息
*/
placeholder?: string;
/**
* @description 输入框类型
*/
type?: 'text' | 'password' | 'textarea' | 'number';
/**
* @description 文本输入框最大字符长度
*/
maxLength?: number;
/**
* @description 数值框最大值
*/
max?: number;
/**
* @description 数值框最小值
*/
min?: number;
/**
* @description 数值框精度
*/
precision?: number;
/**
* @description 是否显示最大长度
*/
showMaxLength?: boolean;
}
interface EditorEmit{
(name: 'editorEvent', value: IActionParam): void
}
const props = withDefaults(defineProps<InputProps>(), {
type: 'text',
showMaxLength: false,
})
const emit = defineEmits<EditorEmit>()
const onChange = ($event: any) => {
const value = $event.target.value;
emit('editorEvent', { tag: props.name, action: "valueChange", data: value});
}
</script>
<template>
<div :class="['app-editor-container',`app-input-${name}`]">
<a-input
allowClear
v-if="Object.is('text', type)"
v-model:value="value"
:disabled="disabled"
:maxlength="maxLength"
@blur="onChange"
:placeholder="showMaxLength ? `最大内容长度为${maxLength}` : placeholder" />
<a-input-password
v-if="Object.is('password', type)"
v-model:value="value"
:disabled="disabled"
@blur="onChange"
:placeholder="placeholder"/>
<a-textarea
showCount
allowClear
v-if="Object.is('textarea', type)"
v-model:value="value"
:disabled="disabled"
:maxlength="maxLength"
@blur="onChange"
:placeholder="placeholder"/>
<a-input-number
v-if="Object.is('number', type)"
v-model:value="value"
:max="max"
:min="min"
:disabled="disabled"
:precision="precision"
@blur="onChange"
:placeholder="placeholder"/>
</div>
</template>
<style scoped>
</style>
\ No newline at end of file
<script setup lang="ts">
import { handleEditorNavParams, loadCodeListData, IParam } from "@ibiz-core";
import { onBeforeMount, ref, Ref } from "vue";
interface SpanProps {
/**
* 当前值
*
* @type {*}
* @memberof AppSpan
*/
value: string;
/**
* 传入表单数据
*
* @type {*}
* @memberof AppSpan
*/
data?: IParam;
/**
* 数据类型
*
* @type {string}
* @memberof AppSpan
*/
dataType?: string;
/**
* 单位名称
*
* @type {string}
* @memberof AppSpan
*/
unitName?: string;
/**
* 精度
*
* @type {number}
* @memberof AppSpan
*/
precision?: number;
/**
* 数据值格式化
*
* @type {string}
* @memberof AppSpan
*/
valueFormat: string;
/**
* 当前表单项名称
*
* @type {*}
* @memberof AppSpan
*/
name?: string;
/**
* @description 代码表标识
*/
codeListTag?: string;
/**
* @description 代码表类型
*/
codeListType?: string;
/**
* @description 上下文
*/
contextProp?: IParam;
/**
* @description 视图参数
*/
viewParamsProp?: IParam;
/**
* @description 局部上下文
*/
localContext?: IParam;
/**
* @description 局部视图参数
*/
localParam?: IParam;
}
const props = withDefaults(defineProps<SpanProps>(), {
unitName: "",
precision: 2,
});
const { navContext, navViewParam } = handleEditorNavParams(props);
let text: Ref<string> = ref("");
let textFormat: Ref<string> = ref("");
onBeforeMount(() => {
if (props.codeListTag) {
loadCodeListData(
props.codeListTag,
props.codeListType,
navContext,
navViewParam
).then((codeListData: IParam[]) => {
const item: IParam | undefined = codeListData.find((item) =>
Object.is(item.value, props.value)
);
if (item) {
text.value = item.label;
} else {
text.value = props.value;
}
});
} else {
text.value = props.value;
}
if (props.valueFormat) {
textFormat.value = props.valueFormat;
} else if (
Object.is(props.dataType, "DATETIME") ||
Object.is(props.dataType, "DATE") ||
Object.is(props.dataType, "TIME") ||
Object.is(props.dataType, "SMALLDATETIME")
) {
textFormat.value = "YYYY-MM-DD HH:mm:ss";
} else if (Object.is(props.dataType, "NUMBER")) {
textFormat.value = `#${props.unitName}`;
}
});
</script>
<template>
<div :class="['app-editor-container', `app-span-${name}`]">
<span></span>
</div>
</template>
<style scoped>
.app-editor-container {
width: fit-content;
}
</style>
export {} import AppInput from './app-input.vue';
\ No newline at end of file import AppDropdownList from './app-dropdown-list.vue';
import AppSpan from './app-span.vue';
export {
AppInput,
AppDropdownList,
AppSpan,
}
\ No newline at end of file
import { IContext, IParam } from '@ibiz-core';
import { Ref } from 'vue'; import { Ref } from 'vue';
import { deepCopy } from '../../utils'; import { deepCopy } from '../../utils';
...@@ -50,4 +51,39 @@ export function toOneWayRef<T extends object, K extends keyof T>(object: Ref<T> ...@@ -50,4 +51,39 @@ export function toOneWayRef<T extends object, K extends keyof T>(object: Ref<T>
return propertyRef; return propertyRef;
} }
/**
* @description 使用上下文参数逻辑块
* @export
* @param {Record<any, any>} props
*/
export function useContextParams(props: Record<any, any>) {
const { contextProp, viewParamsProp } = toRefs(props);
// 维护上下文并监控其变化
const context: Ref<IContext> = ref({});
watch(
contextProp,
(newVal: any, oldVal: any) => {
context.value = deepCopy(newVal || {});
},
{
immediate: true,
deep: true,
}
);
// 维护视图参数并监控其变化
const viewParams: Ref<IParam> = ref({});
watch(
viewParamsProp,
(newVal: any, oldVal: any) => {
viewParams.value = deepCopy(newVal || {});
},
{
immediate: true,
deep: true,
}
);
return { context, viewParams };
}
import { toRefs } from "vue";
import { IParam } from "@ibiz-core";
import { computedNavData, useContextParams } from "@ibiz-core";
/**
* @description 处理编辑器导航数据(查询代码表)
* @export
* @param {Record<string, any>} props 编辑器输入属性
* @return {*}
*/
export function handleEditorNavParams(props: Record<string, any>) {
const { localContext, localParam, data } = toRefs(props);
const { context, viewParams } = useContextParams(props);
const navParams = {
navContext: context.value,
navViewParam: viewParams.value,
}
if (localContext && Object.keys(localContext).length > 0) {
const _context = computedNavData(data, navParams.navContext, navParams.navViewParam, localContext);
Object.assign(navParams.navContext, _context);
}
if (localParam && Object.keys(localParam).length > 0) {
const _param = computedNavData(data, navParams.navContext, navParams.navViewParam, localParam);
Object.assign(navParams.navViewParam, _param);
}
return navParams;
}
/**
* @description 加载代码表数据
* @export
* @param {string} codeListTag 代码表标识
* @param {string} codeListType 代码表类型
* @param {IParam} navContext 导航上下文
* @param {IParam} navViewParam 导航视图参数
* @param {boolean} isNumber 是否为数值类型
* @return {Promise<any[]>} {any[]}
*/
export async function loadCodeListData(codeListTag?: string, codeListType?: string, navContext?: IParam, navViewParam?: IParam): Promise<IParam[]> {
const data: IParam[] = [
{
value: '243144',
label: 'Jack',
},
{
value: '7dawda',
label: 'Lucy',
},
{
value: 'disaweqeqeqbled',
label: 'Disabled',
disabled: true,
},
{
value: 'yimirwqrqwenghe',
label: 'Yiminghe',
}
];
if (codeListTag) {
// todo 调用代码表服务获取数据
}
return data;
}
/**
* @description 处理层级代码表
* @export
* @param {IParam[]} codeListData 代码表数据
*/
export function handleLevelCodeList(codeListData: IParam[]): IParam[] {
let items: IParam[] = [...codeListData]
const hasChildren: boolean = codeListData.some((item:any) =>{
return item.pvalue;
})
if(hasChildren){
let list: IParam[] = [];
items.forEach((codeItem: IParam) =>{
if(!codeItem.pvalue){
let valueField: string = codeItem.value;
setChildCodeItems(valueField, items, codeItem);
list.push(codeItem);
}
})
items = list;
}
return items;
}
/**
* @description 设置子代码表
* @param {string} pValue 父代码项值
* @param {IParam[]} result 代码表
* @param {IParam} codeItem 代码项
*/
function setChildCodeItems(pValue: string, result: IParam[], codeItem: IParam) {
result.forEach((item: IParam) =>{
if(item.pvalue == pValue){
let valueField:string = item.value;
setChildCodeItems(valueField, result, item);
if(!codeItem.options){
codeItem.children = [];
}
codeItem.children.push(item);
}
})
}
/**
* @description 打开选择视图
* @export
*/
export function openPickUpView() {
//todo
}
/**
* @description 打开链接视图
* @export
*/
export function openLinkView() {
//todo
}
/**
* @description 获取文件上传路径
* @export
* @return {*} {string}
*/
export function getUploadUrl(): string {
//todo 环境参数
// return AppServiceBase.getInstance().getAppEnvironment().BaseUrl + AppServiceBase.getInstance().getAppEnvironment().UploadFile;
return "";
}
/**
* @description 获取文件上传路径
* @export
* @return {*} {string}
*/
export function getDownloadUrl(): string {
//todo 环境参数
// return AppServiceBase.getInstance().getAppEnvironment().ExportFile;
return "";
}
/**
* @description 获取文件请求头
* @export
* @return {*} {IParam}
*/
export function getRequestingHeader(): IParam {
//todo 请求头
// if (AppServiceBase.getInstance().getAppEnvironment().SaaSMode) {
// let activeOrgData = getSessionStorage('activeOrgData');
// this.headers['srforgid'] = activeOrgData?.orgid;
// this.headers['srfsystemid'] = activeOrgData?.systemid;
// if(getSessionStorage("srfdynaorgid")){
// this.headers['srfdynaorgid'] = getSessionStorage("srfdynaorgid");
// }
// } else {
// if(getSessionStorage("srfdynaorgid")){
// this.headers['srfdynaorgid'] = getSessionStorage("srfdynaorgid");
// }
// }
// if (getCookie('ibzuaa-token')) {
// this.headers['Authorization'] = `Bearer ${getCookie('ibzuaa-token')}`;
// } else {
// // 第三方应用打开免登
// if (sessionStorage.getItem("srftoken")) {
// const token = sessionStorage.getItem('srftoken');
// this.headers['Authorization'] = `Bearer ${token}`;
// }
// }
return {};
}
export * from './common' export * from './common'
export * from './views' export * from './views'
export * from './widgets' export * from './widgets'
\ No newline at end of file export * from './editor'
\ No newline at end of file
import { clone } from 'ramda'; export * from './util';
export * from './view-util';
/** \ No newline at end of file
* 克隆方法
* @param {Record<any, any>} data
* @return {*} {Record<any, any>}
*/
export function deepCopy(data: Record<any, any>): Record<any, any> {
return clone(data);
}
/**
* 除undefined,null,NaN以外都为true
* @param {*} arg
* @return {*} {boolean}
*/
export function hasValue(arg: any): boolean {
return arg !== undefined && arg !== null && arg === arg;
}
/**
* 判断是否是对象
* @param val
* @return {*}
*/
export function isObject(val: any) {
return val !== null && typeof val === 'object';
}
import { clone } from "ramda";
/**
* @description 克隆方法
* @export
* @param {Record<any, any>} data
* @return {*} {Record<any, any>}
*/
export function deepCopy(data: Record<any, any>): Record<any, any>{
return clone(data)
}
/**
* @description 除undefined,null,NaN以外都为true
* @export
* @param {*} arg
* @return {*} {boolean}
*/
export function hasValue(arg: any): boolean{
return arg !== undefined && arg !== null && arg === arg;
}
/**
* @description 获取当前数据值类型
* @export
* @param {*} obj 当前数据
* @return {*} {string}
*/
export function typeOf(obj: any): string {
const toString = Object.prototype.toString;
const map: any = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object',
};
return map[toString.call(obj)];
}
/**
* @description 校验值
* @param {*} value 值
* @param {*} op 校验条件
* @param {*} value2 对比值
* @return {*} {boolean}
*/
export function verifyValue(value: any, op: any, value2: any): boolean {
// 等于操作
if (Object.is(op, 'EQ')) {
const _value = `${value}`;
return _value === value2;
}
// 大于操作
if (Object.is(op, 'GT')) {
const result: number = compare(value, value2);
if (result !== undefined && result > 0) {
return true;
} else {
return false;
}
}
// 大于等于操作
if (Object.is(op, 'GTANDEQ')) {
const result: number = compare(value, value2);
if (result !== undefined && result >= 0) {
return true;
} else {
return false;
}
}
// 值包含在给定的范围中
if (Object.is(op, 'IN')) {
return contains(value, value2);
}
// 不为空判断操作
if (Object.is(op, 'ISNOTNULL')) {
return value != null && value !== '';
}
// 为空判断操作
if (Object.is(op, 'ISNULL')) {
return value == null || value === '';
}
// 文本左包含
if (Object.is(op, 'LEFTLIKE')) {
return value && value2 && value.toUpperCase().indexOf(value2.toUpperCase()) === 0;
}
// 文本包含
if (Object.is(op, 'LIKE')) {
return value && value2 && value.toUpperCase().indexOf(value2.toUpperCase()) !== -1;
}
// 小于操作
if (Object.is(op, 'LT')) {
const result: number = compare(value, value2);
if (result !== undefined && result < 0) {
return true;
} else {
return false;
}
}
// 小于等于操作
if (Object.is(op, 'LTANDEQ')) {
const result: number = compare(value, value2);
if (result !== undefined && result <= 0) {
return true;
} else {
return false;
}
}
// 不等于操作
if (Object.is(op, 'NOTEQ')) {
const _value = `${value}`;
return _value !== value2;
}
// 值不包含在给定的范围中
if (Object.is(op, 'NOTIN')) {
return !contains(value, value2);
}
// 文本右包含
if (Object.is(op, 'RIGHTLIKE')) {
if (!(value && value2)) {
return false;
}
const nPos = value.toUpperCase().indexOf(value2.toUpperCase());
if (nPos === -1) {
return false;
}
return nPos + value2.length === value.length;
}
return false;
}
/**
* @description 比较值
* @param {*} value 值1
* @param {*} value2 值2
* @return {*} {number}
*/
function compare(value: any, value2: any): number {
let result: any;
if (!Object.is(value, '') && !Object.is(value2, '') && !isNaN(value) && !isNaN(value2)) {
result = compareNumber(parseFloat(value), parseFloat(value2));
} else if (isParseDate(value) && isParseDate(value2)) {
result = compareDate(new Date(value).getTime(), new Date(value2).getTime());
} else if (value && (typeof value === 'boolean' || value instanceof Boolean)) {
result = compareBoolean(value, value2);
} else if (value && (typeof value === 'string' || value instanceof String)) {
result = compareString(value, value2);
}
return result;
}
/**
* @description 比较数值
* @param {number} value 值1
* @param {number} value2 值2
* @return {*} {number}
*/
function compareNumber(value: number, value2: number): number {
if (isNaN(value)) {
value = 0;
}
if (isNaN(value2)) {
value2 = 0;
}
if (value > value2) {
return 1;
} else if (value < value2) {
return -1;
} else {
return 0;
}
}
/**
* @description 判断值是否是时间
* @param {string} value 值
* @return {*} {boolean}
*/
function isParseDate(value: string): boolean {
const time = new Date(value);
if (isNaN(time.getTime())) {
return false;
}
return true;
}
/**
* @description 比较时间
* @param {number} value 值1
* @param {number} value2 值2
* @return {*} {number}
*/
function compareDate(value: number, value2: number): number {
if (value > value2) {
return 1;
} else if (value < value2) {
return -1;
} else {
return 0;
}
}
/**
* @description 比较布尔值
* @param {*} value 值1
* @param {*} value2 值2
* @return {*} {number}
*/
function compareBoolean(value: any, value2: any): number {
if (value === value2) {
return 0;
} else {
return -1;
}
}
/**
* @description 比较字符串
* @param {*} value 值1
* @param {*} value2 值2
* @return {*} {number}
*/
function compareString(value: any, value2: any): number {
return value.localeCompare(value2);
}
/**
* @description 文本包含
* @param {*} value 值1
* @param {*} value2 值2
* @return {*} {boolean}
*/
function contains(value: any, value2: any): boolean {
if (value && value2) {
let arr = [];
arr = value2.split(',');
const S = String.fromCharCode(2);
const reg = new RegExp(S + value + S);
return reg.test(S + arr.join(S) + S);
}
return false;
}
\ No newline at end of file
import { IParam } from "@ibiz-core";
/**
* @description 计算界面行为项权限状态
* @export
* @param {IParam} data 传入数据
* @param {IParam} actionModel 界面行为模型
* @param {*} UIService 界面行为服务
* @return {*}
*/
export function calcActionItemAuthState(data: IParam, actionModel: IParam, UIService: any) {
const result: any[] = [];
if (!UIService) return;
for (const key in actionModel) {
if (!actionModel.hasOwnProperty(key)) {
return result;
}
const item = actionModel[key];
let dataActionResult: any;
if (item && item['dataAccessAction']) {
if (Object.is(item['actionTarget'], 'NONE') || Object.is(item['actionTarget'], '')) {
dataActionResult = UIService.getAllOPPrivs({}, item['dataAccessAction']);
} else {
if (data && Object.keys(data).length > 0) {
dataActionResult = UIService.getAllOPPrivs(data, item['dataAccessAction']);
}
}
} else {
dataActionResult = 1;
}
// 无权限:0;有权限:1
if (dataActionResult === 0) {
// 禁用:1;隐藏:2;隐藏且默认隐藏:6
if (item.getNoPrivDisplayMode === 1) {
item.disabled = true;
}
if (item.getNoPrivDisplayMode === 2 || item.getNoPrivDisplayMode === 6) {
item.visabled = false;
} else {
item.visabled = true;
}
}
if (dataActionResult === 1) {
item.visabled = true;
item.disabled = false;
}
// 返回权限验证的结果
item.dataActionResult = dataActionResult;
result.push(dataActionResult);
}
return result;
}
/**
* @description 计算导航数据
* 先从当前数据目标计算,然后再从当前上下文计算,最后从当前视图参数计算,没有则为null
* @export
* @param {*} data 当前数据目标
* @param {*} parentContext 当前上下文
* @param {*} parentParam 当前视图参数
* @param {*} params 导航参数
* @return {*}
*/
export function computedNavData(data: any, parentContext: any, parentParam: any, params: any): any {
const _data: any = {};
if (params && Object.keys(params).length > 0) {
Object.keys(params).forEach((name: string) => {
if (!name) {
return;
}
let value: string | null = params[name];
if (value && value.toString().startsWith('%') && value.toString().endsWith('%')) {
const key = value.substring(1, value.length - 1).toLowerCase();
if (data && data.hasOwnProperty(key)) {
value = data[key];
} else if (parentContext && parentContext[key]) {
value = parentContext[key];
} else if (parentParam && parentParam[key]) {
value = parentParam[key];
} else {
value = null;
}
}
Object.assign(_data, { [name.toLowerCase()]: value });
});
}
return _data;
}
\ No newline at end of file
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册