搜索结果列表页面开发

This commit is contained in:
付民康
2025-03-12 18:41:20 +08:00
commit 7cebe8fc00
739 changed files with 88149 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
<script setup lang="ts">
import { reactive, ref, toRaw, watchEffect } from 'vue';
import { customEventList } from './customEventList';
import { useRouter } from 'vue-router';
import debounce from 'lodash/debounce';
import { urlRegExp } from '@/utils/regex';
const emits = defineEmits(['create', 'change']);
const nameMaxLen = 500;
const props = defineProps<{
data?: Record<string, any>;
editable?: boolean;
loading?: boolean;
}>();
const router = useRouter();
const formRef = ref<any>(null);
const form = reactive<Record<string, any>>({
url: '',
push_events: true,
tag_push_events: false,
merge_requests_events: false,
note_events: false,
content_type: 'application/json',
token: '',
active: true
});
const hookToken = ref('');
type WebHookEventKey = keyof typeof form
const contentTypeList = ref(['application/json', 'application/x-www-form-urlencoded']);
// const eventTypeList = shallowRef<{ key: WebHookEventKey, label: string }[]>([
// // {
// // key: 'all',
// // label: '全部事件'
// // },
// {
// key: 'push_events',
// label: '仅限 push 事件'
// },
// {
// key: 'custom_ctrl_item_events',
// label: '自定义事件'
// }
// ]);
const handleClick = async() => {
const valid = await formRef.value.validate();
if (valid) {
if (props?.editable) {
const { token, ...config } = toRaw(form);
if (token) {
emits('change', { token, ...config });
} else {
emits('change', config);
}
} else {
emits('create', toRaw(form));
}
}
};
const handleCancel = () => {
router.back();
};
const regex = /^[^\*\u4e00-\u9fa5\s]*$/;
const handleChange = (val: string) => {
if (props.editable) {
form.token = val;
}
};
const handleFocus = () => {
if (props.editable) {
if (!form.token) {
hookToken.value = '';
} else {
hookToken.value = form.token;
}
}
};
const handleBlur = () => {
if (props.editable) {
if (!form.token) {
hookToken.value = props?.data?.token ? '*'.repeat(props.data.token.length) : '********';
} else {
hookToken.value = form.token;
}
}
};
const handleInput = debounce((val: string) => {
if (val && formRef.value) {
form.token = val;
if (regex.test(val) && val.length <= 2000) {
formRef.value.clearValidate(['token']);
} else {
formRef.value.validateFields(['token']);
}
}
}, 500);
watchEffect(() => {
if (props.data) {
for (const key in form) {
if (key === 'token' && props.editable) {
form.token = '';
hookToken.value = props?.data?.token ? '*'.repeat(props.data.token.length) : '********';
} else {
form[key] = props.data[key];
}
}
}
});
function restricVal(event:any) {
let value = event.target.value;
if (event.type === 'paste') value = (event.clipboardData || (window as any).clipboardData).getData('text');
if (value.length < nameMaxLen) return;
form.url = value.slice(0, nameMaxLen);
event.preventDefault();
}
const formRules = { // 表单校验
url: [
{ required: true, message: '请填写WebHook的url信息', trigger: 'blur' },
{ max: nameMaxLen, message: 'WebHook的url信息长度不能超过500' },
{ message: '请输入正确的URL地址', pattern: urlRegExp },
],
content_type: [{ required: true, message: '请选择POST请求内容类型', trigger: 'blur' }],
token: [
{ required: !props.editable, message: '请输入Token', trigger: 'blur' },
{ message: 'Token不能包含中文、空格、*', pattern: regex },
{ max: 2000, message: 'WebHook的Token信息长度不能超过2000' }
]
};
</script>
<template>
<div class="web-hook-edit g-content-card p-20">
<d-form class="max-w-[900px]" :pop-position="['right']" :data="form" layout="vertical" ref="formRef" :rules="formRules">
<d-form-item field="url" label="URL">
<d-input maxlength="500" v-model="form.url" placeholder="请输入 WebHook 的 URL 地址" v-on:keypress="restricVal" v-on:paste="restricVal">
<template #suffix><span>{{form.url?.length}}/{{ nameMaxLen }}</span></template>
</d-input>
</d-form-item>
<d-form-item field="token" label="Token">
<div v-if="editable">
<div class="text-CG600 text-[14px] mb-[10px]">
如果你忘记了之前设置的Token, 你可以重新添加添加一个Token, 为避免影响正常使用, 请将所有应用到该Token的配置更新为最新的Token
</div>
<d-input maxlength="2000" placeholder="请输入Token" v-model="hookToken" @change="handleChange" @focus="handleFocus" @blur="handleBlur" @input="handleInput">
<template #suffix><span>{{hookToken?.length}}/2000</span></template>
</d-input>
</div>
<d-input maxlength="2000" placeholder="请输入Token" v-model="form.token" v-else>
<template #suffix><span>{{form.token?.length}}/2000</span></template>
</d-input>
</d-form-item>
<d-form-item field="content_type" class="no-label">
<div class="flex items-center">
<div class="text-G900 mr-[10px]">POST 请求内容类型</div>
<d-select
class="web-hook-select"
v-model="form.content_type"
:placeholder="form.content_type"
>
<gc-option v-for="(item,index) of contentTypeList.filter(name => name !== form.content_type)" :key="index" :value="item" :title="item">
<span>{{ item }}</span>
</gc-option>
</d-select>
</div>
</d-form-item>
<div class="my-[10px]">事件类型</div>
<div class="webhook-checkbox flex flex-wrap">
<d-checkbox class="my-[10px] w-[25%]" v-for="item of customEventList" :key="item.key" v-model="form[item.key as WebHookEventKey]">{{ item.title }}</d-checkbox>
</div>
<d-checkbox class="my-[10px]" v-model="form.active">
<span class="inline-block mr-[1px]">激活</span>
<span class="text-G600">当以上指定事件触发时将发送请求</span>
</d-checkbox>
<div class="flex items-center mt-5 justify-end">
<d-button class="mr-4 w-[64px]" @click="handleCancel"><span>取消</span></d-button>
<d-button variant="solid" :loading="loading" @click="handleClick">{{ editable ? '保存' : ' 创建' }}</d-button>
</div>
</d-form>
</div>
</template>
<style lang="scss">
.web-hook-edit {
.web-hook-select {
width: 320px;
input::placeholder {
color: var(--color-G900);
}
}
.webhook-checkbox {
.devui-checkbox label>span.devui-checkbox__label-text {
line-height: 18px;
}
}
.devui-form__item--vertical {
margin-bottom: 10px;
&:nth-of-type(3) {
.devui-form__label--vertical {
height: 0;
padding-bottom: 10px;
}
}
}
}
.no-label{
:deep(.devui-form__label){
display:none;
}
}
</style>

