!31 Implements style、size and disabled states of button
Merge pull request !31 from cassiel/master
This commit is contained in:
commit
d33b163cf8
|
@ -20,3 +20,4 @@ dist-ssr
|
||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,7 @@
|
||||||
],
|
],
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"npmClient": "yarn"
|
"npmClient": "yarn",
|
||||||
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
|
"useNx": false
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@
|
||||||
"eslint-plugin-vue": "^9.4.0",
|
"eslint-plugin-vue": "^9.4.0",
|
||||||
"husky": "^8.0.0",
|
"husky": "^8.0.0",
|
||||||
"intersection-observer": "^0.12.2",
|
"intersection-observer": "^0.12.2",
|
||||||
"lerna": "^4.0.0",
|
"lerna": "^5.5.4",
|
||||||
"lint-staged": "^13.0.0",
|
"lint-staged": "^13.0.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"stylelint": "^14.11.0",
|
"stylelint": "^14.11.0",
|
||||||
|
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// This starter template is using Vue 3 <script setup> SFCs
|
// This starter template is using Vue 3 <script setup> SFCs
|
||||||
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||||
import HelloWorld from './components/HelloWorld.vue'
|
import HelloWorld from './components/HelloWorld.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
defineProps<{ msg: string }>();
|
defineProps<{ msg: string }>();
|
||||||
|
|
||||||
const count = ref(0)
|
const count = ref(0)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
defineProps<{ msg: string }>();
|
||||||
|
|
||||||
|
const count = ref(0)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<h1>{{ msg }}</h1>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<button type="button" @click="count++">count is {{ count }}</button>
|
||||||
|
<p>
|
||||||
|
Edit
|
||||||
|
<code>components/HelloWorld.vue</code> to test HMR
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Check out
|
||||||
|
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
||||||
|
>create-vue</a
|
||||||
|
>, the official Vue + Vite starter
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Install
|
||||||
|
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
|
||||||
|
in your IDE for a better DX
|
||||||
|
</p>
|
||||||
|
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.read-the-docs {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,7 +1,8 @@
|
||||||
/// <reference types="vite/client" />
|
// / <reference types="vite/client" />
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import type { DefineComponent } from 'vue'
|
import type { DefineComponent } from 'vue';
|
||||||
const component: DefineComponent<{}, {}, any>
|
|
||||||
export default component
|
const component: DefineComponent<{}, {}, any>;
|
||||||
|
export default component;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,308 @@
|
||||||
|
import { Component, OnInit, ViewChildren, ElementRef, Input, Output, EventEmitter, HostListener, ViewChild, forwardRef } from '@angular/core';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
import { NotifyService } from '@farris/ui-notify';
|
||||||
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
import { LocaleService } from '@farris/ui-locale';
|
||||||
|
|
||||||
|
export interface upImageFile {
|
||||||
|
size: number;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
lastModified?: string;
|
||||||
|
lastModifiedDate?: Date;
|
||||||
|
state?: string;
|
||||||
|
base64?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'farris-avatar',
|
||||||
|
templateUrl: './avatar.component.html',
|
||||||
|
styleUrls: ['./avatar.component.scss'],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: NG_VALUE_ACCESSOR,
|
||||||
|
useExisting: forwardRef(() => AvatarComponent),
|
||||||
|
multi: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AvatarComponent implements ControlValueAccessor, OnInit {
|
||||||
|
private defaultImgSrc = 'data:image/jpeg;base64,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'
|
||||||
|
private errorImgSrc = 'data:image/jpeg;base64,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';
|
||||||
|
public imgSrc;
|
||||||
|
// public fileBinary: string;
|
||||||
|
@ViewChild('file') file: ElementRef;
|
||||||
|
// @Input() cover = '';
|
||||||
|
tReadOnly: boolean = false;
|
||||||
|
@Input()
|
||||||
|
set readonly(value: boolean) {
|
||||||
|
if (value !== this.tReadOnly) {
|
||||||
|
let localeTitle = this.localeService.getValue('avatar.imgtitle');
|
||||||
|
this.imgtitle = value ? '' : (this.imgTitle ? this.imgTitle : localeTitle);
|
||||||
|
this.tReadOnly = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
get readonly(): boolean {
|
||||||
|
return this.tReadOnly;
|
||||||
|
}
|
||||||
|
// @Input() type;
|
||||||
|
@Input() size: number = 1;
|
||||||
|
@Input() imgTitle: string;
|
||||||
|
@Input() avatarWidth: number = 100;
|
||||||
|
@Input() avatarHeight: number = 100;
|
||||||
|
@Input() imgShape: string = 'circle';
|
||||||
|
imgtitle: string = '点击修改';
|
||||||
|
// @Input() isBase64:boolean = true;
|
||||||
|
@Output('imgChange') imgChange = new EventEmitter();
|
||||||
|
|
||||||
|
_type;
|
||||||
|
@Input()
|
||||||
|
set type(val) {
|
||||||
|
if (val && val.length) {
|
||||||
|
let types = val;
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
types = val.split(',');
|
||||||
|
}
|
||||||
|
if (types && types.length) {
|
||||||
|
this.currentImgType = [];
|
||||||
|
types.forEach(t => {
|
||||||
|
if ((typeof t == 'string') && t.constructor == String) {
|
||||||
|
let tImgtype = 'image/' + t;
|
||||||
|
if (t === 'jpg') {
|
||||||
|
let jpgType = 'image/jpeg';
|
||||||
|
this.currentImgType.push(jpgType);
|
||||||
|
}
|
||||||
|
this.currentImgType.push(tImgtype);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.currentImgType.length > 0) {
|
||||||
|
this.imgType = this.currentImgType.join(',')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get type() {
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
_cover;
|
||||||
|
@Input()
|
||||||
|
set cover(val) {
|
||||||
|
if (val) {
|
||||||
|
this._cover = val;
|
||||||
|
this.imgsrcInit(this.cover);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.imgSrc = this.defaultImgSrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get cover() {
|
||||||
|
return this._cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onChangeCallback: Function = () => { }
|
||||||
|
private onTouchedCallback: Function = () => { }
|
||||||
|
//是否加载中
|
||||||
|
loadingImg: boolean;
|
||||||
|
imgType = 'image/*';
|
||||||
|
imgFileObj: upImageFile;
|
||||||
|
currentImgType = ['image/image', 'image/webp', 'image/png', 'image/svg', 'image/gif', 'image/jpg', 'image/jpeg', 'image/bmp'];
|
||||||
|
constructor(private notifyService: NotifyService, public localeService: LocaleService) {
|
||||||
|
this.notifyService.config.position = 'top-center';
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
// if(this.cover){
|
||||||
|
// this.imgsrcInit(this.cover);
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// this.imgSrc = this.defaultImgSrc;
|
||||||
|
// }
|
||||||
|
if (this.readonly) {
|
||||||
|
this.imgtitle = '';
|
||||||
|
}
|
||||||
|
else if (this.imgTitle) {
|
||||||
|
this.imgtitle = this.imgTitle;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.imgtitle = this.localeService.getValue('avatar.imgtitle');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*判断cover数据格式,做出修改赋值给imgSrc
|
||||||
|
*/
|
||||||
|
imgsrcInit(val) {
|
||||||
|
let isImg = this.isSrc(val);
|
||||||
|
if (isImg) {
|
||||||
|
this.imgSrc = val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let isFullBase64 = this.isBaseSrc(val);
|
||||||
|
if (isFullBase64) {
|
||||||
|
this.imgSrc = val
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.imgSrc = this.addBase64(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('click')
|
||||||
|
onClick(): void {
|
||||||
|
if (this.readonly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(this.file.nativeElement as HTMLInputElement).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
getfiledata(event) {
|
||||||
|
if (this.readonly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const filetarget = event.target as HTMLInputElement;
|
||||||
|
let getfile = filetarget.files;
|
||||||
|
if (!getfile[0]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let fileType = getfile[0].type;
|
||||||
|
const isLtSize = getfile[0].size / 1024 / 1024 < this.size;
|
||||||
|
if (this.currentImgType.indexOf(fileType) < 0) {
|
||||||
|
let typeerrorText = this.localeService.getValue('avatar.typeError');
|
||||||
|
this.notifyService.error({
|
||||||
|
type: 'error',
|
||||||
|
title: '',
|
||||||
|
msg: typeerrorText
|
||||||
|
});
|
||||||
|
filetarget.value = '';
|
||||||
|
// this.notifyService.error('上传图片类型不正确');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLtSize) {
|
||||||
|
let sizeerrorText = this.localeService.getValue('avatar.sizeError');
|
||||||
|
let errormes: string = sizeerrorText + this.size + "M!";
|
||||||
|
this.notifyService.error({
|
||||||
|
type: 'error',
|
||||||
|
title: '',
|
||||||
|
msg: errormes
|
||||||
|
});
|
||||||
|
filetarget.value = '';
|
||||||
|
// this.notifyService.error(`上传图片不能大于${this.size}M!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.transformFile(getfile[0]);
|
||||||
|
filetarget.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public getImgFileObj() {
|
||||||
|
return this.imgFileObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
transformFile(getfile: any) {
|
||||||
|
// const subject = new Subject();
|
||||||
|
this.imgFileObj = {
|
||||||
|
size: getfile.size,
|
||||||
|
name: getfile.name,
|
||||||
|
type: getfile.type,
|
||||||
|
lastModified: getfile.lastModified,
|
||||||
|
lastModifiedDate: getfile.lastModifiedDate
|
||||||
|
}
|
||||||
|
this.do(getfile).subscribe(res => {
|
||||||
|
this.loadingImg = false;
|
||||||
|
if (res['state'] === 'done') {
|
||||||
|
this.imgSrc = res['result'];
|
||||||
|
|
||||||
|
//this.onChangeCallback(this.imgSrc);
|
||||||
|
this.onChangeCallback(this.removeBase64(this.imgSrc));
|
||||||
|
this.onTouchedCallback();
|
||||||
|
}
|
||||||
|
else if (res['state'] === 'error') {
|
||||||
|
let uploaderrorText = this.localeService.getValue('avatar.uploadError');
|
||||||
|
this.notifyService.error({
|
||||||
|
type: 'error',
|
||||||
|
title: '',
|
||||||
|
msg: uploaderrorText
|
||||||
|
})
|
||||||
|
// this.notifyService.error('图片上传失败,请重试!');
|
||||||
|
}
|
||||||
|
this.imgFileObj.state = res['state'];
|
||||||
|
this.imgFileObj.base64 = res['result'];
|
||||||
|
this.imgChange.emit(this.imgFileObj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
read(file: File): Observable<string> {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
//this.loadingImg = true;
|
||||||
|
// reader.onloadstart=function(){}
|
||||||
|
reader.onload = () => {
|
||||||
|
//console.log(reader.result);
|
||||||
|
observer.next({ state: 'done', 'result': reader.result });
|
||||||
|
observer.complete();
|
||||||
|
};
|
||||||
|
reader.onerror = function () {
|
||||||
|
observer.next({ state: 'error', 'result': reader.result });
|
||||||
|
observer.complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
do(file: any): Observable<string> {
|
||||||
|
return this.read(file as File);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeValue(val: any): void {
|
||||||
|
if (val && val.length) {
|
||||||
|
// if(this.isBase64){
|
||||||
|
// this.imgSrc = this.addBase64(val);
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// this.imgSrc = val;
|
||||||
|
// }
|
||||||
|
this.imgsrcInit(val);
|
||||||
|
}
|
||||||
|
else if (this.cover) {
|
||||||
|
this.imgsrcInit(this.cover);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.imgSrc = this.defaultImgSrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registerOnChange(fn: any): void {
|
||||||
|
this.onChangeCallback = fn;
|
||||||
|
}
|
||||||
|
registerOnTouched(fn: any): void {
|
||||||
|
this.onTouchedCallback = fn;
|
||||||
|
}
|
||||||
|
// setDisabledState?(isDisabled: boolean): void {
|
||||||
|
// this.disabled = isDisabled;
|
||||||
|
// }
|
||||||
|
|
||||||
|
addBase64(val) {
|
||||||
|
if (!val) return;
|
||||||
|
return 'data:image/jpeg;base64,' + val;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBase64(val) {
|
||||||
|
if (!val) return;
|
||||||
|
let img_arr = val.split(',');
|
||||||
|
if (img_arr.length) {
|
||||||
|
return img_arr[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//判断是否是图片路径
|
||||||
|
isSrc(url) {
|
||||||
|
return (url.match(/\.(jpeg|jpg|gif|png|svg|bmp|webp)$/) != null)
|
||||||
|
}
|
||||||
|
//判断是否是完成base64
|
||||||
|
isBaseSrc(url) {
|
||||||
|
return (url.indexOf('data:image/') > -1 ? true : false)
|
||||||
|
}
|
||||||
|
|
||||||
|
errorSrc() {
|
||||||
|
this.imgSrc = this.errorImgSrc;
|
||||||
|
this.imgtitle = this.localeService.getValue('avatar.loadError');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { AvatarProps } from '../avatar.props';
|
||||||
import { ImageFile } from './types';
|
import { ImageFile } from './types';
|
||||||
|
|
||||||
export function useFile(props: AvatarProps, context: SetupContext, allowTypes: string[]) {
|
export function useFile(props: AvatarProps, context: SetupContext, allowTypes: string[]) {
|
||||||
|
|
||||||
function getFileData($event: Event) {
|
function getFileData($event: Event) {
|
||||||
if (props.readonly) {
|
if (props.readonly) {
|
||||||
return;
|
return;
|
||||||
|
@ -89,4 +90,5 @@ export function useFile(props: AvatarProps, context: SetupContext, allowTypes: s
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import type { App } from 'vue';
|
||||||
|
import FButton from './src/button.component';
|
||||||
|
|
||||||
|
export * from './src/button.props';
|
||||||
|
|
||||||
|
export { FButton };
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(app: App): void {
|
||||||
|
app.component(FButton.name, FButton);
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
// import { defineComponent, computed } from 'vue';
|
||||||
|
// import type { SetupContext } from 'vue';
|
||||||
|
// import { buttonGroupProps, ButtonGroupProps } from './button.props';
|
||||||
|
// import { useButtonGroup } from './composition/use-button-group';
|
||||||
|
|
||||||
|
// export default defineComponent({
|
||||||
|
// name: 'FButtonGroup',
|
||||||
|
// props: buttonGroupProps,
|
||||||
|
// emits: ['click'],
|
||||||
|
// setup(props: ButtonGroupProps, context: SetupContext) {
|
||||||
|
// // const { onClickButton } = useButtonGroup(props, context);
|
||||||
|
// // const fButtonSize = computed(() => ({
|
||||||
|
// // 'btn-lg': props.size === 'large',
|
||||||
|
// // 'btn-sm': props.size === 'small',
|
||||||
|
// // }));
|
||||||
|
// // const fButtonType = computed(() => ({
|
||||||
|
// // 'btn-primary': props.buttonType === 'primary',
|
||||||
|
// // 'btn-warning': props.buttonType === 'warning',
|
||||||
|
// // 'btn-danger': props.buttonType === 'danger',
|
||||||
|
// // 'btn-success': props.buttonType === 'success',
|
||||||
|
// // 'btn-link': props.buttonType === 'link',
|
||||||
|
// // 'btn-secondary': props.buttonType === 'secondary',
|
||||||
|
// // }));
|
||||||
|
|
||||||
|
// return () => (
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// });
|
|
@ -0,0 +1,26 @@
|
||||||
|
// import { ExtractPropTypes, PropType } from 'vue';
|
||||||
|
|
||||||
|
// type ButtonType = 'primary' | 'warning' | 'danger' | 'success' | 'link' | 'secondary';
|
||||||
|
// type SizeType = 'small' | 'large';
|
||||||
|
|
||||||
|
// export const buttonProps = {
|
||||||
|
// /**
|
||||||
|
// * 组件标识
|
||||||
|
// */
|
||||||
|
// id: String,
|
||||||
|
// /**
|
||||||
|
// * 设置按钮类型
|
||||||
|
// */
|
||||||
|
// buttonType: { type: String as PropType<ButtonType>, default: 'primary' },
|
||||||
|
// /**
|
||||||
|
// * 是否禁用
|
||||||
|
// */
|
||||||
|
// disable: { type: Boolean, default: false },
|
||||||
|
// /**
|
||||||
|
// * 按钮尺寸
|
||||||
|
// */
|
||||||
|
// size: { type: String as PropType<SizeType>, default: 'small' },
|
||||||
|
// // 待确定:text参数
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export type ButtonProps = ExtractPropTypes<typeof buttonProps>;
|
|
@ -0,0 +1,102 @@
|
||||||
|
import { defineComponent, computed } from 'vue';
|
||||||
|
import type { SetupContext } from 'vue';
|
||||||
|
import { buttonProps, ButtonProps } from './button.props';
|
||||||
|
import { useButton } from './composition/use-button';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'FButton',
|
||||||
|
props: buttonProps,
|
||||||
|
emits: ['click'],
|
||||||
|
setup(props: ButtonProps, context: SetupContext) {
|
||||||
|
const { onClickButton } = useButton(props, context);
|
||||||
|
const fButtonSize = computed(() => ({
|
||||||
|
'btn-lg': props.size === 'large',
|
||||||
|
'btn-sm': props.size === 'small',
|
||||||
|
}));
|
||||||
|
const fButtonType = computed(() => ({
|
||||||
|
'btn-primary': props.buttonType === 'primary',
|
||||||
|
'btn-warning': props.buttonType === 'warning',
|
||||||
|
'btn-danger': props.buttonType === 'danger',
|
||||||
|
'btn-success': props.buttonType === 'success',
|
||||||
|
'btn-link': props.buttonType === 'link',
|
||||||
|
'btn-secondary': props.buttonType === 'secondary',
|
||||||
|
}));
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
// btn-lg btn btn-primary
|
||||||
|
// btn-sm btn btn-warning
|
||||||
|
<div>
|
||||||
|
<div style={'text-align:left;margin-top:10px;'}>
|
||||||
|
<div style={'margin-top:10px;'}>primary</div>
|
||||||
|
<button
|
||||||
|
class={[fButtonSize.value, ' btn btn-primary']}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
主要按钮
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={[fButtonSize.value, ' btn btn-danger']}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
危险按钮
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={[fButtonSize.value, ' btn btn-success']}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
成功按钮
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={[fButtonSize.value, ' btn btn-warning']}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
警告按钮
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={[fButtonSize.value, ' btn btn-secondary']}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
信息按钮
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={[fButtonSize.value, ' btn btn-link']}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
文本按钮
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div style={'text-align:left'}>
|
||||||
|
<div style={'margin-top:10px;'}>size</div>
|
||||||
|
<button
|
||||||
|
class={['btn-sm btn', fButtonType.value]}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
小尺寸
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={['btn-lg btn', fButtonType.value]}
|
||||||
|
style={'margin:5px'}
|
||||||
|
id={props.id}
|
||||||
|
disabled={props.disable}
|
||||||
|
onClick={onClickButton}>
|
||||||
|
大尺寸
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { ExtractPropTypes, PropType } from 'vue';
|
||||||
|
|
||||||
|
type ButtonType = 'primary' | 'warning' | 'danger' | 'success' | 'link' | 'secondary';
|
||||||
|
type SizeType = 'small' | 'large';
|
||||||
|
|
||||||
|
export const buttonProps = {
|
||||||
|
/**
|
||||||
|
* 组件标识
|
||||||
|
*/
|
||||||
|
id: String,
|
||||||
|
/**
|
||||||
|
* 设置按钮类型
|
||||||
|
*/
|
||||||
|
buttonType: { type: String as PropType<ButtonType>, default: 'primary' },
|
||||||
|
/**
|
||||||
|
* 是否禁用
|
||||||
|
*/
|
||||||
|
disable: { type: Boolean, default: false },
|
||||||
|
/**
|
||||||
|
* 按钮尺寸
|
||||||
|
*/
|
||||||
|
size: { type: String as PropType<SizeType>, default: 'small' },
|
||||||
|
// 待确定:text参数
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ButtonProps = ExtractPropTypes<typeof buttonProps>;
|
|
@ -0,0 +1,13 @@
|
||||||
|
// import { ComputedRef } from 'vue';
|
||||||
|
|
||||||
|
// export interface UseButton {
|
||||||
|
// /**
|
||||||
|
// * 附加按钮的Class
|
||||||
|
// */
|
||||||
|
// // buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||||
|
// /**
|
||||||
|
// * 点击附加按钮事件响应函数
|
||||||
|
// */
|
||||||
|
// onClickButton: ($event: Event) => void;
|
||||||
|
|
||||||
|
// }
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ComputedRef } from 'vue';
|
||||||
|
|
||||||
|
export interface UseButton {
|
||||||
|
/**
|
||||||
|
* 附加按钮的Class
|
||||||
|
*/
|
||||||
|
// buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||||
|
/**
|
||||||
|
* 点击附加按钮事件响应函数
|
||||||
|
*/
|
||||||
|
onClickButton: ($event: Event) => void;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// import { UseButton } from './types';
|
||||||
|
// import { ButtonProps } from '../button.props';
|
||||||
|
// import { computed, SetupContext } from 'vue';
|
||||||
|
|
||||||
|
// export function useButton(props: ButtonProps, context: SetupContext): UseButton {
|
||||||
|
|
||||||
|
// // const buttonClass = computed(() => ({
|
||||||
|
// // // 'input-group-append': true,
|
||||||
|
// // // 'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||||
|
// // }));
|
||||||
|
|
||||||
|
// function onClickButton($event: Event) {
|
||||||
|
// $event.stopPropagation();
|
||||||
|
// // this.disabled
|
||||||
|
// if (props.disable) {
|
||||||
|
// context.emit('clickButton', $event);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// // buttonClass,
|
||||||
|
// onClickButton
|
||||||
|
// };
|
||||||
|
// }
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { UseButton } from './types';
|
||||||
|
import { ButtonProps } from '../button.props';
|
||||||
|
import { computed, SetupContext } from 'vue';
|
||||||
|
|
||||||
|
export function useButton(props: ButtonProps, context: SetupContext): UseButton {
|
||||||
|
|
||||||
|
// const buttonClass = computed(() => ({
|
||||||
|
// // 'input-group-append': true,
|
||||||
|
// // 'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
function onClickButton($event: Event) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
// this.disabled
|
||||||
|
if (props.disable) {
|
||||||
|
context.emit('clickButton', $event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// buttonClass,
|
||||||
|
onClickButton
|
||||||
|
};
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// This starter template is using Vue 3 <script setup> SFCs
|
// This starter template is using Vue 3 <script setup> SFCs
|
||||||
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||||
import { ref } from "vue";
|
import { ref } from 'vue';
|
||||||
import HelloWorld from './components/hello-world.vue';
|
import HelloWorld from './components/hello-world.vue';
|
||||||
import Avatar from './components/avatar.vue';
|
import ButtonEdit from '../components/button-edit/src/button-edit.component';
|
||||||
import ButtonEdit from './components/button-edit.vue';
|
import FButton from '../components/button/src/button.component';
|
||||||
|
|
||||||
const canEdit = ref(true);
|
const canEdit = ref(true);
|
||||||
|
const disable = ref(false);
|
||||||
const canAutoComplete = ref(false);
|
const canAutoComplete = ref(false);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -21,22 +21,30 @@ const canAutoComplete = ref(false);
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<HelloWorld msg="Vite + Vue" />
|
<HelloWorld msg="Vite + Vue" />
|
||||||
|
<!-- <input type="checkbox" id="checkbox" v-model="canEdit" />
|
||||||
|
<label for="checkbox">editable:{{ canEdit }}</label>
|
||||||
|
<input type="checkbox" id="checkbox" v-model="canAutoComplete" />
|
||||||
|
<label for="checkbox">auto complete:{{ canAutoComplete }}</label> -->
|
||||||
|
<!-- <ButtonEdit :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></ButtonEdit> -->
|
||||||
<ButtonEdit></ButtonEdit>
|
<ButtonEdit></ButtonEdit>
|
||||||
<Avatar></Avatar>
|
<Avatar></Avatar>
|
||||||
|
<input type="checkbox" id="checkbox" v-model="disable" />
|
||||||
|
<label for="checkbox">disable:{{ disable }}</label>
|
||||||
|
<FButton :disable="disable"></FButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.logo {
|
.logo {
|
||||||
height: 6em;
|
height: 6em;
|
||||||
padding: 1.5em;
|
padding: 1.5em;
|
||||||
will-change: filter;
|
will-change: filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo:hover {
|
.logo:hover {
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
filter: drop-shadow(0 0 2em #646cffaa);
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo.vue:hover {
|
.logo.vue:hover {
|
||||||
filter: drop-shadow(0 0 2em #42b883aa);
|
filter: drop-shadow(0 0 2em #42b883aa);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue