mirror of
https://gitee.com/xiangheng/x_admin.git
synced 2025-09-26 20:21:19 +08:00
升级依赖
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
## 1.0.14(2024-05-31)
|
||||
1. 修复设置maxDate后存在选择不准确的BUG
|
||||
## 1.0.13(2024-03-22)
|
||||
1. 修复VUE3中出现的BUG
|
||||
## 1.0.12(2023-11-27)
|
||||
|
@@ -78,7 +78,9 @@
|
||||
},
|
||||
watch: {
|
||||
propsChange() {
|
||||
this.init()
|
||||
uni.$uv.sleep(100).then(res=>{
|
||||
this.init()
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "uv-datetime-picker",
|
||||
"displayName": "uv-datetime-picker 时间选择器 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.13",
|
||||
"version": "1.0.14",
|
||||
"description": "时间选择器组件用于时间日期,主要用于年月日时分的选择,具体选择的精确度由参数控制。",
|
||||
"keywords": [
|
||||
"datetime-picker",
|
||||
@@ -43,7 +43,8 @@
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
|
@@ -1,29 +1,101 @@
|
||||
## 1.2.19(2024-05-01)
|
||||
### [1.2.19](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.18...v1.2.19) (2024-05-01)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* ✨ `Slider`组件`min`值允许负数 ([9e7c8d3](https://github.com/Moonofweisheng/wot-design-uni/commit/9e7c8d33eb2c0fccc44f465ed3b28d2cd81efa2d)), closes [#266](https://github.com/Moonofweisheng/wot-design-uni/issues/266)
|
||||
* ✨ fab添加draggable属性 ([#259](https://github.com/Moonofweisheng/wot-design-uni/issues/259)) ([5e0cd6c](https://github.com/Moonofweisheng/wot-design-uni/commit/5e0cd6caa2296a44a3dc1b3d33033d4cc91d01b9))
|
||||
* ✨ table组件添加index参数 ([2161705](https://github.com/Moonofweisheng/wot-design-uni/commit/2161705a2f868f874b89ee28b6029677854a7741))
|
||||
## 1.2.24(2024-06-04)
|
||||
### [1.2.24](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.23...v1.2.24) (2024-06-03)
|
||||
|
||||
|
||||
### Bug Fixes | Bug 修复
|
||||
|
||||
* 修复`slider`组件`step`属性无效问题 ([50133b9](https://github.com/Moonofweisheng/wot-design-uni/commit/50133b9e5e2a18aace8cbf9eb7570579cc563f1d)), closes [#269](https://github.com/Moonofweisheng/wot-design-uni/issues/269)
|
||||
* 修复Cell组件title文字对齐方式受外部影响的问题 ([caf66b6](https://github.com/Moonofweisheng/wot-design-uni/commit/caf66b6beeb236a9295cf0d8ec250557dc19e54e)), closes [#282](https://github.com/Moonofweisheng/wot-design-uni/issues/282)
|
||||
* 修复SelectPicker无默认值时仍会查找选择项节点的问题 ([130c438](https://github.com/Moonofweisheng/wot-design-uni/commit/130c4383dc862e190b96bc3670a852a4cce3e629)), closes [#281](https://github.com/Moonofweisheng/wot-design-uni/issues/281)
|
||||
* 修复Slider组件max和min变化时滑块和进度条未更新的问题 ([#276](https://github.com/Moonofweisheng/wot-design-uni/issues/276)) ([69303b5](https://github.com/Moonofweisheng/wot-design-uni/commit/69303b52077bd268e3563fa9096e91530bb978c5))
|
||||
|
||||
|
||||
### Documentation | 文档
|
||||
|
||||
* 补充Table组件关于Events的介绍 ([6760317](https://github.com/Moonofweisheng/wot-design-uni/commit/676031781b189a3a89dba9e57cb989c06999091a)), closes [#260](https://github.com/Moonofweisheng/wot-design-uni/issues/260)
|
||||
* 修复Input支付宝小程序number/digit类型使用maxlength=-1时v-model失效的问题 ([7aa21b0](https://github.com/Moonofweisheng/wot-design-uni/commit/7aa21b0baadeccf4f0eb179f74332013acec6a10))
|
||||
|
||||
# 更新日志
|
||||
|
||||
|
||||
### [1.2.24](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.23...v1.2.24) (2024-06-03)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* 🐛 修复Input支付宝小程序number/digit类型使用maxlength=-1时v-model失效的问题 ([7aa21b0](https://github.com/Moonofweisheng/wot-design-uni/commit/7aa21b0baadeccf4f0eb179f74332013acec6a10))
|
||||
|
||||
### [1.2.23](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.22...v1.2.23) (2024-06-02)
|
||||
|
||||
|
||||
### ✏️ Documentation | 文档
|
||||
|
||||
* ✏️ 更新LICENSE文件地址 ([dae3ffc](https://github.com/Moonofweisheng/wot-design-uni/commit/dae3ffcc7b488dd6d87bc1c5e8ae16a78b794f85))
|
||||
* ✏️ 修复loading组件示例代码中文标点符号、img-cropper组件示例代码标签缺失的问题 ([#347](https://github.com/Moonofweisheng/wot-design-uni/issues/347)) ([d171255](https://github.com/Moonofweisheng/wot-design-uni/commit/d171255899d232f141c84aa1251c03cc1d0a0b75))
|
||||
* update select-picker doc ([#346](https://github.com/Moonofweisheng/wot-design-uni/issues/346)) ([7454452](https://github.com/Moonofweisheng/wot-design-uni/commit/7454452ad44331f329408cead9b483cf774cce5f))
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* 🐛 修复Cell的value为0时无法渲染的问题 ([dc64c09](https://github.com/Moonofweisheng/wot-design-uni/commit/dc64c09e6c6f991fe6f8f9fcfa309392e233ce21))
|
||||
* 🐛 修复Sticky在h5和App端缓慢拖动时存在几率始终固定在顶部的问题 ([#350](https://github.com/Moonofweisheng/wot-design-uni/issues/350)) ([c5b3c5f](https://github.com/Moonofweisheng/wot-design-uni/commit/c5b3c5f68e1bb376249ed5f2c30b1898cc375abe))
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* ✨ 调整Circle环形进度条在微信小程序端使用canvas2d支持同层渲染 ([#351](https://github.com/Moonofweisheng/wot-design-uni/issues/351)) ([4489517](https://github.com/Moonofweisheng/wot-design-uni/commit/44895179e4688ceb995ea1968d23df4f0bf9cdc2))
|
||||
|
||||
### [1.2.22](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.21...v1.2.22) (2024-05-23)
|
||||
|
||||
|
||||
### ✏️ Documentation | 文档
|
||||
|
||||
* ✏️ 组件库介绍组件数量调整至70+ ([efd55ca](https://github.com/Moonofweisheng/wot-design-uni/commit/efd55ca8afc07368b8d9f348d73c9a25cf186c47))
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* 🐛 修复Form指定prop为`a.b`时校验失败的问题 ([#329](https://github.com/Moonofweisheng/wot-design-uni/issues/329)) ([ab600b9](https://github.com/Moonofweisheng/wot-design-uni/commit/ab600b915a647ff089d5cfbb0ac955e3baa581c3))
|
||||
|
||||
### [1.2.21](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.20...v1.2.21) (2024-05-20)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* ✨ 添加索引栏组件 ([#321](https://github.com/Moonofweisheng/wot-design-uni/issues/321)) ([f84e9af](https://github.com/Moonofweisheng/wot-design-uni/commit/f84e9affb1a044a37661c5d1dc118d834b49239c))
|
||||
* ✨ img组件添加loading、error插槽 ([#323](https://github.com/Moonofweisheng/wot-design-uni/issues/323)) ([00ffa9f](https://github.com/Moonofweisheng/wot-design-uni/commit/00ffa9f3e54f3ba9eec967887e195c0266ef0a41))
|
||||
* ✨ skeleton添加默认内容插槽 ([#322](https://github.com/Moonofweisheng/wot-design-uni/issues/322)) ([9a68c47](https://github.com/Moonofweisheng/wot-design-uni/commit/9a68c477dbf5e0f30f74882df92251eac707fdde))
|
||||
* add backtop ([#314](https://github.com/Moonofweisheng/wot-design-uni/issues/314)) ([bf9e55a](https://github.com/Moonofweisheng/wot-design-uni/commit/bf9e55a24e676a764b1e035ca86bd6fe26b87420))
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* 🐛 修复Cell组件单独使用时设置border无效的问题 ([19b9f19](https://github.com/Moonofweisheng/wot-design-uni/commit/19b9f196466b88456e8b3e7221afd710da3df99b))
|
||||
* 🐛 修复Picker选择器多列选择模式绑定值为空数组时将列第一项作为显示值的问题 ([c3b96ce](https://github.com/Moonofweisheng/wot-design-uni/commit/c3b96ce912bfc13d30c09393dd57cbcbf2d0b80a))
|
||||
* 🐛 修复Sticky吸顶组件在微信小程序中放置在页面顶部时吸顶失效的问题 ([4ca3ebe](https://github.com/Moonofweisheng/wot-design-uni/commit/4ca3ebe7202f118a1bf6a462b27dc76ab6c720f9)), closes [#325](https://github.com/Moonofweisheng/wot-design-uni/issues/325)
|
||||
* 修复wd-button在自定义样式时激活态样式问题 ([#312](https://github.com/Moonofweisheng/wot-design-uni/issues/312)) ([7544d69](https://github.com/Moonofweisheng/wot-design-uni/commit/7544d690f176b44a8e016688723af70d2a77388a))
|
||||
|
||||
|
||||
### ✏️ Documentation | 文档
|
||||
|
||||
* ✏️ 常见问题增加关于useToast等hooks的答疑以及自定义编译平台的内容 ([65597c7](https://github.com/Moonofweisheng/wot-design-uni/commit/65597c76b812e5e61be17879de320989d0873df4))
|
||||
* ✏️ 文档中增加解释导入方式的faq ([83fa0b0](https://github.com/Moonofweisheng/wot-design-uni/commit/83fa0b06927fddabd1021ee02c3c7f8377704786))
|
||||
|
||||
### [1.2.20](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.19...v1.2.20) (2024-05-12)
|
||||
|
||||
|
||||
### ✏️ Documentation | 文档
|
||||
|
||||
* ✏️ 调整捐赠榜单和友情链接的数据到cloudflare上 ([1314373](https://github.com/Moonofweisheng/wot-design-uni/commit/1314373af1dff95aee4cd3cddefebcb3a6a5c5d2))
|
||||
* ✏️ 推荐文档地址调整至cloudflare ([9119f30](https://github.com/Moonofweisheng/wot-design-uni/commit/9119f30b23676ad1b9a3869e362a3840ba288dc3))
|
||||
* ✏️ Curtain组件width属性标记为number类型 ([d172ce7](https://github.com/Moonofweisheng/wot-design-uni/commit/d172ce7ffcfebf29b184b57a7f74a25acad1f967)), closes [#303](https://github.com/Moonofweisheng/wot-design-uni/issues/303)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* Segmented组件添加click事件 ([#301](https://github.com/Moonofweisheng/wot-design-uni/issues/301)) ([225ce22](https://github.com/Moonofweisheng/wot-design-uni/commit/225ce225ac7faedffd4686b908076c47ba111695))
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* 🐛 修复MessageBox中使用TextArea字数统计样式错误的问题 ([b186ac0](https://github.com/Moonofweisheng/wot-design-uni/commit/b186ac09294a4fede16c514cd96ff94f661fcbc9)), closes [#290](https://github.com/Moonofweisheng/wot-design-uni/issues/290)
|
||||
* 🐛 修复PickerView可以滚动到禁用选项的问题 ([edd44ed](https://github.com/Moonofweisheng/wot-design-uni/commit/edd44eda3fc9879dc980b02d1885d77530a3d2e8)), closes [#302](https://github.com/Moonofweisheng/wot-design-uni/issues/302)
|
||||
* 🐛 修复Popover指定placement后箭头显示异常的问题([#306](https://github.com/Moonofweisheng/wot-design-uni/issues/306)) ([a9b108d](https://github.com/Moonofweisheng/wot-design-uni/commit/a9b108d231a8e537aab4ba49781590bcafb9354d))
|
||||
* 🐛 修复release脚本处理最低版本号问题 ([c8077c9](https://github.com/Moonofweisheng/wot-design-uni/commit/c8077c9f3790e7844c902528d43596c4bc4025af))
|
||||
* 🐛 修复Sticky组件获取节点错误的问题 ([5483ea6](https://github.com/Moonofweisheng/wot-design-uni/commit/5483ea6c447f85229af66b950e34c1dc690fadb1))
|
||||
* 修复wd-calendar未抛出事件 ([c1203c9](https://github.com/Moonofweisheng/wot-design-uni/commit/c1203c91841c3d5bcd407923a577711e462207a3))
|
||||
|
||||
### [1.2.19](https://github.com/Moonofweisheng/wot-design-uni/compare/v1.2.18...v1.2.19) (2024-05-01)
|
||||
|
||||
|
||||
|
@@ -286,6 +286,7 @@
|
||||
height: $size;
|
||||
background-color: $bg;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: calc(-1 * $size / 2);
|
||||
transform: rotateZ(45deg);
|
||||
box-shadow: $box-shadow;
|
||||
@@ -293,12 +294,14 @@
|
||||
}
|
||||
@include e(arrow-up) {
|
||||
transform: translateX(-50%);
|
||||
top: 0;
|
||||
&:after {
|
||||
content: "";
|
||||
width: $size;
|
||||
height: $size;
|
||||
background-color: $bg;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(-1 * $size / 2);
|
||||
transform: rotateZ(45deg);
|
||||
box-shadow: $box-shadow;
|
||||
@@ -306,6 +309,7 @@
|
||||
}
|
||||
@include e(arrow-left) {
|
||||
transform: translateY(-50%);
|
||||
left: 0;
|
||||
&:after {
|
||||
content: "";
|
||||
width: $size;
|
||||
@@ -313,12 +317,15 @@
|
||||
background-color: $bg;
|
||||
position: absolute;
|
||||
left: calc(-1 * $size / 2);
|
||||
top: 0;
|
||||
transform: rotateZ(45deg);
|
||||
box-shadow: $box-shadow;
|
||||
}
|
||||
}
|
||||
@include e(arrow-right) {
|
||||
transform: translateY(-50%);
|
||||
right: 0;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
width: $size;
|
||||
@@ -326,6 +333,7 @@
|
||||
background-color: $bg;
|
||||
position: absolute;
|
||||
right: calc(-1 * $size / 2);
|
||||
top: 0;
|
||||
transform: rotateZ(45deg);
|
||||
box-shadow: $box-shadow;
|
||||
}
|
||||
|
@@ -869,3 +869,9 @@ $-password-input-cursor-duration: var(--wd-password-input-cursor-duration, 1s);
|
||||
$-form-item-error-message-color: var(--wot-form-item-error-message-color, $-color-danger) !default;
|
||||
$-form-item-error-message-font-size: var(--wot-form-item-error-message-font-size, $-fs-secondary) !default;
|
||||
$-form-item-error-message-line-height: var(--wot-form-item-error-message-line-height, 24px) !default;
|
||||
|
||||
/* backtop */
|
||||
$-backtop-bg: var(--wot-backtop-bg, #e1e1e1) !default;
|
||||
|
||||
/* index-bar */
|
||||
$-index-bar-index-font-size: var(--wot-index-bar-index-font-size, $-fs-aid) !default;
|
||||
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 适配 canvas 2d 上下文
|
||||
* @param ctx canvas 2d 上下文
|
||||
* @returns
|
||||
*/
|
||||
export function canvas2dAdapter(ctx: CanvasRenderingContext2D): UniApp.CanvasContext {
|
||||
return Object.assign(ctx, {
|
||||
setFillStyle(color: string | CanvasGradient) {
|
||||
ctx.fillStyle = color
|
||||
},
|
||||
setStrokeStyle(color: string | CanvasGradient | CanvasPattern) {
|
||||
ctx.strokeStyle = color
|
||||
},
|
||||
setLineWidth(lineWidth: number) {
|
||||
ctx.lineWidth = lineWidth
|
||||
},
|
||||
setLineCap(lineCap: 'butt' | 'round' | 'square') {
|
||||
ctx.lineCap = lineCap
|
||||
},
|
||||
|
||||
setFontSize(font: string) {
|
||||
ctx.font = font
|
||||
},
|
||||
setGlobalAlpha(alpha: number) {
|
||||
ctx.globalAlpha = alpha
|
||||
},
|
||||
setLineJoin(lineJoin: 'bevel' | 'round' | 'miter') {
|
||||
ctx.lineJoin = lineJoin
|
||||
},
|
||||
setTextAlign(align: 'left' | 'center' | 'right') {
|
||||
ctx.textAlign = align
|
||||
},
|
||||
setMiterLimit(miterLimit: number) {
|
||||
ctx.miterLimit = miterLimit
|
||||
},
|
||||
setShadow(offsetX: number, offsetY: number, blur: number, color: string) {
|
||||
ctx.shadowOffsetX = offsetX
|
||||
ctx.shadowOffsetY = offsetY
|
||||
ctx.shadowBlur = blur
|
||||
ctx.shadowColor = color
|
||||
},
|
||||
setTextBaseline(textBaseline: 'top' | 'bottom' | 'middle') {
|
||||
ctx.textBaseline = textBaseline
|
||||
},
|
||||
createCircularGradient() {},
|
||||
draw() {},
|
||||
addColorStop() {}
|
||||
}) as unknown as UniApp.CanvasContext
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
@import '../common/abstracts/variable';
|
||||
@import '../common/abstracts/mixin';
|
||||
|
||||
@include b(backtop) {
|
||||
position: fixed;
|
||||
background-color: $-backtop-bg;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: $-color-gray-8;
|
||||
|
||||
@include when(circle) {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@include when(square) {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
import { baseProps, makeNumberProp, makeRequiredProp, makeStringProp } from '../common/props'
|
||||
|
||||
export const backtopProps = {
|
||||
...baseProps,
|
||||
/**
|
||||
* 页面滚动距离
|
||||
*/
|
||||
scrollTop: makeRequiredProp(Number),
|
||||
/**
|
||||
* 距离顶部多少距离时显示
|
||||
*/
|
||||
top: makeNumberProp(300),
|
||||
/**
|
||||
* 返回顶部滚动时间
|
||||
*/
|
||||
duration: makeNumberProp(100),
|
||||
/**
|
||||
* 层级
|
||||
*/
|
||||
zIndex: makeNumberProp(10),
|
||||
/**
|
||||
* icon样式
|
||||
*/
|
||||
iconStyle: makeStringProp(''),
|
||||
/**
|
||||
* 形状
|
||||
*/
|
||||
shape: makeStringProp('circle'),
|
||||
/**
|
||||
* 距离屏幕底部距离
|
||||
*/
|
||||
bottom: makeNumberProp(100),
|
||||
/**
|
||||
* 距离屏幕右边距离
|
||||
*/
|
||||
right: makeNumberProp(20)
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<wd-transition :show="show" name="fade">
|
||||
<view
|
||||
:class="`wd-backtop ${customClass} is-${shape}`"
|
||||
:style="`z-index: ${zIndex}; bottom: ${bottom}px; right: ${right}px; ${customStyle}`"
|
||||
@click="handleBacktop"
|
||||
>
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<wd-icon v-else name="backtop" size="20px" :custom-style="iconStyle" />
|
||||
</view>
|
||||
</wd-transition>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'wd-backtop',
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
virtualHost: true,
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { backtopProps } from './types'
|
||||
|
||||
const props = defineProps(backtopProps)
|
||||
|
||||
const show = computed(() => props.scrollTop > props.top)
|
||||
|
||||
function handleBacktop() {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
duration: props.duration
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
@@ -52,7 +52,7 @@
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
color: $-button-normal-color;
|
||||
transition: all 0.2s;
|
||||
transition: opacity 0.2s;
|
||||
user-select: none;
|
||||
font-weight: normal;
|
||||
|
||||
@@ -224,14 +224,7 @@
|
||||
|
||||
@include when(round) {
|
||||
border-radius: 999px;
|
||||
|
||||
&::after {
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
border-radius: 999px;
|
||||
}
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@include when(text) {
|
||||
|
@@ -200,3 +200,10 @@ export type CalendarOnShortcutsClickOption = {
|
||||
}
|
||||
|
||||
export type CalendarOnShortcutsClick = (option: CalendarOnShortcutsClickOption) => number | number[]
|
||||
|
||||
export type CalendarExpose = {
|
||||
/** 关闭时间选择器弹窗 */
|
||||
close: () => void
|
||||
/** 打开时间选择器弹窗 */
|
||||
open: () => void
|
||||
}
|
||||
|
@@ -123,7 +123,7 @@ import { useCell } from '../composables/useCell'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { calendarProps } from './types'
|
||||
import { calendarProps, type CalendarExpose } from './types'
|
||||
import type { CalendarType } from '../wd-calendar-view/types'
|
||||
const { translate } = useTranslate('calendar')
|
||||
|
||||
@@ -409,6 +409,11 @@ function handleShortcutClick(index: number) {
|
||||
handleConfirm()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose<CalendarExpose>({
|
||||
close,
|
||||
open
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { baseProps, makeArrayProp, makeBooleanProp, makeStringProp } from '../common/props'
|
||||
import { baseProps, makeArrayProp, makeBooleanProp, makeStringProp, makeNumericProp } from '../common/props'
|
||||
|
||||
import { type FormItemRule } from '../wd-form/types'
|
||||
|
||||
@@ -12,7 +12,7 @@ export const cellProps = {
|
||||
/**
|
||||
* 右侧内容
|
||||
*/
|
||||
value: String,
|
||||
value: makeNumericProp(''),
|
||||
/**
|
||||
* 图标类名
|
||||
*/
|
||||
|
@@ -32,8 +32,7 @@
|
||||
<view class="wd-cell__body">
|
||||
<!--文案内容-->
|
||||
<view :class="`wd-cell__value ${customValueClass}`">
|
||||
<template v-if="value">{{ value }}</template>
|
||||
<slot v-else></slot>
|
||||
<slot>{{ value }}</slot>
|
||||
</view>
|
||||
<!--箭头-->
|
||||
<wd-icon v-if="isLink" custom-class="wd-cell__arrow-right" name="arrow-right" />
|
||||
@@ -63,6 +62,7 @@ import { useCell } from '../composables/useCell'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { FORM_KEY } from '../wd-form/types'
|
||||
import { cellProps } from './types'
|
||||
import { isDef } from '../common/util'
|
||||
|
||||
const props = defineProps(cellProps)
|
||||
const emit = defineEmits(['click'])
|
||||
@@ -70,7 +70,7 @@ const emit = defineEmits(['click'])
|
||||
const cell = useCell()
|
||||
|
||||
const isBorder = computed(() => {
|
||||
return cell.border.value
|
||||
return isDef(cell.border.value) ? cell.border.value : props.border
|
||||
})
|
||||
|
||||
const { parent: form } = useParent(FORM_KEY)
|
||||
|
@@ -1,21 +1,20 @@
|
||||
<template>
|
||||
<view :class="`wd-circle ${customClass}`" :style="customStyle">
|
||||
<canvas :width="canvasSize" :height="canvasSize" :style="style" :id="canvasId" :canvas-id="canvasId"></canvas>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<canvas :style="canvasStyle" :id="canvasId" :canvas-id="canvasId" type="2d"></canvas>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<canvas :width="canvasSize" :height="canvasSize" :style="canvasStyle" :id="canvasId" :canvas-id="canvasId"></canvas>
|
||||
<!-- #endif -->
|
||||
|
||||
<view v-if="!text" class="wd-circle__text">
|
||||
<!-- 自定义提示内容 -->
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<cover-view v-else class="wd-circle__text">
|
||||
{{ text }}
|
||||
</cover-view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<!-- eslint-disable-next-line vue/valid-v-else -->
|
||||
|
||||
<text v-else class="wd-circle__text">
|
||||
{{ text }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@@ -29,10 +28,10 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
// Circle 环形进度条
|
||||
import { computed, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { addUnit, isObj, objToStyle, uuid } from '../common/util'
|
||||
import { circleProps } from './types'
|
||||
import { canvas2dAdapter } from '../common/canvasHelper'
|
||||
|
||||
// 大于等于0且小于等于100
|
||||
function format(rate: number) {
|
||||
@@ -47,23 +46,39 @@ const STEP = 1
|
||||
const props = defineProps(circleProps)
|
||||
|
||||
const progressColor = ref<string | CanvasGradient>('') // 进度条颜色
|
||||
const pixel = ref<number>(1) // 设备像素比
|
||||
|
||||
const currentValue = ref<number>(0) // 当前值
|
||||
const interval = ref<any>(null) // 定时器
|
||||
const canvasId = ref<string>(uuid()) // canvasId
|
||||
const pixelRatio = ref<number>(1) // 像素比
|
||||
const canvasId = ref<string>(`wd-circle${uuid()}`) // canvasId
|
||||
let ctx: UniApp.CanvasContext | null = null
|
||||
|
||||
// canvas渲染大小
|
||||
const canvasSize = computed(() => {
|
||||
return props.size * pixel.value
|
||||
let size = props.size
|
||||
// #ifdef MP-ALIPAY
|
||||
size = size * pixelRatio.value
|
||||
// #endif
|
||||
|
||||
return size
|
||||
})
|
||||
|
||||
// 进度条宽度
|
||||
const sWidth = computed(() => {
|
||||
let sWidth = props.strokeWidth
|
||||
// #ifdef MP-ALIPAY
|
||||
sWidth = sWidth * pixelRatio.value
|
||||
// #endif
|
||||
return sWidth
|
||||
})
|
||||
|
||||
// Circle 样式
|
||||
const style = computed(() => {
|
||||
const canvasStyle = computed(() => {
|
||||
const style = {
|
||||
width: addUnit(props.size),
|
||||
height: addUnit(props.size)
|
||||
}
|
||||
return `${objToStyle(style)}; ${props.customStyle}`
|
||||
return `${objToStyle(style)};`
|
||||
})
|
||||
|
||||
// 监听目标数值变化
|
||||
@@ -96,38 +111,9 @@ watch(
|
||||
{ immediate: false, deep: true }
|
||||
)
|
||||
|
||||
// 监听轨道颜色变化
|
||||
watch(
|
||||
() => props.layerColor,
|
||||
() => {
|
||||
drawCircle(currentValue.value)
|
||||
},
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
// 监听轨道宽度
|
||||
watch(
|
||||
() => props.strokeWidth,
|
||||
() => {
|
||||
drawCircle(currentValue.value)
|
||||
},
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
// 监听轨道展示方向
|
||||
watch(
|
||||
() => props.clockwise,
|
||||
() => {
|
||||
drawCircle(currentValue.value)
|
||||
},
|
||||
{ immediate: false }
|
||||
)
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
onBeforeMount(() => {
|
||||
pixel.value = uni.getSystemInfoSync().pixelRatio
|
||||
pixelRatio.value = uni.getSystemInfoSync().pixelRatio
|
||||
})
|
||||
// #endif
|
||||
|
||||
onMounted(() => {
|
||||
currentValue.value = props.modelValue
|
||||
@@ -143,32 +129,54 @@ const { proxy } = getCurrentInstance() as any
|
||||
* 获取canvas上下文
|
||||
*/
|
||||
function getContext() {
|
||||
if (!ctx) {
|
||||
return new Promise<UniApp.CanvasContext>((resolve) => {
|
||||
if (ctx) {
|
||||
return resolve(ctx)
|
||||
}
|
||||
// #ifndef MP-WEIXIN
|
||||
ctx = uni.createCanvasContext(canvasId.value, proxy)
|
||||
}
|
||||
return Promise.resolve(ctx)
|
||||
resolve(ctx)
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
uni
|
||||
.createSelectorQuery()
|
||||
.in(proxy)
|
||||
.select(`#${canvasId.value}`)
|
||||
.node((res) => {
|
||||
if (res && res.node) {
|
||||
const canvas = res.node
|
||||
ctx = canvas2dAdapter(canvas.getContext('2d') as CanvasRenderingContext2D)
|
||||
canvas.width = props.size * pixelRatio.value
|
||||
canvas.height = props.size * pixelRatio.value
|
||||
ctx.scale(pixelRatio.value, pixelRatio.value)
|
||||
resolve(ctx)
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置canvas
|
||||
*/
|
||||
function presetCanvas(context: any, strokeStyle: string | CanvasGradient, beginAngle: number, endAngle: number, fill?: string) {
|
||||
const canvasSize = props.size * pixel.value
|
||||
let strokeWidth = props.strokeWidth * pixel.value
|
||||
const position = canvasSize / 2
|
||||
let width = sWidth.value
|
||||
const position = canvasSize.value / 2
|
||||
if (!fill) {
|
||||
strokeWidth = strokeWidth / 2
|
||||
width = width / 2
|
||||
}
|
||||
const radius = position - strokeWidth / 2
|
||||
const radius = position - width / 2
|
||||
context.strokeStyle = strokeStyle
|
||||
context.setLineWidth(strokeWidth)
|
||||
context.setStrokeStyle(strokeStyle)
|
||||
context.setLineWidth(width)
|
||||
context.setLineCap(props.strokeLinecap)
|
||||
|
||||
context.beginPath()
|
||||
context.arc(position, position, radius, beginAngle, endAngle, !props.clockwise)
|
||||
context.stroke()
|
||||
if (fill) {
|
||||
context.setLineWidth(strokeWidth)
|
||||
context.setLineWidth(width)
|
||||
context.setFillStyle(fill)
|
||||
context.fill()
|
||||
}
|
||||
@@ -184,14 +192,13 @@ function renderLayerCircle(context: UniApp.CanvasContext) {
|
||||
* 渲染进度条
|
||||
*/
|
||||
function renderHoverCircle(context: UniApp.CanvasContext, formatValue: number) {
|
||||
const canvasSize = props.size * pixel.value
|
||||
// 结束角度
|
||||
const progress = PERIMETER * (formatValue / 100)
|
||||
const endAngle = props.clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress)
|
||||
|
||||
// 设置进度条颜色
|
||||
if (isObj(props.color)) {
|
||||
const LinearColor = context.createLinearGradient(canvasSize, 0, 0, 0)
|
||||
const LinearColor = context.createLinearGradient(canvasSize.value, 0, 0, 0)
|
||||
Object.keys(props.color)
|
||||
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
||||
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, (props.color as Record<string, any>)[key]))
|
||||
@@ -207,12 +214,11 @@ function renderHoverCircle(context: UniApp.CanvasContext, formatValue: number) {
|
||||
* 进度值为0时渲染一个圆点
|
||||
*/
|
||||
function renderDot(context: UniApp.CanvasContext) {
|
||||
const canvasSize = props.size * pixel.value
|
||||
const strokeWidth = props.strokeWidth * pixel.value // 管道宽度=小圆点直径
|
||||
const position = canvasSize / 2 // 坐标
|
||||
const strokeWidth = sWidth.value // 管道宽度=小圆点直径
|
||||
const position = canvasSize.value / 2 // 坐标
|
||||
// 设置进度条颜色
|
||||
if (isObj(props.color)) {
|
||||
const LinearColor = context.createLinearGradient(canvasSize, 0, 0, 0)
|
||||
const LinearColor = context.createLinearGradient(canvasSize.value, 0, 0, 0)
|
||||
Object.keys(props.color)
|
||||
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
||||
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, (props.color as Record<string, any>)[key]))
|
||||
@@ -230,9 +236,8 @@ function renderDot(context: UniApp.CanvasContext) {
|
||||
* 画圆
|
||||
*/
|
||||
function drawCircle(currentValue: number) {
|
||||
const canvasSize = props.size * pixel.value
|
||||
getContext().then((context) => {
|
||||
context.clearRect(0, 0, canvasSize, canvasSize)
|
||||
context.clearRect(0, 0, canvasSize.value, canvasSize.value)
|
||||
renderLayerCircle(context)
|
||||
|
||||
const formatValue = format(currentValue)
|
||||
|
@@ -61,7 +61,7 @@ async function validate(prop?: string): Promise<{ valid: boolean; errors: ErrorM
|
||||
valid = false
|
||||
break
|
||||
}
|
||||
if (rule.pattern && !rule.pattern.test(props.model[prop])) {
|
||||
if (rule.pattern && !rule.pattern.test(value)) {
|
||||
errors.push({
|
||||
prop,
|
||||
message: rule.message
|
||||
@@ -71,7 +71,7 @@ async function validate(prop?: string): Promise<{ valid: boolean; errors: ErrorM
|
||||
}
|
||||
const { validator, ...ruleWithoutValidator } = rule
|
||||
if (validator) {
|
||||
const result = validator(props.model[prop], ruleWithoutValidator)
|
||||
const result = validator(value, ruleWithoutValidator)
|
||||
if (isPromise(result)) {
|
||||
promises.push(
|
||||
result
|
||||
|
@@ -1,6 +1,16 @@
|
||||
<template>
|
||||
<view :class="rootClass" @click="handleClick" :style="rootStyle">
|
||||
<image :class="`wd-img__image ${customImage}`" :src="src" :mode="mode" :lazy-load="lazyLoad" @load="handleLoad" @error="handleError" />
|
||||
<image
|
||||
:class="`wd-img__image ${customImage}`"
|
||||
:style="status !== 'success' ? 'width: 0;height: 0;' : ''"
|
||||
:src="src"
|
||||
:mode="mode"
|
||||
:lazy-load="lazyLoad"
|
||||
@load="handleLoad"
|
||||
@error="handleError"
|
||||
/>
|
||||
<slot v-if="status === 'loading'" name="loading"></slot>
|
||||
<slot v-if="status === 'error'" name="error"></slot>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@@ -15,7 +25,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { addUnit, isDef, objToStyle } from '../common/util'
|
||||
import { imgProps } from './types'
|
||||
|
||||
@@ -41,7 +51,10 @@ const rootClass = computed(() => {
|
||||
return `wd-img ${props.round ? 'is-round' : ''} ${props.customClass}`
|
||||
})
|
||||
|
||||
const status = ref<'loading' | 'error' | 'success'>('loading')
|
||||
|
||||
function handleError(event: Event) {
|
||||
status.value = 'error'
|
||||
emit('error', event)
|
||||
}
|
||||
function handleClick() {
|
||||
@@ -53,6 +66,7 @@ function handleClick() {
|
||||
emit('click')
|
||||
}
|
||||
function handleLoad(event: Event) {
|
||||
status.value = 'success'
|
||||
emit('load', event)
|
||||
}
|
||||
</script>
|
||||
|
@@ -0,0 +1,35 @@
|
||||
@import "./../common/abstracts/_mixin.scss";
|
||||
@import "./../common/abstracts/variable.scss";
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(index-anchor) {
|
||||
background-color: $-color-gray-8;
|
||||
color: $-color-white;
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-DINGTALK
|
||||
@include b(index-anchor-ding) {
|
||||
|
||||
@include when(sticky){
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
@include b(index-anchor) {
|
||||
background-color: $-color-gray-2;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
color: $-color-title;
|
||||
|
||||
@include when(sticky){
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { baseProps, makeRequiredProp } from '../common/props'
|
||||
|
||||
export const indexAnchorProps = {
|
||||
...baseProps,
|
||||
index: makeRequiredProp([String, Number])
|
||||
}
|
||||
|
||||
export type IndexAnchorProps = ExtractPropTypes<typeof indexAnchorProps>
|
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<!-- #ifdef MP-DINGTALK -->
|
||||
<view :class="`wd-index-anchor-ding ${isSticky ? 'is-sticky' : ''}`">
|
||||
<!-- #endif -->
|
||||
<view :class="`wd-index-anchor ${isSticky ? 'is-sticky' : ''} ${customClass}`" :style="customStyle" :id="indexAnchorId">
|
||||
<slot>
|
||||
{{ index }}
|
||||
</slot>
|
||||
</view>
|
||||
<!-- #ifdef MP-DINGTALK -->
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { indexAnchorProps } from './type'
|
||||
import { onMounted, getCurrentInstance, ref, computed } from 'vue'
|
||||
import { indexBarInjectionKey } from '../wd-index-bar/type'
|
||||
import { getRect, isDef, uuid } from '../common/util'
|
||||
import { useParent } from '../composables/useParent'
|
||||
|
||||
const props = defineProps(indexAnchorProps)
|
||||
|
||||
const { parent: indexBar } = useParent(indexBarInjectionKey)
|
||||
|
||||
const indexAnchorId = ref<string>(`indexBar${uuid()}`)
|
||||
|
||||
const { proxy } = getCurrentInstance()!
|
||||
|
||||
const isSticky = computed(() => {
|
||||
return indexBar && indexBar.props.sticky && indexBar.anchorState.activeIndex === props.index
|
||||
})
|
||||
|
||||
function getInfo() {
|
||||
getRect(`#${indexAnchorId.value}`, false, proxy).then((res) => {
|
||||
if (isDef(indexBar)) {
|
||||
const anchor = indexBar.anchorState.anchorList.find((v) => v.index === props.index)!
|
||||
anchor.top = res.top!
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (isDef(indexBar)) {
|
||||
indexBar.anchorState.anchorList.push({ top: 0, index: props.index })
|
||||
}
|
||||
getInfo()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
@@ -0,0 +1,39 @@
|
||||
@import "./../common/abstracts/_mixin.scss";
|
||||
@import "./../common/abstracts/variable.scss";
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(index-bar) {
|
||||
@include e(index) {
|
||||
color: $-color-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(index-bar) {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@include e(content) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@include e(sidebar) {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 4px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
@include e(index) {
|
||||
font-size: 12px;
|
||||
font-weight: $-fw-medium;
|
||||
color: $-color-title;
|
||||
padding: 4px 6px;
|
||||
|
||||
@include when(active) {
|
||||
color: $-color-theme;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
import type { Ref } from 'vue'
|
||||
import type { InjectionKey } from 'vue'
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { makeBooleanProp } from '../common/props'
|
||||
|
||||
export type AnchorIndex = number | string
|
||||
|
||||
export interface AnchorItem {
|
||||
top: number
|
||||
index: AnchorIndex
|
||||
}
|
||||
|
||||
export const indexBarProps = {
|
||||
/**
|
||||
* @description 索引是否吸顶
|
||||
*/
|
||||
sticky: makeBooleanProp(false)
|
||||
}
|
||||
|
||||
export type IndexBarProps = ExtractPropTypes<typeof indexBarProps>
|
||||
|
||||
export type InderBarProvide = {
|
||||
props: { sticky?: boolean }
|
||||
anchorState: {
|
||||
anchorList: AnchorItem[] // 锚点列表
|
||||
activeIndex: AnchorIndex | null // 当前激活的索引
|
||||
}
|
||||
}
|
||||
|
||||
export const indexBarInjectionKey: InjectionKey<InderBarProvide> = Symbol('wd-index-bar')
|
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<view class="wd-index-bar" :id="indexBarId">
|
||||
<!-- #ifdef MP-DINGTALK -->
|
||||
<view class="wd-index-bar" :id="indexBarId">
|
||||
<!-- #endif -->
|
||||
<scroll-view :scrollTop="scrollTop" :scroll-y="true" class="wd-index-bar__content" @scroll="hanleScroll">
|
||||
<slot></slot>
|
||||
</scroll-view>
|
||||
<view
|
||||
class="wd-index-bar__sidebar"
|
||||
@touchmove.stop.prevent="handleTouchMove"
|
||||
@touchend.stop.prevent="handleTouchEnd"
|
||||
@touchcancel.stop.prevent="handleTouchEnd"
|
||||
>
|
||||
<view
|
||||
class="wd-index-bar__index"
|
||||
:class="{ 'is-active': item.index === state.activeIndex }"
|
||||
v-for="item in state.anchorList"
|
||||
:key="item.index"
|
||||
>
|
||||
{{ item.index }}
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef MP-DINGTALK -->
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { AnchorItem, AnchorIndex } from './type'
|
||||
import { indexBarInjectionKey, indexBarProps } from './type'
|
||||
import { ref, getCurrentInstance, onMounted, reactive } from 'vue'
|
||||
import { getRect, isDef, uuid } from '../common/util'
|
||||
import { useChildren } from '../composables/useChildren'
|
||||
|
||||
const props = defineProps(indexBarProps)
|
||||
|
||||
const indexBarId = ref<string>(`indexBar${uuid()}`)
|
||||
|
||||
const { proxy } = getCurrentInstance()!
|
||||
|
||||
const state = reactive({
|
||||
activeIndex: null as AnchorIndex | null,
|
||||
anchorList: [] as AnchorItem[]
|
||||
})
|
||||
|
||||
const { linkChildren } = useChildren(indexBarInjectionKey)
|
||||
|
||||
linkChildren({ props, anchorState: state })
|
||||
|
||||
const scrollTop = ref(0)
|
||||
|
||||
// 组件距离页面顶部的高度
|
||||
let offsetTop = 0
|
||||
let sidebarInfo = {
|
||||
// 侧边栏距离顶部的高度
|
||||
offsetTop: 0,
|
||||
// 高度固定24px
|
||||
indexHeight: 24
|
||||
}
|
||||
|
||||
function init() {
|
||||
setTimeout(() => {
|
||||
state.activeIndex = state.anchorList[0]?.index
|
||||
|
||||
Promise.all([
|
||||
getRect(`#${indexBarId.value}`, false, proxy),
|
||||
getRect('.wd-index-bar__sidebar', false, proxy),
|
||||
getRect('.wd-index-bar__index', false, proxy)
|
||||
]).then(([bar, sidebar, index]) => {
|
||||
offsetTop = bar.top!
|
||||
sidebarInfo.offsetTop = sidebar.top!
|
||||
sidebarInfo.indexHeight = index.height!
|
||||
})
|
||||
}, 100)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
function hanleScroll(scrollEvent: any) {
|
||||
const { detail } = scrollEvent
|
||||
const anchor = state.anchorList.find((item, index) => {
|
||||
if (!isDef(state.anchorList[index + 1])) return true
|
||||
if (item.top - offsetTop <= detail.scrollTop && state.anchorList[index + 1].top - offsetTop > detail.scrollTop) return true
|
||||
return false
|
||||
})!
|
||||
state.activeIndex = anchor.index
|
||||
}
|
||||
|
||||
function getAnchorByPageY(pageY: number) {
|
||||
const y = pageY - sidebarInfo.offsetTop
|
||||
let idx = Math.floor(y / sidebarInfo.indexHeight)
|
||||
if (idx < 0) idx = 0
|
||||
else if (idx > state.anchorList.length - 1) idx = state.anchorList.length - 1
|
||||
return state.anchorList[idx]
|
||||
}
|
||||
|
||||
function handleTouchMove(e: TouchEvent) {
|
||||
const clientY = e.touches[0].pageY
|
||||
if (state.activeIndex === getAnchorByPageY(clientY).index) {
|
||||
return
|
||||
}
|
||||
state.activeIndex = getAnchorByPageY(clientY).index
|
||||
scrollTop.value = getAnchorByPageY(clientY).top - offsetTop
|
||||
}
|
||||
|
||||
function handleTouchEnd(e: TouchEvent) {
|
||||
const clientY = e.changedTouches[0].pageY
|
||||
scrollTop.value = getAnchorByPageY(clientY).top - offsetTop
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
@@ -61,7 +61,12 @@ export const inputProps = {
|
||||
/**
|
||||
* 原生属性,最大长度
|
||||
*/
|
||||
maxlength: makeNumberProp(-1),
|
||||
maxlength: {
|
||||
type: Number,
|
||||
// #ifndef MP-ALIPAY
|
||||
default: -1
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 原生属性,禁用
|
||||
*/
|
||||
|
@@ -57,7 +57,7 @@
|
||||
<text
|
||||
:class="[
|
||||
inputValue && String(inputValue).length > 0 ? 'wd-input__count-current' : '',
|
||||
String(inputValue).length > maxlength ? 'is-error' : ''
|
||||
String(inputValue).length > maxlength! ? 'is-error' : ''
|
||||
]"
|
||||
>
|
||||
{{ String(inputValue).length }}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-03-15 20:40:34
|
||||
* @LastEditTime: 2024-03-18 14:59:32
|
||||
* @LastEditTime: 2024-05-27 18:49:28
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-loading\types.ts
|
||||
@@ -10,13 +10,12 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { baseProps, makeNumericProp, makeStringProp } from '../common/props'
|
||||
|
||||
// 'circle-outline' | 'circle-ring' 废弃
|
||||
export type LoadingType = 'outline' | 'ring' | 'circle-outline' | 'circle-ring' // 提示信息加载状态类型
|
||||
export type LoadingType = 'outline' | 'ring' // 提示信息加载状态类型
|
||||
|
||||
export const loadingProps = {
|
||||
...baseProps,
|
||||
/**
|
||||
* 加载指示器类型,可选值:'outline' | 'ring' | 'circle-outline' | 'circle-ring'
|
||||
* 加载指示器类型,可选值:'outline' | 'ring'
|
||||
*/
|
||||
type: makeStringProp<LoadingType>('ring'),
|
||||
/**
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<view :class="rootClass" :style="rootStyle">
|
||||
<view v-if="!type || type === 'ring' || type === 'circle-ring'" class="wd-loading__body">
|
||||
<view v-if="!type || type === 'ring'" class="wd-loading__body">
|
||||
<view class="wd-loading__svg" :style="`background-image: url(${svg});`"></view>
|
||||
</view>
|
||||
|
||||
<view v-if="type === 'circle-outline' || type === 'outline'" class="wd-loading__body">
|
||||
<view v-if="type === 'outline'" class="wd-loading__body">
|
||||
<view class="wd-loading__svg" :style="`background-image: url(${svg});`"></view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue'
|
||||
import base64 from '../common/base64'
|
||||
import { gradient, context, objToStyle, addUnit } from '../common/util'
|
||||
import { gradient, context, objToStyle, addUnit, isDef } from '../common/util'
|
||||
import { loadingProps } from './types'
|
||||
|
||||
const svgDefineId = context.id++
|
||||
@@ -86,19 +86,8 @@ onBeforeMount(() => {
|
||||
|
||||
function buildSvg() {
|
||||
const { type, color } = props
|
||||
let adaptType: 'outline' | 'ring' = 'ring'
|
||||
// 2.2.0 版本向下兼容 circle-outline 和 circle-ring;
|
||||
if (type === 'circle-outline') {
|
||||
adaptType = 'outline'
|
||||
} else if (type === 'outline') {
|
||||
adaptType = 'outline'
|
||||
} else if (type === 'circle-ring') {
|
||||
adaptType = 'ring'
|
||||
}
|
||||
const svgStr = `"data:image/svg+xml;base64,${base64(
|
||||
adaptType === 'ring' ? icon[adaptType](color, intermediateColor.value) : icon[adaptType](color)
|
||||
)}"`
|
||||
|
||||
let ringType: 'outline' | 'ring' = isDef(type) ? type : 'ring'
|
||||
const svgStr = `"data:image/svg+xml;base64,${base64(ringType === 'ring' ? icon[ringType](color, intermediateColor.value) : icon[ringType](color))}"`
|
||||
svg.value = svgStr
|
||||
}
|
||||
</script>
|
||||
|
@@ -60,7 +60,6 @@
|
||||
font-size: $-message-box-content-fs;
|
||||
text-align: center;
|
||||
overflow: auto;
|
||||
word-break: break-all;
|
||||
line-height: 20px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
|
@@ -11,29 +11,20 @@
|
||||
:duration="200"
|
||||
>
|
||||
<view :class="rootClass">
|
||||
<!--内容部分-->
|
||||
<view :class="bodyClass">
|
||||
<!--公共title-->
|
||||
<view v-if="title" class="wd-message-box__title">
|
||||
{{ title }}
|
||||
</view>
|
||||
<!--其它类型-->
|
||||
<view class="wd-message-box__content">
|
||||
<!--prompt类型-->
|
||||
<block v-if="type === 'prompt'">
|
||||
<!--输入框-->
|
||||
<wd-input v-model="inputValue" :type="inputType" size="large" :placeholder="inputPlaceholder || '请输入'" @input="inputValChange" />
|
||||
<!--错误提示-->
|
||||
<view v-if="showErr" class="wd-message-box__input-error">
|
||||
{{ inputError || translate('inputNoValidate') }}
|
||||
</view>
|
||||
</block>
|
||||
<!--使用插槽-->
|
||||
<slot>{{ msg }}</slot>
|
||||
<!--使用文本-->
|
||||
</view>
|
||||
</view>
|
||||
<!--action按钮组合-->
|
||||
<view :class="`wd-message-box__actions ${showCancelButton ? 'wd-message-box__flex' : 'wd-message-box__block'}`">
|
||||
<wd-button type="info" block v-if="showCancelButton" custom-style="margin-right: 16px;" @click="toggleModal('cancel')">
|
||||
{{ cancelButtonText || translate('cancel') }}
|
||||
@@ -183,15 +174,13 @@ watch(
|
||||
)
|
||||
|
||||
/**
|
||||
* @description 关闭消息框的统一主调 handle
|
||||
* @param {'cancel' | 'confirm'} action
|
||||
* 点击操作
|
||||
* @param action
|
||||
*/
|
||||
function toggleModal(action: 'confirm' | 'cancel' | 'modal') {
|
||||
// closeOnClickModal为false,此时点击蒙层没任何效果
|
||||
if (action === 'modal' && !closeOnClickModal.value) {
|
||||
return
|
||||
}
|
||||
// prompt类型的弹窗 文案没有通过校验,点击了确定按钮没有任何效果
|
||||
if (type.value === 'prompt' && action === 'confirm' && !validate()) {
|
||||
return
|
||||
}
|
||||
@@ -228,6 +217,10 @@ function toggleModal(action: 'confirm' | 'cancel' | 'modal') {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认回调
|
||||
* @param result
|
||||
*/
|
||||
function handleConfirm(result: MessageResult) {
|
||||
show.value = false
|
||||
if (isFunction(onConfirm)) {
|
||||
@@ -235,6 +228,10 @@ function handleConfirm(result: MessageResult) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消回调
|
||||
* @param result
|
||||
*/
|
||||
function handleCancel(result: MessageResult) {
|
||||
show.value = false
|
||||
if (isFunction(onCancel)) {
|
||||
|
@@ -5,19 +5,22 @@
|
||||
<view class="wd-navbar__capsule" v-if="$slots.capsule">
|
||||
<slot name="capsule" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
:class="`wd-navbar__left ${leftDisabled ? 'is-disabled' : ''}`"
|
||||
:hover-class="leftDisabled ? '' : 'wd-navbar__left--hover'"
|
||||
:hover-class="leftDisabled || $slots.left ? '' : 'wd-navbar__left--hover'"
|
||||
hover-stay-time="70"
|
||||
@click="handleClickLeft"
|
||||
v-if="!$slots.capsule && ($slots.left || leftArrow || leftText)"
|
||||
v-else-if="!$slots.left"
|
||||
>
|
||||
<slot name="left" />
|
||||
<block v-if="!$slots.left && (leftArrow || leftText)">
|
||||
<wd-icon v-if="leftArrow" size="24px" name="arrow-left" custom-class="wd-navbar__arrow" />
|
||||
<view v-if="leftText" class="wd-navbar__text">{{ leftText }}</view>
|
||||
</block>
|
||||
<wd-icon v-if="leftArrow" size="24px" name="arrow-left" custom-class="wd-navbar__arrow" />
|
||||
<view v-if="leftText" class="wd-navbar__text">{{ leftText }}</view>
|
||||
</view>
|
||||
|
||||
<view v-else :class="`wd-navbar__left ${leftDisabled ? 'is-disabled' : ''}`" @click="handleClickLeft">
|
||||
<slot name="left" />
|
||||
</view>
|
||||
|
||||
<view class="wd-navbar__title">
|
||||
<slot name="title" />
|
||||
<block v-if="!$slots.title && title">{{ title }}</block>
|
||||
|
@@ -14,6 +14,7 @@
|
||||
@include b(number-keyboard) {
|
||||
width: 100%;
|
||||
background: $-number-keyboard-background;
|
||||
color: $-color-black;
|
||||
user-select: none;
|
||||
|
||||
@include m(with-title) {
|
||||
|
@@ -174,6 +174,9 @@ function selectWithIndex(columnIndex: number, rowIndex: number) {
|
||||
throw Error(`The value to select with Col:${columnIndex} Row:${rowIndex} is correct`)
|
||||
}
|
||||
const select: number[] = deepClone(selectedIndex.value)
|
||||
select[columnIndex] = rowIndex
|
||||
selectedIndex.value = deepClone(select)
|
||||
|
||||
// 被禁用的无法选中,选中距离它最近的未被禁用的
|
||||
if (col[rowIndex].disabled) {
|
||||
// 寻找值为0或最最近的未被禁用的节点的索引
|
||||
@@ -189,10 +192,10 @@ function selectWithIndex(columnIndex: number, rowIndex: number) {
|
||||
} else if (select[columnIndex] === undefined) {
|
||||
select[columnIndex] = 0
|
||||
}
|
||||
} else {
|
||||
select[columnIndex] = rowIndex
|
||||
nextTick(() => {
|
||||
selectedIndex.value = deepClone(select)
|
||||
})
|
||||
}
|
||||
selectedIndex.value = deepClone(select)
|
||||
return selectedIndex.value
|
||||
}
|
||||
|
||||
|
@@ -89,7 +89,7 @@ export default {
|
||||
import { getCurrentInstance, onBeforeMount, ref, watch, computed, onMounted, nextTick } from 'vue'
|
||||
import { deepClone, defaultDisplayFormat, getType, isArray, isDef, isFunction } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { type ColumnItem, formatArray } from '../wd-picker-view/types'
|
||||
import { type ColumnItem, formatArray, type PickerViewInstance } from '../wd-picker-view/types'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
@@ -99,7 +99,7 @@ const { translate } = useTranslate('picker')
|
||||
const props = defineProps(pickerProps)
|
||||
const emit = defineEmits(['confirm', 'open', 'cancel', 'update:modelValue'])
|
||||
|
||||
const pickerViewWd = ref<any>(null)
|
||||
const pickerViewWd = ref<PickerViewInstance | null>(null)
|
||||
const cell = useCell()
|
||||
|
||||
const innerLoading = ref<boolean>(false) // 内部控制是否loading
|
||||
@@ -124,12 +124,8 @@ watch(
|
||||
if (fn && !isFunction(fn)) {
|
||||
console.error('The type of displayFormat must be Function')
|
||||
}
|
||||
if (pickerViewWd.value && pickerViewWd.value.selectedIndex && pickerViewWd.value.selectedIndex.length !== 0) {
|
||||
if (isDef(props.modelValue) && props.modelValue !== '') {
|
||||
setShowValue(pickerViewWd.value.getSelects())
|
||||
} else {
|
||||
showValue.value = ''
|
||||
}
|
||||
if (pickerViewWd.value && pickerViewWd.value.getSelectedIndex().length !== 0) {
|
||||
handleShowValueUpdate(props.modelValue)
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -143,17 +139,7 @@ watch(
|
||||
(newValue) => {
|
||||
pickerValue.value = newValue
|
||||
// 获取初始选中项,并展示初始选中文案
|
||||
if (isDef(newValue) && newValue !== '') {
|
||||
if (pickerViewWd.value && pickerViewWd.value.getSelects) {
|
||||
nextTick(() => {
|
||||
setShowValue(pickerViewWd.value!.getSelects())
|
||||
})
|
||||
} else {
|
||||
setShowValue(getSelects(newValue)!)
|
||||
}
|
||||
} else {
|
||||
showValue.value = ''
|
||||
}
|
||||
handleShowValueUpdate(newValue)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
@@ -167,17 +153,7 @@ watch(
|
||||
displayColumns.value = newValue
|
||||
resetColumns.value = newValue
|
||||
// 获取初始选中项,并展示初始选中文案
|
||||
if (isDef(props.modelValue) && props.modelValue !== '') {
|
||||
if (pickerViewWd.value && pickerViewWd.value.getSelects) {
|
||||
nextTick(() => {
|
||||
setShowValue(pickerViewWd.value!.getSelects())
|
||||
})
|
||||
} else {
|
||||
setShowValue(getSelects(props.modelValue)!)
|
||||
}
|
||||
} else {
|
||||
showValue.value = ''
|
||||
}
|
||||
handleShowValueUpdate(props.modelValue)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
@@ -226,10 +202,7 @@ const isRequired = computed(() => {
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
onMounted(() => {
|
||||
isDef(props.modelValue) && props.modelValue !== '' && setShowValue(getSelects(props.modelValue)!)
|
||||
if (isDef(props.modelValue) && props.modelValue !== '' && pickerViewWd.value && pickerViewWd.value.getSelects) {
|
||||
setShowValue(pickerViewWd.value!.getSelects())
|
||||
}
|
||||
handleShowValueUpdate(props.modelValue)
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
@@ -237,6 +210,25 @@ onBeforeMount(() => {
|
||||
resetColumns.value = deepClone(props.columns)
|
||||
})
|
||||
|
||||
/**
|
||||
* 值变更时更新显示内容
|
||||
* @param value
|
||||
*/
|
||||
function handleShowValueUpdate(value: string | number | Array<string | number>) {
|
||||
// 获取初始选中项,并展示初始选中文案
|
||||
if ((isArray(value) && value.length > 0) || (isDef(value) && !isArray(value) && value !== '')) {
|
||||
if (pickerViewWd.value) {
|
||||
nextTick(() => {
|
||||
setShowValue(pickerViewWd.value!.getSelects())
|
||||
})
|
||||
} else {
|
||||
setShowValue(getSelects(value)!)
|
||||
}
|
||||
} else {
|
||||
showValue.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 根据传入的value,picker组件获取当前cell展示值。
|
||||
* @param {String|Number|Array<String|Number|Array<any>>}value
|
||||
@@ -344,6 +336,7 @@ function handleConfirm() {
|
||||
popupShow.value = false
|
||||
resetColumns.value = deepClone(columns)
|
||||
emit('update:modelValue', values)
|
||||
|
||||
setShowValue(selects)
|
||||
emit('confirm', {
|
||||
value: values,
|
||||
|
@@ -88,6 +88,13 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.placement,
|
||||
() => {
|
||||
popover.init(props.placement, props.visibleArrow, selector)
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
|
@@ -38,7 +38,7 @@ import { segmentedProps, type SegmentedInfo, type SegmentedOption } from './type
|
||||
const $item = '.wd-segmented__item'
|
||||
|
||||
const props = defineProps(segmentedProps)
|
||||
const emit = defineEmits(['update:value', 'change'])
|
||||
const emit = defineEmits(['update:value', 'change', 'click'])
|
||||
|
||||
const sectionItemInfo = reactive<SegmentedInfo>({
|
||||
width: 0,
|
||||
@@ -130,6 +130,7 @@ function handleClick(option: string | number | SegmentedOption, index: number) {
|
||||
updateActiveStyle()
|
||||
emit('update:value', value)
|
||||
emit('change', isObj(option) ? option : { value })
|
||||
emit('click', isObj(option) ? option : { value })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { PropType, CSSProperties, ExtractPropTypes } from 'vue'
|
||||
import type { PropType, ExtractPropTypes, CSSProperties } from 'vue'
|
||||
import { makeArrayProp, makeBooleanProp, makeStringProp } from '../common/props'
|
||||
|
||||
type SkeletonTheme = 'text' | 'avatar' | 'paragraph' | 'image'
|
||||
@@ -16,7 +16,7 @@ export type SkeletonRowColObj = {
|
||||
borderRadius?: string | number
|
||||
backgroundColor?: string
|
||||
}
|
||||
export type SkeletonRowCol = Array<number | SkeletonRowColObj | Array<SkeletonRowColObj>>
|
||||
export type SkeletonRowCol = number | SkeletonRowColObj | Array<SkeletonRowColObj>
|
||||
export type SkeletonThemeVars = {
|
||||
notifyPadding?: string
|
||||
notifyFontSize?: string
|
||||
|
@@ -9,11 +9,14 @@
|
||||
-->
|
||||
<template>
|
||||
<view :class="`wd-skeleton ${customClass}`" :style="customStyle">
|
||||
<view class="wd-skeleton__content" v-if="parsedRowCols.length">
|
||||
<view class="wd-skeleton__content" v-if="show">
|
||||
<view class="wd-skeleton__row" v-for="(row, index) of parsedRowCols" :key="`row-${index}`">
|
||||
<view v-for="(col, idx) of row" :key="`col-${idx}`" :class="col.class" :style="col.style" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@@ -45,7 +48,7 @@ const themeMap = {
|
||||
paragraph: [1, 1, 1, { width: '55%' }]
|
||||
}
|
||||
const props = defineProps(skeletonProps)
|
||||
const rowCols = ref<SkeletonRowCol>([])
|
||||
const rowCols = ref<SkeletonRowCol[]>([])
|
||||
|
||||
const parsedRowCols = computed(() => {
|
||||
return rowCols.value.map((item) => {
|
||||
@@ -107,6 +110,8 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const show = computed(() => props.loading == undefined || props.loading === true)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -57,10 +57,10 @@ function handleClick() {
|
||||
}
|
||||
}
|
||||
}
|
||||
emit('update:modelValue', value)
|
||||
emit('change', {
|
||||
value
|
||||
})
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-04-08 22:34:01
|
||||
* @LastEditTime: 2024-06-01 16:04:56
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-sticky-box/types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import type { ComponentInternalInstance, InjectionKey } from 'vue'
|
||||
|
||||
export type stickyBoxProvide = {
|
||||
boxStyle: {
|
||||
height: number // 高度
|
||||
width: number // 宽度
|
||||
}
|
||||
observerForChild: (child: ComponentInternalInstance) => void // 监听子组件
|
||||
}
|
||||
|
||||
export const STICKY_BOX_KEY: InjectionKey<stickyBoxProvide> = Symbol('wd-sticky-box')
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view style="position: relative">
|
||||
<view :class="`wd-sticky-box ${props.customClass}`" :style="customStyle" id="styckyBoxId">
|
||||
<wd-resize @resize="resizeHandler">
|
||||
<view :class="`wd-sticky-box ${props.customClass}`" :style="customStyle" :id="styckyBoxId">
|
||||
<wd-resize @resize="handleResize">
|
||||
<slot />
|
||||
</wd-resize>
|
||||
</view>
|
||||
@@ -20,38 +20,43 @@ export default {
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getCurrentInstance, onBeforeMount, provide, ref } from 'vue'
|
||||
import { getCurrentInstance, onBeforeMount, reactive, ref } from 'vue'
|
||||
import { getRect, uuid } from '../common/util'
|
||||
import { baseProps } from '../common/props'
|
||||
import { STICKY_BOX_KEY } from './types'
|
||||
import { useChildren } from '../composables/useChildren'
|
||||
|
||||
const props = defineProps(baseProps)
|
||||
|
||||
const styckyBoxId = ref<string>(`wd-sticky-box${uuid()}`)
|
||||
|
||||
const observerMap = ref<Map<any, any>>(new Map())
|
||||
const height = ref<number>(0)
|
||||
const width = ref<number>(0)
|
||||
|
||||
const stickyList: any[] = [] // 子元素sticky列表
|
||||
const boxStyle = reactive({
|
||||
height: 0,
|
||||
width: 0
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const instance = getCurrentInstance() as any
|
||||
|
||||
provide('box-height', height)
|
||||
provide('box-width', width)
|
||||
provide('observerForChild', observerForChild)
|
||||
const { children: stickyList, linkChildren } = useChildren(STICKY_BOX_KEY)
|
||||
linkChildren({
|
||||
boxStyle: boxStyle,
|
||||
observerForChild
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
observerMap.value = new Map()
|
||||
})
|
||||
|
||||
/**
|
||||
* @description wd-sticky-box 尺寸发生变化时,重新监听所有的viewport
|
||||
* 容器大小变化后重新监听sticky组件与box组件的交叉状态
|
||||
* @param detail
|
||||
*/
|
||||
function resizeHandler(detail: any) {
|
||||
function handleResize(detail: any) {
|
||||
// 相对的容器大小改变后,同步设置 wd-sticky-box 的大小
|
||||
width.value = detail.width
|
||||
height.value = detail.height
|
||||
boxStyle.width = detail.width
|
||||
boxStyle.height = detail.height
|
||||
// wd-sticky-box 大小变化时,重新监听所有吸顶元素
|
||||
const temp = observerMap.value
|
||||
observerMap.value = new Map()
|
||||
@@ -67,8 +72,8 @@ function resizeHandler(detail: any) {
|
||||
temp.clear()
|
||||
}
|
||||
/**
|
||||
* @description 删除 wd-sticky 废弃的监听器
|
||||
* @param child
|
||||
* 删除对指定sticky的监听
|
||||
* @param child 指定的子组件
|
||||
*/
|
||||
function deleteObserver(child: any) {
|
||||
const observer = observerMap.value.get(child.$.uid)
|
||||
@@ -77,63 +82,70 @@ function deleteObserver(child: any) {
|
||||
observerMap.value.delete(child.$.uid)
|
||||
}
|
||||
/**
|
||||
* @description 为 wd-sticky 创建监听器
|
||||
* @param child
|
||||
* 针对指定sticky添加监听
|
||||
* @param child 指定的子组件
|
||||
*/
|
||||
function createObserver(child: any) {
|
||||
const observer = uni.createIntersectionObserver(instance)
|
||||
const observer = uni.createIntersectionObserver(proxy, { thresholds: [0, 0.5] })
|
||||
observerMap.value.set(child.$.uid, observer)
|
||||
return observer
|
||||
}
|
||||
/**
|
||||
* @description 为单个 wd-sticky 监听 viewport
|
||||
* @param child sticky
|
||||
* 监听子组件
|
||||
* @param child 子组件
|
||||
*/
|
||||
function observerForChild(child: any) {
|
||||
const hasChild = stickyList.find((sticky) => {
|
||||
return sticky.$.uid === child.$.uid
|
||||
})
|
||||
if (!hasChild) {
|
||||
stickyList.push(child)
|
||||
}
|
||||
deleteObserver(child)
|
||||
const observer = createObserver(child)
|
||||
|
||||
const exposed = child.$.exposed
|
||||
const offset = exposed.height.value + exposed.offsetTop
|
||||
let offset = exposed.stickyState.height + exposed.offsetTop
|
||||
// #ifdef H5
|
||||
// H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
|
||||
// H5的导航栏高度为44px
|
||||
offset = offset + 44
|
||||
// #endif
|
||||
|
||||
// 如果 wd-sticky 比 wd-sticky-box还大,"相对吸顶"无任何意义,此时强制吸顶元素回归其占位符
|
||||
if (height.value <= exposed.height.value) {
|
||||
if (boxStyle.height <= exposed.stickyState.height) {
|
||||
exposed.setPosition(false, 'absolute', 0)
|
||||
}
|
||||
observer.relativeToViewport({ top: -offset }).observe(`#${styckyBoxId.value}`, (result) => {
|
||||
scrollHandler(exposed, result)
|
||||
handleRelativeTo(exposed, result)
|
||||
})
|
||||
// 当子组件默认处于边界外且永远不会进入边界内时,需要手动调用一次
|
||||
getRect(`#${styckyBoxId.value}`, false, proxy)
|
||||
.then((res) => {
|
||||
// 当 wd-sticky-box 位于 viewport 外部时不会触发 observe,此时根据位置手动修复位置。
|
||||
if (Number(res.bottom) <= offset) scrollHandler(exposed, { boundingClientRect: res })
|
||||
// #ifdef H5
|
||||
// H5端,查询节点信息未计算导航栏高度
|
||||
res.bottom = Number(res.bottom) + 44
|
||||
// #endif
|
||||
if (Number(res.bottom) <= offset) handleRelativeTo(exposed, { boundingClientRect: res })
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description 为子节点监听 viewport,处理子节点的相对吸顶逻辑
|
||||
* 监听容器组件
|
||||
* @param {Object} exposed wd-sticky实例暴露出的事件
|
||||
* @param {Object} boundingClientRect 目标节点各个边在viewport中的坐标
|
||||
* @param {Object} boundingClientRect 边界信息
|
||||
*/
|
||||
function scrollHandler(exposed: any, { boundingClientRect }: any) {
|
||||
const offset = exposed.height.value + exposed.offsetTop
|
||||
if (boundingClientRect.bottom <= offset) {
|
||||
// 父元素即将被吸顶元素遮盖,将吸顶元素固定到父元素底部
|
||||
exposed.setPosition(true, 'absolute', boundingClientRect.height - exposed.height.value)
|
||||
} else if (boundingClientRect.top <= offset && boundingClientRect.bottom > offset) {
|
||||
// wd-sticky 已经完全呈现了 viewport 中了,
|
||||
// 此时没有必要再相对 wd-sticky-box 吸顶了
|
||||
if (exposed.state.value === 'normal') return
|
||||
// 顶元素开始遮盖不住父元素了,将吸顶元素恢复到吸顶模式
|
||||
exposed.setPosition(false, 'fixed', exposed.offsetTop)
|
||||
function handleRelativeTo(exposed: any, { boundingClientRect }: any) {
|
||||
let childOffsetTop = exposed.offsetTop
|
||||
// #ifdef H5
|
||||
// H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
|
||||
// H5的导航栏高度为44px
|
||||
childOffsetTop = childOffsetTop + 44
|
||||
// #endif
|
||||
const offset = exposed.stickyState.height + childOffsetTop
|
||||
let isAbsolute = boundingClientRect.bottom <= offset
|
||||
// #ifdef H5 || APP-PLUS
|
||||
isAbsolute = boundingClientRect.bottom < offset
|
||||
// #endif
|
||||
if (isAbsolute) {
|
||||
exposed.setPosition(true, 'absolute', boundingClientRect.height - exposed.stickyState.height)
|
||||
} else if (boundingClientRect.top <= offset && !isAbsolute) {
|
||||
if (exposed.stickyState.state === 'normal') return
|
||||
exposed.setPosition(false, 'fixed', childOffsetTop)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -1,13 +1,8 @@
|
||||
<template>
|
||||
<view :style="`${rootStyle};display: inline-block;`">
|
||||
<!--强制设置高宽,防止元素坍塌-->
|
||||
<!--在使用 wd-sticky-box 时,某些情况下 wd-sticky__container 的 'position:absolute' 需要相对于 wd-sticky-box-->
|
||||
<view :class="`wd-sticky ${props.customClass}`" :style="stickyStyle" :id="styckyId">
|
||||
<!--吸顶容器-->
|
||||
<view :class="`wd-sticky ${customClass}`" :style="stickyStyle" :id="styckyId">
|
||||
<view class="wd-sticky__container" :style="containerStyle">
|
||||
<!--监听元素尺寸变化-->
|
||||
<wd-resize @resize="resizeHandler" custom-style="display: inline-block;">
|
||||
<!--需要吸顶的内容-->
|
||||
<wd-resize @resize="handleResize" custom-style="display: inline-block;">
|
||||
<slot />
|
||||
</wd-resize>
|
||||
</view>
|
||||
@@ -20,63 +15,64 @@ export default {
|
||||
name: 'wd-sticky',
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
// virtualHost: true,
|
||||
virtualHost: true,
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { type Ref, computed, getCurrentInstance, inject, ref } from 'vue'
|
||||
import { addUnit, getRect, objToStyle, uuid } from '../common/util'
|
||||
import { computed, getCurrentInstance, reactive, ref, type CSSProperties } from 'vue'
|
||||
import { addUnit, getRect, objToStyle, requestAnimationFrame, uuid } from '../common/util'
|
||||
import { stickyProps } from './types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { STICKY_BOX_KEY } from '../wd-sticky-box/types'
|
||||
|
||||
const props = defineProps(stickyProps)
|
||||
const styckyId = ref<string>(`wd-sticky${uuid()}`)
|
||||
|
||||
const openBox = ref<boolean>(false)
|
||||
const position = ref<string>('absolute')
|
||||
const top = ref<number>(0)
|
||||
const height = ref<number>(0)
|
||||
const width = ref<number>(0)
|
||||
const observerList = ref<UniApp.IntersectionObserver[]>([])
|
||||
const state = ref<string>('')
|
||||
|
||||
const boxHeight: Ref<number> = inject('box-height', null) || ref(0)
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
const observerForChild: Function | null = inject('observerForChild', null)
|
||||
const stickyState = reactive({
|
||||
position: 'absolute',
|
||||
boxLeaved: false,
|
||||
top: 0,
|
||||
height: 0,
|
||||
width: 0,
|
||||
state: ''
|
||||
})
|
||||
|
||||
const { parent: stickyBox } = useParent(STICKY_BOX_KEY)
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
const instance = getCurrentInstance() as any
|
||||
|
||||
const rootStyle = computed(() => {
|
||||
const style: Record<string, string | number> = {
|
||||
const style: CSSProperties = {
|
||||
'z-index': props.zIndex,
|
||||
height: addUnit(height.value),
|
||||
width: addUnit(width.value)
|
||||
height: addUnit(stickyState.height),
|
||||
width: addUnit(stickyState.width)
|
||||
}
|
||||
if (!openBox.value) {
|
||||
if (!stickyState.boxLeaved) {
|
||||
style['position'] = 'relative'
|
||||
}
|
||||
return `${objToStyle(style)};${props.customStyle}`
|
||||
})
|
||||
|
||||
const stickyStyle = computed(() => {
|
||||
const style: Record<string, string | number> = {
|
||||
const style: CSSProperties = {
|
||||
'z-index': props.zIndex,
|
||||
height: addUnit(height.value),
|
||||
width: addUnit(width.value)
|
||||
height: addUnit(stickyState.height),
|
||||
width: addUnit(stickyState.width)
|
||||
}
|
||||
if (!openBox.value) {
|
||||
if (!stickyState.boxLeaved) {
|
||||
style['position'] = 'relative'
|
||||
}
|
||||
return `${objToStyle(style)};`
|
||||
})
|
||||
|
||||
const containerStyle = computed(() => {
|
||||
const style: Record<string, string | number> = {
|
||||
position: position.value,
|
||||
top: addUnit(top.value)
|
||||
const style: CSSProperties = {
|
||||
position: stickyState.position as 'static' | 'relative' | 'absolute' | 'sticky' | 'fixed',
|
||||
top: addUnit(stickyState.top)
|
||||
}
|
||||
return objToStyle(style)
|
||||
})
|
||||
@@ -93,7 +89,7 @@ const innerOffsetTop = computed(() => {
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 清除无用的 viewport 观察者
|
||||
* 清除对当前组件的监听
|
||||
*/
|
||||
function clearObserver() {
|
||||
while (observerList.value.length !== 0) {
|
||||
@@ -101,90 +97,92 @@ function clearObserver() {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @description 创建新的 viewport 观察者
|
||||
* 添加对当前组件的监听
|
||||
*/
|
||||
function createObserver() {
|
||||
const observer = uni.createIntersectionObserver(instance)
|
||||
const observer = uni.createIntersectionObserver(proxy, { thresholds: [0, 0.5] })
|
||||
observerList.value.push(observer)
|
||||
return observer
|
||||
}
|
||||
/**
|
||||
* @description 监听到吸顶元素尺寸大小变化时,立即重新模拟吸顶
|
||||
* 当前内容高度发生变化时重置监听
|
||||
*/
|
||||
function resizeHandler(detail: any) {
|
||||
// 当吸顶内容处于absolute、fixed时,为了防止父容器坍塌,需要手动设置父容器高宽。
|
||||
width.value = detail.width
|
||||
height.value = detail.height
|
||||
// // 如果和 wd-sticky-box 配套使用,吸顶逻辑交由 wd-sticky-box 进行处理
|
||||
observerContentScroll()
|
||||
if (!observerForChild) return
|
||||
observerForChild(proxy)
|
||||
function handleResize(detail: any) {
|
||||
stickyState.width = detail.width
|
||||
stickyState.height = detail.height
|
||||
requestAnimationFrame(() => {
|
||||
observerContentScroll()
|
||||
if (!stickyBox || !stickyBox.observerForChild) return
|
||||
stickyBox.observerForChild(proxy)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description 模拟吸顶逻辑
|
||||
* 监听吸顶元素滚动事件
|
||||
*/
|
||||
function observerContentScroll() {
|
||||
// 视图在 render tree 中未呈现,吸顶无任何意义。
|
||||
if (height.value === 0 && width.value === 0) return
|
||||
const offset = innerOffsetTop.value + height.value
|
||||
if (stickyState.height === 0 && stickyState.width === 0) return
|
||||
const offset = innerOffsetTop.value + stickyState.height
|
||||
clearObserver()
|
||||
createObserver()
|
||||
.relativeToViewport({
|
||||
top: -offset // viewport上边界往下拉
|
||||
top: -offset
|
||||
})
|
||||
.observe(`#${styckyId.value}`, (result) => {
|
||||
handleRelativeTo(result)
|
||||
})
|
||||
.observe(`#${styckyId.value}`, scrollHandler)
|
||||
getRect(`#${styckyId.value}`, false, proxy).then((res) => {
|
||||
// 当 wd-sticky 位于 viewport 外部时不会触发 observe,此时根据位置手动修复位置。
|
||||
if (Number(res.bottom) <= offset) scrollHandler({ boundingClientRect: res })
|
||||
// #ifdef H5
|
||||
// H5端,查询节点信息未计算导航栏高度
|
||||
res.bottom = Number(res.bottom) + 44
|
||||
// #endif
|
||||
if (Number(res.bottom) <= offset) handleRelativeTo({ boundingClientRect: res })
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description 根据位置进行吸顶
|
||||
*/
|
||||
function scrollHandler({ boundingClientRect }: any) {
|
||||
function handleRelativeTo({ boundingClientRect }: any) {
|
||||
// sticky 高度大于或等于 wd-sticky-box,使用 wd-sticky-box 无任何意义
|
||||
if (observerForChild && height.value >= boxHeight.value) {
|
||||
position.value = 'absolute'
|
||||
top.value = 0
|
||||
if (stickyBox && stickyState.height >= stickyBox.boxStyle.height) {
|
||||
stickyState.position = 'absolute'
|
||||
stickyState.top = 0
|
||||
return
|
||||
}
|
||||
// boundingClientRect : 目标节点各个边在 viewport 中的坐标
|
||||
if (boundingClientRect.top <= innerOffsetTop.value) {
|
||||
state.value = 'sticky'
|
||||
// 开始吸顶,固定到顶部
|
||||
openBox.value = false
|
||||
position.value = 'fixed'
|
||||
top.value = innerOffsetTop.value
|
||||
} else if (boundingClientRect.top > innerOffsetTop.value) {
|
||||
state.value = 'normal'
|
||||
// 完全展示,结束吸顶
|
||||
openBox.value = false
|
||||
position.value = 'absolute'
|
||||
top.value = 0
|
||||
|
||||
let isStycky = boundingClientRect.top <= innerOffsetTop.value
|
||||
// #ifdef H5 || APP-PLUS
|
||||
isStycky = boundingClientRect.top < innerOffsetTop.value
|
||||
// #endif
|
||||
|
||||
if (isStycky) {
|
||||
stickyState.state = 'sticky'
|
||||
stickyState.boxLeaved = false
|
||||
stickyState.position = 'fixed'
|
||||
stickyState.top = innerOffsetTop.value
|
||||
} else {
|
||||
stickyState.state = 'normal'
|
||||
stickyState.boxLeaved = false
|
||||
stickyState.position = 'absolute'
|
||||
stickyState.top = 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置位置
|
||||
* @param setOpenBox
|
||||
* @param setboxLeaved
|
||||
* @param setPosition
|
||||
* @param setTop
|
||||
*/
|
||||
function setPosition(setOpenBox: boolean, setPosition: string, setTop: number) {
|
||||
openBox.value = setOpenBox
|
||||
position.value = setPosition
|
||||
top.value = setTop
|
||||
function setPosition(boxLeaved: boolean, position: string, top: number) {
|
||||
stickyState.boxLeaved = boxLeaved
|
||||
stickyState.position = position
|
||||
stickyState.top = top
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
setPosition,
|
||||
openBox: openBox,
|
||||
position: position,
|
||||
top: top,
|
||||
height: height,
|
||||
width: width,
|
||||
state: state,
|
||||
offsetTop: innerOffsetTop.value
|
||||
stickyState,
|
||||
offsetTop: props.offsetTop
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -40,6 +40,7 @@
|
||||
border-radius: 2px;
|
||||
transition: opacity .3s;
|
||||
vertical-align: middle;
|
||||
line-height: initial;
|
||||
|
||||
@include when(default) {
|
||||
@include tag-type-style($-tag-info-color, $-tag-info-bg);
|
||||
|
@@ -95,6 +95,10 @@ declare module '@vue/runtime-core' {
|
||||
WdPasswordInput: typeof import('./components/wd-password-input/wd-password-input.vue')['default']
|
||||
WdForm: typeof import('./components/wd-form/wd-form.vue')['default']
|
||||
WdTextarea: typeof import('./components/wd-textarea/wd-textarea.vue')['default']
|
||||
WdBacktop: typeof import('./components/wd-backtop/wd-backtop.vue')['default']
|
||||
WdSkeleton: typeof import('./components/wd-skeleton/wd-skeleton.vue')['default']
|
||||
WdIndexBar: typeof import('./components/wd-index-bar/wd-index-bar.vue')['default']
|
||||
WdIndexAnchor: typeof import('./components/wd-index-anchor/wd-index-anchor.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,8 +2,8 @@
|
||||
"id": "wot-design-uni",
|
||||
"name": "wot-design-uni",
|
||||
"displayName": "wot-design-uni 基于vue3+Typescript的高颜值组件库",
|
||||
"version": "1.2.19",
|
||||
"description": "一个基于Vue3+TS开发的uni-app组件库,提供60+高质量组件,支持暗黑模式、国际化和自定义主题。",
|
||||
"version": "1.2.24",
|
||||
"description": "一个基于Vue3+TS开发的uni-app组件库,提供70+高质量组件,支持暗黑模式、国际化和自定义主题。",
|
||||
"keywords": [
|
||||
"wot-design-uni",
|
||||
"国际化",
|
||||
@@ -42,7 +42,8 @@
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://wot-design-uni.gitee.io/wot-design.png" width="200">
|
||||
<img alt="logo" src="https://wot-design-uni.pages.dev/wot-design.png" width="200">
|
||||
</p>
|
||||
<h1 align="center">Wot Design Uni</h1>
|
||||
|
||||
@@ -39,15 +39,16 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
✈️ <a href="https://wot-design-uni.gitee.io">文档网站 (国内推荐)</a>
|
||||
✈️ <a href="https://wot-design-uni.pages.dev/">文档网站 (推荐)</a>
|
||||
🚀 <a href="https://wot-design-uni.cn">文档网站 (备用)</a>
|
||||
🔥 <a href="https://wot-design-uni.netlify.app">文档网站 (备用)</a>
|
||||
🔥 <a href="https://wot-design-uni.netlify.app/">文档网站 (备用)</a>
|
||||
🚫 <a href="https://wot-design-uni.gitee.io/">文档网站 (Gitee暂时下线)</a>
|
||||
</p>
|
||||
|
||||
## ✨ 特性
|
||||
|
||||
- 🎯 多平台覆盖,支持 微信小程序、支付宝小程序、钉钉小程序、H5、APP 等.
|
||||
- 🚀 60+ 个高质量组件,覆盖移动端主流场景.
|
||||
- 🚀 70+ 个高质量组件,覆盖移动端主流场景.
|
||||
- 💪 使用 Typescript 构建,提供良好的组件类型系统.
|
||||
- 🌍 支持国际化,内置 6 种语言包.
|
||||
- 📖 提供丰富的文档和组件示例.
|
||||
@@ -59,23 +60,23 @@
|
||||
扫描二维码访问演示,注意:因微信审核机制限制,当前的微信小程序示例可能不是最新版本,可以clone代码到本地预览。
|
||||
|
||||
<p>
|
||||
<img src="https://wot-design-uni.gitee.io/wx.jpg" width="200" height="200" style="margin-right:30px"/>
|
||||
<img src="https://wot-design-uni.gitee.io/alipay.png" width="200" height="200" />
|
||||
<img src="https://wot-design-uni.pages.dev/wx.jpg" width="200" height="200" style="margin-right:30px"/>
|
||||
<img src="https://wot-design-uni.pages.dev/alipay.png" width="200" height="200" />
|
||||
</p>
|
||||
|
||||
## 快速上手
|
||||
|
||||
详细说明见 [快速上手](https://wot-design-uni.gitee.io/guide/quick-use.html)。
|
||||
详细说明见 [快速上手](https://wot-design-uni.pages.dev/guide/quick-use.html)。
|
||||
|
||||
## 链接
|
||||
|
||||
* [意见反馈](https://github.com/Moonofweisheng/wot-design-uni/issues)
|
||||
* [更新日志](https://wot-design-uni.gitee.io/guide/changelog.html)
|
||||
* [常见问题](https://wot-design-uni.gitee.io/guide/common-problems.html)
|
||||
* [更新日志](https://wot-design-uni.pages.dev/guide/changelog.html)
|
||||
* [常见问题](https://wot-design-uni.pages.dev/guide/common-problems.html)
|
||||
* [Discussions 讨论区](https://github.com/Moonofweisheng/wot-design-uni/discussions)
|
||||
* [QQ 群](https://qm.qq.com/cgi-bin/qm/qr?k=O1Z3pal6StL39qHtABqR54Tb56igr90O&jump_from=webapi&authKey=MtVWfi/EQbT03wW7tKXv4bmyKYHBHtzI8VewlzSsOdxFjN0wbgNy17np9Z9yC4Z8)
|
||||
* [快速上手项目](https://github.com/Moonofweisheng/wot-starter)
|
||||
* [Vue3路由库](https://wot-design-uni.gitee.io/uni-mini-router/)
|
||||
* [Vue3路由库](https://wot-design-uni.pages.dev/uni-mini-router/)
|
||||
|
||||
## 开发计划
|
||||
|
||||
@@ -107,10 +108,10 @@
|
||||
### 扫码捐赠
|
||||
|
||||
<p>
|
||||
<img src="https://wot-design-uni.gitee.io/weixinQrcode.jpg" width="200" height="200" style="margin-right:30px"/>
|
||||
<img src="https://wot-design-uni.gitee.io/alipayQrcode.jpg" width="200" height="200" />
|
||||
<img src="https://wot-design-uni.pages.dev/weixinQrcode.jpg" width="200" height="200" style="margin-right:30px"/>
|
||||
<img src="https://wot-design-uni.pages.dev/alipayQrcode.jpg" width="200" height="200" />
|
||||
</p>
|
||||
|
||||
## LICENSE
|
||||
|
||||
[MIT](https://github.com/Moonofweisheng/wot-design-uni/blob/develop/LICENSE)
|
||||
[MIT](https://github.com/Moonofweisheng/wot-design-uni/blob/master/LICENSE)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const baseUrl = 'http://127.0.0.1:8001';
|
||||
const baseUrl = 'http://192.168.43.34:8001';
|
||||
|
||||
export default {
|
||||
//微信APPID
|
||||
|
Reference in New Issue
Block a user