forked from wangjiadong/comp
parent
85aea7bc2a
commit
b1843653bc
3 changed files with 262 additions and 0 deletions
@ -0,0 +1,69 @@ |
|||||||
|
<template> |
||||||
|
<BasicModal v-bind="$attrs" title="配置路径"> |
||||||
|
<a-directory-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys" multiple |
||||||
|
:tree-data="treeData"></a-directory-tree> |
||||||
|
</BasicModal> |
||||||
|
</template> |
||||||
|
<script lang="ts" setup> |
||||||
|
import { BasicModal } from '/@/components/Modal'; |
||||||
|
|
||||||
|
|
||||||
|
// tree |
||||||
|
|
||||||
|
import type { TreeProps } from 'ant-design-vue'; |
||||||
|
import { ref } from 'vue'; |
||||||
|
|
||||||
|
const expandedKeys = ref<string[]>(['0-0', '0-1']); |
||||||
|
const selectedKeys = ref<string[]>([]); |
||||||
|
const treeData: TreeProps['treeData'] = [ |
||||||
|
{ |
||||||
|
title: 'C:\\', |
||||||
|
key: '0-0', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
title: 'leaf 0-0', |
||||||
|
key: '0-0-0', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
title: 'child:\\', |
||||||
|
key: '0-0-0-0', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
title: 'leaf 0-0', |
||||||
|
key: '0-0-0-0-0', |
||||||
|
isLeaf: true, |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'leaf 0-1', |
||||||
|
key: '0-0-0-0-1', |
||||||
|
isLeaf: true, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'leaf 0-1', |
||||||
|
key: '0-0-1', |
||||||
|
isLeaf: true, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'parent 1', |
||||||
|
key: '0-1', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
title: 'leaf 1-0', |
||||||
|
key: '0-1-0', |
||||||
|
isLeaf: true, |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'leaf 1-1', |
||||||
|
key: '0-1-1', |
||||||
|
isLeaf: true, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
]; |
||||||
|
</script> |
@ -0,0 +1,37 @@ |
|||||||
|
<script setup lang="ts"> |
||||||
|
import { ref } from 'vue'; |
||||||
|
import { h } from 'vue'; |
||||||
|
import { FolderOpenOutlined } from '@ant-design/icons-vue'; |
||||||
|
const value = ref() |
||||||
|
|
||||||
|
const browseFolder = async () => { |
||||||
|
const FilSysDirHan = await showDirectoryPicker() |
||||||
|
processHandle(FilSysDirHan) |
||||||
|
console.log(FilSysDirHan); |
||||||
|
} |
||||||
|
async function processHandle(handle) { |
||||||
|
if (handle.kind === 'file') return |
||||||
|
const iter = await handle.entries() |
||||||
|
handle.children = [] |
||||||
|
for await (const entry of iter) { |
||||||
|
const subHan = entry[1] |
||||||
|
handle.children.push(subHan) |
||||||
|
processHandle(subHan) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<div class=""> |
||||||
|
<a-input v-model:value="value" placeholder="Basic usage" /> |
||||||
|
<a-button type="primary" :icon="h(FolderOpenOutlined)" @click="browseFolder">浏览</a-button> |
||||||
|
<a-input-search placeholder="input search text" size="large"> |
||||||
|
<template #enterButton> |
||||||
|
<a-button :icon="h(FolderOpenOutlined)">浏览</a-button> |
||||||
|
</template> |
||||||
|
</a-input-search> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,156 @@ |
|||||||
|
<template> |
||||||
|
<a-form ref="formRef" name="custom-validation" :model="formState" v-bind="layout" @finish="handleFinish" |
||||||
|
@validate="handleValidate" @finishFailed="handleFinishFailed"> |
||||||
|
<a-form-item class="h-item" has-feedback label="作品上传路径" name="pass"> |
||||||
|
<a-input v-model:value="formState.pass" type="password" autocomplete="off" /> |
||||||
|
<a-button :icon="h(FolderOpenOutlined)" @click="openModal(true, {})">浏览</a-button> |
||||||
|
</a-form-item> |
||||||
|
<a-form-item class="h-item" has-feedback label="比赛证书上传路径" name="checkPass"> |
||||||
|
<a-input v-model:value="formState.checkPass" type="password" autocomplete="off" /> |
||||||
|
<a-button :icon="h(FolderOpenOutlined)" @click="openModal(true, {})">浏览</a-button> |
||||||
|
</a-form-item> |
||||||
|
<a-form-item label="需要配置的标题" name="title"> |
||||||
|
<a-input v-model:value="formState.title" /> |
||||||
|
</a-form-item> |
||||||
|
<a-form-item has-feedback label="LOGO" name="age"> |
||||||
|
<div class="clearfix"> |
||||||
|
<a-upload v-model:file-list="fileList" action="https://www.mocky.io/v2/5cc8019d300000980a055e76" |
||||||
|
list-type="picture-card" @preview="handlePreview"> |
||||||
|
<div v-if="fileList.length < 8"> |
||||||
|
<plus-outlined /> |
||||||
|
<div style="margin-top: 8px">Upload</div> |
||||||
|
</div> |
||||||
|
</a-upload> |
||||||
|
<a-modal :open="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel"> |
||||||
|
<img alt="example" style="width: 100%" :src="previewImage" /> |
||||||
|
</a-modal> |
||||||
|
</div> |
||||||
|
</a-form-item> |
||||||
|
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> |
||||||
|
<a-button type="primary" html-type="submit">Submit</a-button> |
||||||
|
</a-form-item> |
||||||
|
</a-form> |
||||||
|
<div class="px-10"> |
||||||
|
<Modal @register="register" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script lang="ts" setup> |
||||||
|
import { useModal } from '/@/components/Modal'; |
||||||
|
import Modal from './Modal.vue'; |
||||||
|
|
||||||
|
import { PlusOutlined } from '@ant-design/icons-vue'; |
||||||
|
import type { UploadProps } from 'ant-design-vue'; |
||||||
|
|
||||||
|
import { FolderOpenOutlined } from '@ant-design/icons-vue'; |
||||||
|
import { reactive, ref, h } from 'vue'; |
||||||
|
import type { Rule } from 'ant-design-vue/es/form'; |
||||||
|
import type { FormInstance } from 'ant-design-vue'; |
||||||
|
interface FormState { |
||||||
|
pass: string; |
||||||
|
checkPass: string; |
||||||
|
age: number | undefined; |
||||||
|
title: string; |
||||||
|
} |
||||||
|
const formRef = ref<FormInstance>(); |
||||||
|
const formState = reactive<FormState>({ |
||||||
|
pass: '', |
||||||
|
checkPass: '', |
||||||
|
age: undefined, |
||||||
|
title: '' |
||||||
|
}); |
||||||
|
const checkAge = async (_rule: Rule, value: number) => { |
||||||
|
if (!value) { |
||||||
|
return Promise.reject('Please input the age'); |
||||||
|
} |
||||||
|
if (!Number.isInteger(value)) { |
||||||
|
return Promise.reject('Please input digits'); |
||||||
|
} else { |
||||||
|
if (value < 18) { |
||||||
|
return Promise.reject('Age must be greater than 18'); |
||||||
|
} else { |
||||||
|
return Promise.resolve(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
const validatePass = async (_rule: Rule, value: string) => { |
||||||
|
if (value === '') { |
||||||
|
return Promise.reject('Please input the password'); |
||||||
|
} else { |
||||||
|
if (formState.checkPass !== '') { |
||||||
|
formRef.value.validateFields('checkPass'); |
||||||
|
} |
||||||
|
return Promise.resolve(); |
||||||
|
} |
||||||
|
}; |
||||||
|
const validatePass2 = async (_rule: Rule, value: string) => { |
||||||
|
if (value === '') { |
||||||
|
return Promise.reject('Please input the password again'); |
||||||
|
} else if (value !== formState.pass) { |
||||||
|
return Promise.reject("Two inputs don't match!"); |
||||||
|
} else { |
||||||
|
return Promise.resolve(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const layout = { |
||||||
|
labelCol: { span: 4 }, |
||||||
|
wrapperCol: { span: 14 }, |
||||||
|
}; |
||||||
|
const handleFinish = (values: FormState) => { |
||||||
|
console.log(values, formState); |
||||||
|
}; |
||||||
|
const handleFinishFailed = errors => { |
||||||
|
console.log(errors); |
||||||
|
}; |
||||||
|
const resetForm = () => { |
||||||
|
formRef.value.resetFields(); |
||||||
|
}; |
||||||
|
const handleValidate = (...args) => { |
||||||
|
console.log(args); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// LOGO upload |
||||||
|
function getBase64(file: File) { |
||||||
|
return new Promise((resolve, reject) => { |
||||||
|
const reader = new FileReader(); |
||||||
|
reader.readAsDataURL(file); |
||||||
|
reader.onload = () => resolve(reader.result); |
||||||
|
reader.onerror = error => reject(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
const previewVisible = ref(false); |
||||||
|
const previewImage = ref(''); |
||||||
|
const previewTitle = ref(''); |
||||||
|
|
||||||
|
const fileList = ref<UploadProps['fileList']>([]); |
||||||
|
|
||||||
|
const handleCancel = () => { |
||||||
|
previewVisible.value = false; |
||||||
|
previewTitle.value = ''; |
||||||
|
}; |
||||||
|
const handlePreview = async (file: UploadProps['fileList'][number]) => { |
||||||
|
if (!file.url && !file.preview) { |
||||||
|
file.preview = (await getBase64(file.originFileObj)) as string; |
||||||
|
} |
||||||
|
previewImage.value = file.url || file.preview; |
||||||
|
previewVisible.value = true; |
||||||
|
previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// 弹窗 |
||||||
|
const [register, { openModal }] = useModal(); |
||||||
|
</script> |
||||||
|
<style scoped lang="less"> |
||||||
|
.h-item { |
||||||
|
.ant-input { |
||||||
|
width: 90%; |
||||||
|
} |
||||||
|
|
||||||
|
.ant-btn { |
||||||
|
width: 10%; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
Loading…
Reference in new issue