mirror of
https://gh-proxy.org/https://github.com/klinsmaya/yudao-ui-admin-vben.git
synced 2026-11-08 01:16:57 +08:00
@@ -3,6 +3,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
|
||||
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { isServerHost } from '@vben/utils';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
|
||||
@@ -94,7 +95,10 @@ function useConnectionFormSchema(
|
||||
componentProps: {
|
||||
placeholder: '请输入服务器域名',
|
||||
},
|
||||
rules: 'required',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, '请输入服务器域名')
|
||||
.refine(isServerHost, '请输入有效的服务器域名或 IP 地址'),
|
||||
},
|
||||
{
|
||||
fieldName: `${protocol}.port`,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { computed, nextTick, ref, watch } from 'vue';
|
||||
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { formatDateTime } from '@vben/utils';
|
||||
import { cloneDeep, formatDateTime, isEqual } from '@vben/utils';
|
||||
|
||||
import { Button, DatePicker, Input, InputNumber, Select } from 'ant-design-vue';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -72,34 +72,39 @@ async function reloadData() {
|
||||
await gridApi.grid?.reloadData(tableData.value);
|
||||
}
|
||||
|
||||
/** 监听外部传入的明细数据,同引用回写时跳过重载 */
|
||||
/** 表单值可能只读,使用独立副本编辑;同值回写时不重载表格 */
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (items) => {
|
||||
const next = items ?? [];
|
||||
const unchanged =
|
||||
next.length === tableData.value.length &&
|
||||
next.every((item, index) => item === tableData.value[index]);
|
||||
if (unchanged) {
|
||||
if (isEqual(next, tableData.value)) {
|
||||
return;
|
||||
}
|
||||
tableData.value = [...next];
|
||||
tableData.value = cloneDeep(next);
|
||||
await reloadData();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
tableData,
|
||||
(items) => {
|
||||
if (!isEqual(items, props.modelValue)) {
|
||||
emit('update:modelValue', cloneDeep(items));
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
/** 新增费用明细 */
|
||||
async function handleAdd() {
|
||||
tableData.value.push({ invoiceCount: 0, price: 0 });
|
||||
emit('update:modelValue', [...tableData.value]);
|
||||
await reloadData();
|
||||
}
|
||||
|
||||
/** 删除费用明细 */
|
||||
async function handleDelete(index: number) {
|
||||
tableData.value.splice(index, 1);
|
||||
emit('update:modelValue', [...tableData.value]);
|
||||
await reloadData();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { OaSupplyItemApi } from '#/api/oa/supply/item';
|
||||
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
|
||||
@@ -111,12 +109,8 @@ function handleSelect(item: OaSupplyItemApi.SupplyItem) {
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
showConfirmButton: false,
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
// 打开时重置搜索并重新查询
|
||||
await nextTick();
|
||||
async onOpened() {
|
||||
// 表格挂载后重置搜索并重新查询
|
||||
await gridApi.formApi.reset();
|
||||
gridApi.query();
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
|
||||
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { isServerHost } from '@vben/utils';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
|
||||
@@ -94,7 +95,10 @@ function useConnectionFormSchema(
|
||||
componentProps: {
|
||||
placeholder: '请输入服务器域名',
|
||||
},
|
||||
rules: 'required',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, '请输入服务器域名')
|
||||
.refine(isServerHost, '请输入有效的服务器域名或 IP 地址'),
|
||||
},
|
||||
{
|
||||
fieldName: `${protocol}.port`,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { computed, nextTick, ref, watch } from 'vue';
|
||||
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { formatDateTime } from '@vben/utils';
|
||||
import { cloneDeep, formatDateTime, isEqual } from '@vben/utils';
|
||||
|
||||
import { Button, DatePicker, Input, InputNumber, Select } from 'antdv-next';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -72,34 +72,39 @@ async function reloadData() {
|
||||
await gridApi.grid?.reloadData(tableData.value);
|
||||
}
|
||||
|
||||
/** 监听外部传入的明细数据,同引用回写时跳过重载 */
|
||||
/** 表单值可能只读,使用独立副本编辑;同值回写时不重载表格 */
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (items) => {
|
||||
const next = items ?? [];
|
||||
const unchanged =
|
||||
next.length === tableData.value.length &&
|
||||
next.every((item, index) => item === tableData.value[index]);
|
||||
if (unchanged) {
|
||||
if (isEqual(next, tableData.value)) {
|
||||
return;
|
||||
}
|
||||
tableData.value = [...next];
|
||||
tableData.value = cloneDeep(next);
|
||||
await reloadData();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
tableData,
|
||||
(items) => {
|
||||
if (!isEqual(items, props.modelValue)) {
|
||||
emit('update:modelValue', cloneDeep(items));
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
/** 新增费用明细 */
|
||||
async function handleAdd() {
|
||||
tableData.value.push({ invoiceCount: 0, price: 0 });
|
||||
emit('update:modelValue', [...tableData.value]);
|
||||
await reloadData();
|
||||
}
|
||||
|
||||
/** 删除费用明细 */
|
||||
async function handleDelete(index: number) {
|
||||
tableData.value.splice(index, 1);
|
||||
emit('update:modelValue', [...tableData.value]);
|
||||
await reloadData();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { OaSupplyItemApi } from '#/api/oa/supply/item';
|
||||
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
|
||||
@@ -111,12 +109,8 @@ function handleSelect(item: OaSupplyItemApi.SupplyItem) {
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
showConfirmButton: false,
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
// 打开时重置搜索并重新查询
|
||||
await nextTick();
|
||||
async onOpened() {
|
||||
// 表格挂载后重置搜索并重新查询
|
||||
await gridApi.formApi.reset();
|
||||
gridApi.query();
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
|
||||
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { isServerHost } from '@vben/utils';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
|
||||
@@ -94,7 +95,10 @@ function useConnectionFormSchema(
|
||||
componentProps: {
|
||||
placeholder: '请输入服务器域名',
|
||||
},
|
||||
rules: 'required',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, '请输入服务器域名')
|
||||
.refine(isServerHost, '请输入有效的服务器域名或 IP 地址'),
|
||||
},
|
||||
{
|
||||
fieldName: `${protocol}.port`,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { computed, nextTick, ref, watch } from 'vue';
|
||||
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { formatDateTime } from '@vben/utils';
|
||||
import { cloneDeep, formatDateTime, isEqual } from '@vben/utils';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
@@ -76,34 +76,39 @@ async function reloadData() {
|
||||
await gridApi.grid?.reloadData(tableData.value);
|
||||
}
|
||||
|
||||
/** 监听外部传入的明细数据,同引用回写时跳过重载 */
|
||||
/** 表单值可能只读,使用独立副本编辑;同值回写时不重载表格 */
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (items) => {
|
||||
const next = items ?? [];
|
||||
const unchanged =
|
||||
next.length === tableData.value.length &&
|
||||
next.every((item, index) => item === tableData.value[index]);
|
||||
if (unchanged) {
|
||||
if (isEqual(next, tableData.value)) {
|
||||
return;
|
||||
}
|
||||
tableData.value = [...next];
|
||||
tableData.value = cloneDeep(next);
|
||||
await reloadData();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
tableData,
|
||||
(items) => {
|
||||
if (!isEqual(items, props.modelValue)) {
|
||||
emit('update:modelValue', cloneDeep(items));
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
/** 新增费用明细 */
|
||||
async function handleAdd() {
|
||||
tableData.value.push({ invoiceCount: 0, price: 0 });
|
||||
emit('update:modelValue', [...tableData.value]);
|
||||
await reloadData();
|
||||
}
|
||||
|
||||
/** 删除费用明细 */
|
||||
async function handleDelete(index: number) {
|
||||
tableData.value.splice(index, 1);
|
||||
emit('update:modelValue', [...tableData.value]);
|
||||
await reloadData();
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -3,8 +3,6 @@ import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { OaSupplyItemApi } from '#/api/oa/supply/item';
|
||||
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
|
||||
@@ -111,12 +109,8 @@ function handleSelect(item: OaSupplyItemApi.SupplyItem) {
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
showConfirmButton: false,
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
// 打开时重置搜索并重新查询
|
||||
await nextTick();
|
||||
async onOpened() {
|
||||
// 表格挂载后重置搜索并重新查询
|
||||
await gridApi.formApi.reset();
|
||||
gridApi.query();
|
||||
},
|
||||
|
||||
@@ -14,3 +14,35 @@ function isMobile(value?: null | string): boolean {
|
||||
}
|
||||
|
||||
export { isMobile };
|
||||
|
||||
/** 校验服务器主机名或 IP,不包含协议、路径和端口 */
|
||||
export function isServerHost(value?: null | string): boolean {
|
||||
if (!value || value.length > 253) return false;
|
||||
const ipv4 =
|
||||
/^(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)){3}$/;
|
||||
if (value.includes(':')) {
|
||||
let address = value;
|
||||
if (address.includes('.')) {
|
||||
const index = address.lastIndexOf(':');
|
||||
if (!ipv4.test(address.slice(index + 1))) return false;
|
||||
address = `${address.slice(0, index + 1)}0:0`;
|
||||
}
|
||||
const parts = address.split('::');
|
||||
if (
|
||||
parts.length > 2 ||
|
||||
!parts.every(
|
||||
(part) => part === '' || /^[\da-f]{1,4}(?::[\da-f]{1,4})*$/i.test(part),
|
||||
)
|
||||
)
|
||||
return false;
|
||||
const count = parts.reduce(
|
||||
(total, part) => total + (part ? part.split(':').length : 0),
|
||||
0,
|
||||
);
|
||||
return parts.length === 2 ? count < 8 : count === 8;
|
||||
}
|
||||
if (/^\d+(?:\.\d+){3}$/.test(value)) return ipv4.test(value);
|
||||
return /^[a-z\d](?:[a-z\d-]{0,61}[a-z\d])?(?:\.[a-z\d](?:[a-z\d-]{0,61}[a-z\d])?)*\.?$/i.test(
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user