project init & fix ui

This commit is contained in:
2023-01-06 14:24:11 +08:00
parent abc4f65a8e
commit ac9b479805
866 changed files with 39916 additions and 53 deletions

View File

@@ -0,0 +1,26 @@
:: BASE_DOC ::
## API
### Image Props
name | type | default | description | required
-- | -- | -- | -- | --
custom-style | String | - | \- | N
error | String / Slot | 'default' | \- | N
external-classes | Array | - | `['t-class', 't-class-load']` | N
height | String / Number | - | \- | N
lazy | Boolean | false | \- | N
loading | String / Slot | 'default' | \- | N
mode | String | scaleToFill | optionsscaleToFill/aspectFit/aspectFill/widthFix/heightFix/top/bottom/center/left/right/top left/top right/bottom left/bottom right | N
shape | String | square | optionscircle/round/square | N
show-menu-by-longpress | Boolean | false | \- | N
src | String | - | \- | N
webp | Boolean | false | \- | N
width | String / Number | - | \- | N
### Image Events
name | params | description
-- | -- | --
error | \- | \-
load | \- | \-

View File

@@ -0,0 +1,52 @@
---
title: Image 图片
description: 用于展示效果,主要为上下左右居中裁切、拉伸、平铺等方式。
spline: base
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-100%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-image": "tdesign-miniprogram/image/image"
}
```
## 代码演示
### 裁切样式
{{ base }}
### 加载状态
{{ status }}
## API
### Image Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
custom-style `v0.25.0` | String | - | 自定义组件样式 | N
error | String / Slot | 'default' | 加载失败时显示的内容。值为 `default` 则表示使用默认加载失败风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `error`;值为其他则表示普通文本内容,如“加载失败” | N
external-classes | Array | - | 组件类名,分别用于设置加载组件外层元素,中间内容等元素类名。`['t-class', 't-class-load']` | N
height | String / Number | - | 高度,默认单位为`px` | N
lazy | Boolean | false | 是否开启图片懒加载 | N
loading | String / Slot | 'default' | 加载态内容。值为 `default` 则表示使用默认加载中风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `loading`;值为其他则表示普通文本内容,如“加载中” | N
mode | String | scaleToFill | 图片裁剪、缩放的模式;[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/image.html)。可选项scaleToFill/aspectFit/aspectFill/widthFix/heightFix/top/bottom/center/left/right/top left/top right/bottom left/bottom right | N
shape | String | square | 图片圆角类型。可选项circle/round/square | N
show-menu-by-longpress | Boolean | false | 长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单。 | N
src | String | - | 图片链接 | N
webp | Boolean | false | 默认不解析 webP 格式,只支持网络资源 | N
width | String / Number | - | 宽度,默认单位为`px` | N
### Image Events
名称 | 参数 | 描述
-- | -- | --
error | \- | 图片加载失败时触发
load | \- | 图片加载完成时触发

View File

@@ -0,0 +1,75 @@
{
"key": "Image",
"label": "图片",
"icon": "",
"properties": [
{
"key": "error",
"type": ["String", "TNode"],
"defaultValue": "'default'",
"desc": "加载失败时显示的内容。值为 `default` 则表示使用默认加载失败风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `error`;值为其他则表示普通文本内容,如“加载失败”",
"label": ""
},
{
"key": "externalClasses",
"type": ["Array"],
"defaultValue": "",
"desc": "组件类名,分别用于设置加载组件外层元素,中间内容等元素类名",
"label": ""
},
{
"key": "lazy",
"type": ["Boolean"],
"defaultValue": "false",
"desc": "是否开启图片懒加载",
"label": ""
},
{
"key": "loading",
"type": ["String", "TNode"],
"defaultValue": "'default'",
"desc": "加载态内容。值为 `default` 则表示使用默认加载中风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `loading`;值为其他则表示普通文本内容,如“加载中”",
"label": ""
},
{
"key": "MP_EXCLUDE_PROPS",
"type": ["String"],
"defaultValue": "",
"desc": "为避免重复或冲突,需要过滤掉的小程序原生属性",
"label": ""
},
{
"key": "MP_PROPS",
"type": ["String"],
"defaultValue": "",
"desc": "[小程序原生属性](https://developers.weixin.qq.com/miniprogram/dev/component/image.html)",
"label": ""
},
{
"key": "shape",
"type": ["String"],
"defaultValue": "square",
"desc": "图片圆角类型",
"label": ""
},
{
"key": "src",
"type": ["String"],
"defaultValue": "",
"desc": "图片链接",
"label": ""
}
],
"events": [
{
"key": "error",
"desc": "图片加载失败时触发",
"label": ""
},
{
"key": "load",
"desc": "图片加载完成时触发",
"label": ""
}
]
}

View File

@@ -0,0 +1,27 @@
import { SuperComponent } from '../common/src/index';
export default class Image extends SuperComponent {
externalClasses: string[];
options: {
multipleSlots: boolean;
};
properties: import("./type").TdImageProps;
data: {
prefix: string;
isLoading: boolean;
isFailed: boolean;
innerStyle: string;
classPrefix: string;
};
preSrc: string;
lifetimes: {
attached(): void;
};
observers: {
src(): void;
};
methods: {
onLoaded(e: any): void;
onLoadError(e: any): void;
update(): void;
};
}

View File

@@ -0,0 +1,104 @@
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { SuperComponent, wxComponent } from '../common/src/index';
import ImageProps from './props';
import config from '../common/config';
import { addUnit } from '../common/utils';
const { prefix } = config;
const name = `${prefix}-image`;
let Image = class Image extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-load`];
this.options = {
multipleSlots: true,
};
this.properties = ImageProps;
this.data = {
prefix,
isLoading: true,
isFailed: false,
innerStyle: '',
classPrefix: name,
};
this.preSrc = '';
this.lifetimes = {
attached() {
const { width, height } = this.data;
let innerStyle = '';
this.update();
if (width) {
innerStyle += `width: ${addUnit(width)};`;
}
if (height) {
innerStyle += `height: ${addUnit(height)};`;
}
this.setData({
innerStyle,
});
},
};
this.observers = {
src() {
if (this.preSrc === this.properties.src)
return;
this.update();
},
};
this.methods = {
onLoaded(e) {
const sdkVersion = wx.getSystemInfoSync().SDKVersion;
const versionArray = sdkVersion.split('.').map((v) => parseInt(v, 10));
const { mode } = this.properties;
const isInCompatible = versionArray[0] < 2 ||
(versionArray[0] === 2 && versionArray[1] < 10) ||
(versionArray[0] === 2 && versionArray[1] === 10 && versionArray[2] < 3);
if (mode === 'heightFix' && isInCompatible) {
const { height: picHeight, width: picWidth } = e.detail;
const query = this.createSelectorQuery();
query
.select('#image')
.boundingClientRect((res) => {
const { height } = res;
const resultWidth = ((height / picHeight) * picWidth).toFixed(2);
this.setData({ innerStyle: `height: ${addUnit(height)}; width: ${resultWidth}px;` });
})
.exec();
}
this.setData({
isLoading: false,
isFailed: false,
});
this.triggerEvent('load', e.detail);
},
onLoadError(e) {
this.setData({
isLoading: false,
isFailed: true,
});
this.triggerEvent('error', e.detail);
},
update() {
const { src } = this.properties;
this.preSrc = src;
if (!src) {
this.onLoadError({ errMsg: '图片链接为空' });
}
else {
this.setData({
isLoading: true,
isFailed: false,
});
}
},
};
}
};
Image = __decorate([
wxComponent()
], Image);
export default Image;

View File

@@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"t-loading": "../loading/loading",
"t-icon": "../icon/icon"
}
}

View File

@@ -0,0 +1,50 @@
<!-- 加载中占位 -->
<view
wx:if="{{isLoading}}"
style="{{innerStyle}} {{customStyle}}"
class="{{prefix}}-class {{classPrefix}} {{classPrefix}}__mask {{classPrefix}}--loading {{classPrefix}}--shape-{{shape}}"
aria-hidden="{{ariaHidden}}"
>
<t-loading
wx:if="{{loading === 'default'}}"
theme="dots"
size="44rpx"
loading
inherit-color
class="t-class-load"
t-class-text="{{classPrefix}}--loading-text"
></t-loading>
<view wx:elif="{{loading !== 'slot' && loading !== ''}}" class="{{classPrefix}}__common {{prefix}}-class-load">
{{loading}}
</view>
<slot wx:else name="loading" class="{{prefix}}-class-load" />
</view>
<!-- 加载失败占位 -->
<view
wx:elif="{{isFailed}}"
style="{{innerStyle}} {{customStyle}}"
class="{{prefix}}-class {{classPrefix}} {{classPrefix}}__mask {{classPrefix}}--failed {{classPrefix}}--shape-{{shape}}"
aria-hidden="{{ariaHidden}}"
>
<view wx:if="{{error === 'default'}}" style="font-size: 44rpx" class="{{prefix}}-class-load">
<t-icon name="close" aria-role="img" aria-label="加载失败" />
</view>
<view wx:elif="{{error && error !== 'slot'}}" class="{{classPrefix}}__common {{prefix}}-class-load"> {{error}} </view>
<slot wx:else name="error" class="{{prefix}}-class-load"></slot>
</view>
<!-- 图片 -->
<image
id="image"
hidden="{{isLoading || isFailed}}"
class="{{prefix}}-class {{classPrefix}} {{classPrefix}}--shape-{{shape}}"
src="{{src}}"
style="{{innerStyle}}{{customStyle}}"
mode="{{mode}}"
webp="{{webp}}"
lazy-load="{{lazy}}"
bind:load="onLoaded"
bind:error="onLoadError"
show-menu-by-longpress="{{showMenuByLongpress}}"
aria-hidden="{{ariaHidden || isLoading || isFailed}}"
aria-label="{{ariaLabel}}"
/>