View File

@@ -0,0 +1,92 @@
export const customEventList = [
{
key: 'push_events',
title: '推送事件'
},
{
key: 'merge_requests_events',
title: 'Pull Request事件'
// desc: '合并请求请求事件包括合并请求的新建、分配负责人、取消负责人、关闭、转换成草稿WIP、新增 Label、移除 Label、新增里程碑、移除里程碑、重新打开事件'
},
{
key: 'tag_push_events',
title: 'Tag推送事件'
},
{
key: 'note_events',
title: '评论事件'
// desc: '新建分支或新建 Tag'
}
// {
// title: '删除分支或 Tag',
// desc: '删除分支或删除 Tag'
// },
// {
// title: '保护分支更新',
// desc: '新增、删除或修改保护分支设置'
// },
// {
// title: 'Forks',
// desc: '项目的 Fork 事件'
// },
// {
// title: '项目成员更新',
// desc: '新增、移除项目成员,或项目成员权限变更'
// },
// {
// title: 'Star',
// desc: '项目新增 Star 或取消 Star'
// },
// {
// key: 'issues_events',
// title: 'Issues',
// desc: 'Issues 事件,包括 Issue 的新增,编辑、删除、转移、置顶、取消置顶、关闭、重新打开、分配负责人、取消负责人、新增 Label、移除 Label、新增里程碑、移除里程碑、锁定和取消锁定事件'
// },
// {
// title: '提交评论',
// desc: '提交或 Diff 的评论事件'
// },
// {
// title: '里程碑',
// desc: '里程碑事件,包括里程碑的新增、关闭、打开、编辑和删除事件'
// },
// {
// title: '看板',
// desc: '新增、更新和删除看板'
// },
// {
// title: 'Pages',
// desc: 'Pages 站点更新'
// },
// {
// title: '看板事件',
// desc: '看板内容更新事件,包括新增、编辑、删除、归档、恢复、转换成 Issue 和排序'
// },
// {
// key: 'push_events',
// title: 'push 事件',
// desc: '代码库的 git push 事件'
// },
// {
// key: 'change_request_events',
// title: '合并请求评审状态事件',
// desc: '合并请求的代码评审事件(评审通过/不通过相关)'
// },
// {
// title: '代码评审评论',
// desc: '代码评审的评论事件'
// },
// {
// key: 'wiki_page_events',
// title: 'Wiki',
// desc: 'Wiki 更新'
// }
// {
// title: '项目导入',
// desc: '项目导入成功、失败或取消'
// },
// {
// title: '公开项目',
// desc: '项目由私密项目更改为公开项目'
// }
];