first commit

This commit is contained in:
lingxiao865
2026-02-10 08:05:03 +08:00
commit c5af079d8c
1094 changed files with 97530 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
:: BASE_DOC ::
## API
### Image Props
name | type | default | description | required
-- | -- | -- | -- | --
custom-style | Object | - | CSS(Cascading Style Sheets) | N
error | String | 'default' | \- | N
height | String / Number | - | \- | N
lazy | Boolean | false | \- | N
loading | String | 'default' | \- | N
mode | String | scaleToFill | options: scaleToFill/aspectFit/aspectFill/widthFix/heightFix/top/bottom/center/left/right/top left/top right/bottom left/bottom right | N
shape | String | square | options: circle/round/square | N
show-menu-by-longpress | Boolean | false | \- | N
src | String | - | \- | N
t-id | String | - | image tag id | N
webp | Boolean | false | \- | N
width | String / Number | - | \- | N
### Image Events
name | params | description
-- | -- | --
error | `(context: { e: ImageEvent })` | trigger on image load failed。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/common.ts)
load | `(context: { e: ImageEvent })` | trigger on image loaded。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/common.ts)
### Image Slots
name | Description
-- | --
error | \-
loading | \-
### Image External Classes
className | Description
-- | --
t-class | \-
t-class-load | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-image-color | @text-color-placeholder | -
--td-image-loading-bg-color | @bg-color-secondarycontainer | -
--td-image-loading-color | @text-color-placeholder | -
--td-image-round-radius | @radius-default | -

View File

@@ -0,0 +1,86 @@
---
title: Image 图片
description: 用于展示效果,主要为上下左右居中裁切、拉伸、平铺等方式。
spline: base
isComponent: true
---
## 引入
可在 `main.ts` 或在需要使用的页面或组件中引入。
```js
import TImage from '@tdesign/uniapp/image/image.vue';
```
### 裁切样式
{{ base }}
### 加载状态
{{ status }}
## 常见问题
<details>
<summary>
本地图片无法正确引用?
<span class="icon">👇</span>
</summary>
<p style="margin-top: 10px; color: rgba(0, 0, 0, .6)">
建议使用绝对路径,而不是相对路径。绝对路径以 app.json 所在位置为基准。
</p>
</details>
## API
### Image Props
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
custom-style | Object | - | 自定义样式 | N
error | String | 'default' | 加载失败时显示的内容。值为 `default` 则表示使用默认加载失败风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `error`;值为其他则表示普通文本内容,如“加载失败” | N
height | String / Number | - | 高度,默认单位为`px` | N
lazy | Boolean | false | 是否开启图片懒加载 | N
loading | String | 'default' | 加载态内容。值为 `default` 则表示使用默认加载中风格;值为其他则表示普通文本内容,如“加载中” | 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
t-id | String | - | 图片标签id | N
webp | Boolean | false | 默认不解析 webP 格式,只支持网络资源 | N
width | String / Number | - | 宽度,默认单位为`px` | N
### Image Events
名称 | 参数 | 描述
-- | -- | --
error | `(context: { e: ImageEvent })` | 图片加载失败时触发。[通用类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/common.ts)
load | `(context: { e: ImageEvent })` | 图片加载完成时触发。[通用类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/common/common.ts)
### Image Slots
名称 | 描述
-- | --
error | 自定义 `error` 显示内容
loading | 自定义 `loading` 显示内容
### Image External Classes
类名 | 描述
-- | --
t-class | 根节点样式类
t-class-load | 加载样式类
### CSS Variables
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-image-color | @text-color-placeholder | -
--td-image-loading-bg-color | @bg-color-secondarycontainer | -
--td-image-loading-color | @text-color-placeholder | -
--td-image-round-radius | @radius-default | -

View File

@@ -0,0 +1,44 @@
.t-image {
position: relative;
display: inline-block;
}
.t-image__mask,
.t-image__img {
color: var(--td-image-color, var(--td-text-color-placeholder, var(--td-font-gray-3, rgba(0, 0, 0, 0.4))));
vertical-align: top;
width: inherit;
height: inherit;
}
.t-image__mask {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--td-image-loading-bg-color, var(--td-bg-color-secondarycontainer, var(--td-gray-color-1, #f3f3f3)));
color: var(--td-image-loading-color, var(--td-text-color-placeholder, 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--lazy {
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
.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,207 @@
<template>
<view
:style="tools._style([customStyle])"
:class="[tClass, classPrefix]"
>
<view
v-if="isLoading"
:style="tools._style([innerStyle])"
:class="classPrefix + '__mask ' + classPrefix + '--loading ' + classPrefix + '--shape-' + shape"
:aria-hidden="ariaHidden"
>
<t-loading
v-if="loading === 'default'"
theme="dots"
size="44rpx"
loading
inherit-color
:t-class="tClassLoad"
:t-class-text="classPrefix + '--loading-text'"
/>
<view
v-else-if="loading !== '' && loading !== 'slot'"
:class="classPrefix + '__common ' + tClassLoad"
>
{{ loading }}
</view>
<slot
v-else
name="loading"
/>
</view>
<view
v-else-if="isFailed"
:style="tools._style([innerStyle])"
:class="[
classPrefix + '__mask ' + classPrefix + '--failed ' + classPrefix + '--shape-' + shape,
tClassError
]"
:aria-hidden="ariaHidden"
>
<view
v-if="error === 'default'"
style="font-size: 44rpx"
:class="tClassLoad"
>
<t-icon
name="close"
aria-role="img"
aria-label="加载失败"
/>
</view>
<view
v-else-if="error && error !== 'slot'"
:class="[classPrefix + '__common ', tClassLoad]"
>
{{ error }}
</view>
<slot
v-else
name="error"
/>
</view>
<image
v-if="!isFailed"
:id="tId || 'image'"
:style="tools._style([innerStyle])"
:class="[
classPrefix + '__img ' + classPrefix + '--shape-' + shape + ' ',
(isLoading ? classPrefix + '--lazy' : '') + ' ',
tClassImage
]"
:src="src"
:mode="mode"
:webp="webp"
:lazy-load="lazy"
:show-menu-by-longpress="showMenuByLongpress"
:aria-hidden="ariaHidden || isLoading || isFailed"
:aria-label="ariaLabel"
@click="onClick"
@load="onLoaded"
@error="onLoadError"
/>
</view>
</template>
<script>
import TLoading from '../loading/loading';
import TIcon from '../icon/icon';
import { uniComponent } from '../common/src/index';
import ImageProps from './props';
import { prefix } from '../common/config';
import { addUnit, getRect, appBaseInfo } from '../common/utils';
import { compareVersion } from '../common/version';
import tools from '../common/utils.wxs';
const name = `${prefix}-image`;
export default uniComponent({
name,
options: {
styleIsolation: 'shared',
},
externalClasses: [
`${prefix}-class`,
`${prefix}-class-load`,
`${prefix}-class-image`,
`${prefix}-class-error`,
],
components: {
TLoading,
TIcon,
},
props: {
...ImageProps,
},
emits: [
'click',
],
data() {
return {
prefix,
isLoading: true,
isFailed: false,
innerStyle: '',
classPrefix: name,
tools,
preSrc: '',
};
},
watch: {
src() {
if (this.preSrc !== this.src) {
this.update();
}
},
width: 'calcSize',
height: 'calcSize',
},
mounted() {
this.calcSize(this.width, this.height);
},
methods: {
onLoaded(e) {
const version = appBaseInfo.SDKVersion;
const {
mode,
tId,
} = this;
const lower = compareVersion(version, '2.10.3') < 0;
// #ifdef MP-WEIXIN || MP-QQ
if ('heightFix' === mode && lower) {
getRect(this, `#${tId || 'image'}`).then((e) => {
const {
height,
width,
} = e;
this.innerStyle = `height: ${addUnit(height)}; width: ${width}px;`;
})
.catch(() => {
});
}
// #endif
this.isLoading = false;
this.isFailed = false;
this.$emit('load', { e });
},
onLoadError(e) {
this.isLoading = false;
this.isFailed = true;
this.$emit('error', { e });
},
calcSize(width = this.width, height = this.height) {
let innerStyle = '';
if (width) {
innerStyle += `width: ${addUnit(width)};`;
}
if (height) {
innerStyle += `height: ${addUnit(height)};`;
}
this.innerStyle = innerStyle;
},
update() {
const {
src,
} = this;
this.preSrc = src;
if (src) {
this.isLoading = true;
this.isFailed = false;
} else {
this.onLoadError({
errMsg: '图片链接为空',
});
}
},
onClick(e) {
this.$emit('click', e);
},
},
});
</script>
<style scoped>
@import './image.css';
</style>

View File

@@ -0,0 +1,71 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TdImageProps } from './type';
export default {
/** 加载失败时显示的内容。值为 `default` 则表示使用默认加载失败风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `error`;值为其他则表示普通文本内容,如“加载失败” */
error: {
type: String,
default: 'default' as TdImageProps['error'],
},
/** 高度,默认单位为`px` */
height: {
type: [String, Number],
},
/** 是否开启图片懒加载 */
lazy: Boolean,
/** 加载态内容。值为 `default` 则表示使用默认加载中风格;值为其他则表示普通文本内容,如“加载中” */
loading: {
type: String,
default: 'default' as TdImageProps['loading'],
},
/** 图片裁剪、缩放的模式;[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/image.html) */
mode: {
type: String,
default: 'scaleToFill' as TdImageProps['mode'],
validator(val: TdImageProps['mode']): boolean {
if (!val) return true;
return ['scaleToFill', 'aspectFit', 'aspectFill', 'widthFix', 'heightFix', 'top', 'bottom', 'center', 'left', 'right', 'top left', 'top right', 'bottom left', 'bottom right'].includes(val);
},
},
/** 图片圆角类型 */
shape: {
type: String,
default: 'square' as TdImageProps['shape'],
validator(val: TdImageProps['shape']): boolean {
if (!val) return true;
return ['circle', 'round', 'square'].includes(val);
},
},
/** 长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单 */
showMenuByLongpress: Boolean,
/** 图片链接 */
src: {
type: String,
default: '',
},
/** 图片标签id */
tId: {
type: String,
default: '',
},
/** 默认不解析 webP 格式,只支持网络资源 */
webp: Boolean,
/** 宽度,默认单位为`px` */
width: {
type: [String, Number],
},
/** 图片加载失败时触发 */
onError: {
type: Function,
default: () => ({}),
},
/** 图片加载完成时触发 */
onLoad: {
type: Function,
default: () => ({}),
},
};

View File

@@ -0,0 +1,85 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { ImageEvent } from '../common/common';
export interface TdImageProps {
/**
* 加载失败时显示的内容。值为 `default` 则表示使用默认加载失败风格;值为空或者 `slot` 表示使用插槽渲染,插槽名称为 `error`;值为其他则表示普通文本内容,如“加载失败”
* @default 'default'
*/
error?: string;
/**
* 高度,默认单位为`px`
*/
height?: string | number;
/**
* 是否开启图片懒加载
* @default false
*/
lazy?: boolean;
/**
* 加载态内容。值为 `default` 则表示使用默认加载中风格;值为其他则表示普通文本内容,如“加载中”
* @default 'default'
*/
loading?: string;
/**
* 图片裁剪、缩放的模式;[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/image.html)
* @default scaleToFill
*/
mode?:
| 'scaleToFill'
| 'aspectFit'
| 'aspectFill'
| 'widthFix'
| 'heightFix'
| 'top'
| 'bottom'
| 'center'
| 'left'
| 'right'
| 'top left'
| 'top right'
| 'bottom left'
| 'bottom right';
/**
* 图片圆角类型
* @default square
*/
shape?: 'circle' | 'round' | 'square';
/**
* 长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单
* @default false
*/
showMenuByLongpress?: boolean;
/**
* 图片链接
* @default ''
*/
src?: string;
/**
* 图片标签id
* @default ''
*/
tId?: string;
/**
* 默认不解析 webP 格式,只支持网络资源
* @default false
*/
webp?: boolean;
/**
* 宽度,默认单位为`px`
*/
width?: string | number;
/**
* 图片加载失败时触发
*/
onError?: (context: { e: ImageEvent }) => void;
/**
* 图片加载完成时触发
*/
onLoad?: (context: { e: ImageEvent }) => void;
}