View File

@@ -0,0 +1,58 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-image {
color: var(--td-image-color, var(--td-font-gray-3, rgba(0, 0, 0, 0.4)));
vertical-align: top;
}
.t-image__mask {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--td-image-loading-bg-color, var(--td-gray-color-1, #f3f3f3));
color: var(--td-image-loading-color, var(--td-font-gray-3, rgba(0, 0, 0, 0.4)));
}
.t-image--loading-text {
width: 0;
height: 0;
}
.t-image__common {
width: 100%;
height: 100%;
}
.t-image--shape-circle {
border-radius: 50%;
overflow: hidden;
}
.t-image--shape-round {
border-radius: var(--td-image-round-radius, var(--td-radius-default, 12rpx));
overflow: hidden;
}
.t-image--shape-square {
border-radius: 0;
overflow: hidden;
}

View File

@@ -0,0 +1,4 @@
import { TdImageProps } from './type';
export declare type ImageProps = TdImageProps;
export * from './props';
export * from './image';

View File

@@ -0,0 +1,2 @@
export * from './props';
export * from './image';

View File

@@ -0,0 +1,3 @@
import { TdImageProps } from './type';
declare const props: TdImageProps;
export default props;

View File

@@ -0,0 +1,48 @@
const props = {
customStyle: {
type: String,
value: '',
},
error: {
type: String,
value: 'default',
},
externalClasses: {
type: Array,
},
height: {
type: null,
},
lazy: {
type: Boolean,
value: false,
},
loading: {
type: String,
value: 'default',
},
mode: {
type: String,
value: 'scaleToFill',
},
shape: {
type: String,
value: 'square',
},
showMenuByLongpress: {
type: Boolean,
value: false,
},
src: {
type: String,
value: '',
},
webp: {
type: Boolean,
value: false,
},
width: {
type: null,
},
};
export default props;

View File

@@ -0,0 +1,50 @@
export interface TdImageProps {
customStyle?: {
type: StringConstructor;
value?: string;
};
error?: {
type: StringConstructor;
value?: string;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-load'];
};
height?: {
type: null;
value?: string | number;
};
lazy?: {
type: BooleanConstructor;
value?: boolean;
};
loading?: {
type: StringConstructor;
value?: string;
};
mode?: {
type: StringConstructor;
value?: 'scaleToFill' | 'aspectFit' | 'aspectFill' | 'widthFix' | 'heightFix' | 'top' | 'bottom' | 'center' | 'left' | 'right' | 'top left' | 'top right' | 'bottom left' | 'bottom right';
};
shape?: {
type: StringConstructor;
value?: 'circle' | 'round' | 'square';
};
showMenuByLongpress?: {
type: BooleanConstructor;
value?: boolean;
};
src?: {
type: StringConstructor;
value?: string;
};
webp?: {
type: BooleanConstructor;
value?: boolean;
};
width?: {
type: null;
value?: string | number;
};
}

View File

@@ -0,0 +1 @@
export {};