hy-app 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,76 +1,80 @@
1
- import type { CSSProperties } from "vue";
1
+ import type { CSSProperties } from 'vue'
2
2
 
3
3
  export default interface HyImageProps {
4
4
  /**
5
5
  * @description 图片地址
6
6
  * */
7
- src?: string;
7
+ src?: string
8
8
  /**
9
9
  * @description 裁剪模式,见官网说明 (默认 'aspectFill' )
10
10
  * */
11
- mode?: HyApp.ImageModeVo;
11
+ mode?: HyApp.ImageModeVo
12
12
  /**
13
13
  * @description 宽度,单位任意,如果为数值,则为px单位 (默认 '300' )
14
14
  * */
15
- width?: string | number;
15
+ width?: string | number
16
16
  /**
17
17
  * @description 高度,单位任意,如果为数值,则为px单位 (默认 '225' )
18
18
  * */
19
- height?: string | number;
19
+ height?: string | number
20
20
  /**
21
21
  * @description 图片形状,circle-圆形,square-方形 (默认 'square' )
22
22
  * */
23
- shape?: HyApp.ShapeType;
23
+ shape?: HyApp.ShapeType
24
24
  /**
25
25
  * @description 圆角值,单位任意,如果为数值,则为px单位 (默认 0 )
26
26
  * */
27
- radius?: number | string;
27
+ radius?: number | string
28
28
  /**
29
29
  * @description 是否懒加载,仅微信小程序、App、百度小程序、字节跳动小程序有效 (默认 true )
30
30
  * */
31
- lazyLoad?: boolean;
31
+ lazyLoad?: boolean
32
32
  /**
33
33
  * @description 是否开启长按图片显示识别小程序码菜单,仅微信小程序有效 (默认 true )
34
34
  * */
35
- showMenuByLongPress?: boolean;
35
+ showMenuByLongPress?: boolean
36
36
  /**
37
37
  * @description 加载中的图标,或者小图片 (默认 'photo' )
38
38
  * */
39
- loadingIcon?: string;
39
+ loadingIcon?: string
40
40
  /**
41
41
  * @description 加载失败的图标,或者小图片 (默认 'error-circle' )
42
42
  * */
43
- errorIcon?: string;
43
+ errorIcon?: string
44
44
  /**
45
45
  * @description 是否显示加载中的图标或者自定义的slot (默认 true )
46
46
  * */
47
- showLoading?: boolean;
47
+ showLoading?: boolean
48
48
  /**
49
49
  * @description 是否显示加载错误的图标或者自定义的slot (默认 true )
50
50
  * */
51
- showError?: boolean;
51
+ showError?: boolean
52
52
  /**
53
53
  * @description 是否需要淡入效果 (默认 true )
54
54
  * */
55
- fade?: boolean;
55
+ fade?: boolean
56
56
  /**
57
57
  * @description 只支持网络资源,只对微信小程序有效 (默认 false )
58
58
  * */
59
- webp?: boolean;
59
+ webp?: boolean
60
60
  /**
61
61
  * @description 搭配fade参数的过渡时间,单位ms (默认 500 )
62
62
  * */
63
- duration?: number;
63
+ duration?: number
64
64
  /**
65
65
  * @description 背景颜色,用于深色页面加载图片时,为了和背景色融合 (默认 '#f3f4f6' )
66
66
  * */
67
- bgColor?: string;
67
+ bgColor?: string
68
+ /**
69
+ * @description 是否模糊图片 (默认 false )
70
+ * */
71
+ indistinct?: boolean
68
72
  /**
69
73
  * @description 是否预览图片 (默认 false )
70
74
  * */
71
- previewImage?: boolean;
75
+ previewImage?: boolean
72
76
  /**
73
77
  * @description 定义需要用到的外部样式
74
78
  * */
75
- customStyle?: CSSProperties;
79
+ customStyle?: CSSProperties
76
80
  }
@@ -86,7 +86,7 @@
86
86
  }
87
87
 
88
88
  &--hover {
89
- background-color: $hy-background--hover;
89
+ opacity: 0.7;
90
90
  }
91
91
 
92
92
  &__text {
@@ -0,0 +1,200 @@
1
+ <template>
2
+ <view class="hy-popover" :style="customStyle" id="popover" @click.stop="popover.noop">
3
+ <!-- 使用插槽时无法获取正确宽高 -->
4
+ <view class="hy-popover__pos hy-popover__hidden" id="pos">
5
+ <view class="hy-popover__container">
6
+ <view v-if="mode === 'normal'" class="hy-popover__inner">
7
+ {{ content }}
8
+ </view>
9
+ <view v-if="mode === 'menu' && typeof content === 'object'" class="hy-popover__menu">
10
+ <view
11
+ v-for="(item, index) in content"
12
+ :key="index"
13
+ class="hy-popover__menu-inner"
14
+ @click="menuClick(index)"
15
+ >
16
+ <hy-icon v-if="item.iconClass" :name="item.iconClass" custom-class="hy-popover__icon" />
17
+ <text>{{ item.content }}</text>
18
+ </view>
19
+ </view>
20
+ </view>
21
+ </view>
22
+ <hy-transition
23
+ class="hy-popover__pos"
24
+ :custom-style="popover.popStyle.value"
25
+ :show="showPopover"
26
+ name="fade"
27
+ :duration="200"
28
+ >
29
+ <view class="hy-popover__container">
30
+ <!-- 三角形 -->
31
+ <view
32
+ :class="`hy-popover__arrow ${popover.arrowClass.value}`"
33
+ :style="popover.arrowStyle.value"
34
+ ></view>
35
+ <!-- 三角形 -->
36
+
37
+ <!-- 普通模式 -->
38
+ <view v-if="mode === 'normal'" class="hy-popover__inner">
39
+ {{ content }}
40
+ </view>
41
+ <!-- 普通模式 -->
42
+
43
+ <!-- 列表模式 -->
44
+ <view v-if="mode === 'menu'" class="hy-popover__menu">
45
+ <view
46
+ v-for="(item, index) in content"
47
+ :key="index"
48
+ class="hy-popover__menu-inner"
49
+ @click="menuClick(index)"
50
+ :style="index === 0 ? 'border-top: none' : ''"
51
+ >
52
+ <hy-icon
53
+ v-if="typeof item === 'object' && item.iconClass"
54
+ :name="item.iconClass"
55
+ custom-class="hy-popover__icon"
56
+ />
57
+ <view style="display: inline-block">
58
+ {{ typeof item === 'object' && item.content ? item.content : item }}
59
+ </view>
60
+ </view>
61
+ </view>
62
+ <!-- 列表模式 -->
63
+
64
+ <!-- 用户自定义样式 -->
65
+ <slot name="content" v-else />
66
+ <!-- 用户自定义样式 -->
67
+ </view>
68
+ <hy-icon
69
+ v-if="showClose"
70
+ name="close"
71
+ custom-class="hy-popover__close-icon"
72
+ @click="toggle"
73
+ ></hy-icon>
74
+ </hy-transition>
75
+ <view @click="toggle" class="hy-popover__target" id="target">
76
+ <slot />
77
+ </view>
78
+ </view>
79
+ </template>
80
+
81
+ <script lang="ts">
82
+ export default {
83
+ name: 'hy-popover',
84
+ options: {
85
+ virtualHost: true,
86
+ addGlobalClass: true,
87
+ styleIsolation: 'shared',
88
+ },
89
+ }
90
+ </script>
91
+
92
+ <script lang="ts" setup>
93
+ import { getCurrentInstance, onMounted, ref, toRefs, watch } from 'vue'
94
+ import defaultProps from './props'
95
+ import IProps, { type PopoverExpose } from './typing'
96
+ import { isArray } from '../../utils'
97
+ import { type Queue, queueKey, usePopover } from '../../composables'
98
+
99
+ // 组件
100
+ import HyIcon from '../hy-icon/hy-icon.vue'
101
+ import HyTransition from '../hy-transition/hy-transition.vue'
102
+
103
+ const props = withDefaults(defineProps<IProps>(), defaultProps)
104
+ const { modelValue, content, mode, placement } = toRefs(props)
105
+ const emit = defineEmits(['update:modelValue', 'menuClick', 'change', 'open', 'close'])
106
+
107
+ const queue = inject<Queue | null>(queueKey, null)
108
+ const selector: string = 'popover'
109
+ const { proxy } = getCurrentInstance() as any
110
+ const popover = usePopover()
111
+ const showPopover = ref<boolean>(false) // 控制popover显隐
112
+
113
+ watch(
114
+ () => content.value,
115
+ (newVal) => {
116
+ if (mode.value === 'normal' && typeof newVal !== 'string') {
117
+ console.error('在“normal”模式下,值类型必须为字符串类型。')
118
+ } else if (mode.value === 'menu' && !isArray(newVal)) {
119
+ console.error('在“menu”模式下,值类型必须是数组类型。')
120
+ }
121
+ },
122
+ )
123
+
124
+ watch(
125
+ () => props.placement,
126
+ () => {
127
+ popover.init(placement.value, true, selector)
128
+ },
129
+ )
130
+
131
+ watch(
132
+ () => modelValue.value,
133
+ (newValue: boolean) => {
134
+ showPopover.value = newValue
135
+ },
136
+ )
137
+
138
+ watch(
139
+ () => showPopover.value,
140
+ (newValue) => {
141
+ if (newValue) {
142
+ popover.control(placement.value, props.offset)
143
+ // if (queue && queue.closeOther) {
144
+ // queue.closeOther(proxy)
145
+ // }
146
+ queue.closeOther(proxy)
147
+ }
148
+ popover.showStyle.value = newValue ? 'display: inline-block;' : 'display: none;'
149
+ emit('change', { show: newValue })
150
+ emit(`${newValue ? 'open' : 'close'}`)
151
+ },
152
+ )
153
+
154
+ onMounted(() => {
155
+ popover.init(placement.value, true, selector)
156
+ })
157
+
158
+ onBeforeMount(() => {
159
+ queue.pushToQueue(proxy)
160
+ popover.showStyle.value = showPopover.value ? 'opacity: 1;' : 'opacity: 0;'
161
+ })
162
+
163
+ onBeforeUnmount(() => {
164
+ queue.removeFromQueue(proxy)
165
+ })
166
+
167
+ const menuClick = (index: number) => {
168
+ updateModelValue(false)
169
+ emit('menuClick', {
170
+ item: (props.content as Array<Record<string, any>>)[index],
171
+ index,
172
+ })
173
+ }
174
+
175
+ const toggle = () => {
176
+ if (props.disabled) return
177
+ updateModelValue(!showPopover.value)
178
+ }
179
+
180
+ const open = () => {
181
+ updateModelValue(true)
182
+ }
183
+
184
+ const close = () => {
185
+ updateModelValue(false)
186
+ }
187
+
188
+ function updateModelValue(value: boolean) {
189
+ showPopover.value = value
190
+ emit('update:modelValue', value)
191
+ }
192
+
193
+ defineExpose<PopoverExpose>({
194
+ open,
195
+ close,
196
+ })
197
+ </script>
198
+ <style lang="scss" scoped>
199
+ @import './index.scss';
200
+ </style>
@@ -0,0 +1,83 @@
1
+ @use "../../theme.scss" as *;
2
+ @use "../../libs/css/mixin.scss" as *;
3
+
4
+ $z-index: 998;
5
+
6
+ @include b(popover) {
7
+ position: relative;
8
+ display: inline-block;
9
+
10
+ @include edeep(icon) {
11
+ vertical-align: middle;
12
+ font-size: 18px;
13
+ margin-right: 5px;
14
+ }
15
+
16
+ /* 菜单 */
17
+ @include e(menu-inner) {
18
+ position: relative;
19
+ padding: 20rpx 0;
20
+ display: flex;
21
+ align-items: center;
22
+
23
+ &:not(:last-child) {
24
+ border-bottom: $hy-border-line;
25
+ }
26
+ }
27
+
28
+ @include e(menu) {
29
+ display: inline-block;
30
+ padding: 0 $hy-border-margin-padding-base;
31
+ white-space: nowrap;
32
+ z-index: $z-index;
33
+ position: relative;
34
+ background-color: $hy-background--container;
35
+ border-radius: $hy-border-radius-sm;
36
+ }
37
+
38
+ @include edeep(pos) {
39
+ position: absolute;
40
+ box-sizing: border-box;
41
+ background-clip: padding-box;
42
+ text-align: center;
43
+ min-height: 36px;
44
+ z-index: $z-index;
45
+ transition: opacity 0.2s;
46
+ box-shadow: $hy-box-shadow;
47
+ border-radius: $hy-border-radius-sm;
48
+ }
49
+
50
+
51
+ @include e(hidden) {
52
+ left: -220vw;
53
+ visibility: hidden;
54
+ }
55
+
56
+ @include e(container) {
57
+ position: relative;
58
+ border-radius: $hy-border-radius-sm;
59
+ }
60
+
61
+ @include e(inner) {
62
+ position: relative;
63
+ padding: $hy-border-margin-padding-base;
64
+ line-height: 22px;
65
+ z-index: $z-index;
66
+ background-color: $hy-background--container;
67
+ border-radius: $hy-border-radius-sm;
68
+ box-sizing: content-box;
69
+ width: 200px;
70
+ }
71
+
72
+
73
+ @include edeep(close-icon) {
74
+ font-size: 12px;
75
+ position: absolute;
76
+ right: -10px;
77
+ top: -7px;
78
+ padding: 10px;
79
+ z-index: $z-index;
80
+ }
81
+
82
+ @include squareArrow(6px, $hy-background--container, $z-index, $hy-box-shadow);
83
+ }
@@ -0,0 +1,13 @@
1
+ import type IProps from './typing'
2
+
3
+ const defaultProps: IProps = {
4
+ modelValue: false,
5
+ content: '',
6
+ placement: 'bottom',
7
+ offset: 0,
8
+ showClose: false,
9
+ disabled: false,
10
+ mode: 'normal',
11
+ }
12
+
13
+ export default defaultProps
@@ -0,0 +1,56 @@
1
+ import type { CSSProperties } from 'vue'
2
+
3
+ export type IPlacementVo =
4
+ | 'top'
5
+ | 'top-start'
6
+ | 'top-end'
7
+ | 'bottom'
8
+ | 'bottom-start'
9
+ | 'bottom-end'
10
+ | 'left'
11
+ | 'left-start'
12
+ | 'left-end'
13
+ | 'right'
14
+ | 'right-start'
15
+ | 'right-end'
16
+ export type IOffset = number | number[] | Record<'x' | 'y', number>
17
+
18
+ export type PopoverExpose = {
19
+ open: () => void
20
+ close: () => void
21
+ }
22
+
23
+ export default interface HyOverlayProps {
24
+ /**
25
+ * @description 控制 popover 的显示状态
26
+ * */
27
+ modelValue?: boolean
28
+ /**
29
+ * @description 显示的内容,也可以通过 slot#content 传入
30
+ */
31
+ content?: string | Record<string, any>[]
32
+ /**
33
+ * @description 指定 popover 的放置位置:top / top-start / top-end / bottom / bottom-start / bottom-end / left / left-start / left-end / right / right-start / right-end
34
+ */
35
+ placement?: IPlacementVo
36
+ /**
37
+ * @description 控制 popover 的显示状态
38
+ */
39
+ offset?: IOffset
40
+ /**
41
+ * @description 是否禁用 popover
42
+ */
43
+ disabled?: boolean
44
+ /**
45
+ * @description 是否显示关闭按钮
46
+ */
47
+ showClose?: boolean
48
+ /**
49
+ * 当前显示的模式,决定内容的展现形式,可选值:normal(普通模式)/ menu(菜单模式)
50
+ */
51
+ mode?: 'normal' | 'menu'
52
+ /**
53
+ * @description 定义需要用到的外部样式
54
+ * */
55
+ customStyle?: CSSProperties
56
+ }
@@ -26,40 +26,39 @@ export default {
26
26
  options: {
27
27
  addGlobalClass: true,
28
28
  virtualHost: true,
29
- styleIsolation: 'shared'
30
- }
29
+ styleIsolation: 'shared',
30
+ },
31
31
  }
32
32
  </script>
33
33
 
34
34
  <script setup lang="ts">
35
- import { getCurrentInstance, toRefs, ref, onMounted } from "vue";
36
- import defaultProps from "./props";
37
- import type IProps from "./typing";
38
- import QRCode from "./qrcode.js";
39
- import { addUnit, error } from "../../utils";
40
- import { IconConfig } from "../../config";
35
+ import { getCurrentInstance, toRefs, ref, onMounted } from 'vue'
36
+ import defaultProps from './props'
37
+ import type IProps from './typing'
38
+ import QRCode from './qrcode.js'
39
+ import { addUnit, error } from '../../utils'
40
+ import { IconConfig } from '../../config'
41
41
 
42
42
  // 组件
43
- import HyIcon from "../hy-icon/hy-icon.vue";
44
- import HyLoading from "../hy-loading/hy-loading.vue";
43
+ import HyIcon from '../hy-icon/hy-icon.vue'
44
+ import HyLoading from '../hy-loading/hy-loading.vue'
45
45
 
46
- const props = withDefaults(defineProps<IProps>(), defaultProps);
47
- const { text, allowPreview } = toRefs(props);
48
- const emit = defineEmits(["result", "preview", "longPress"]);
46
+ const props = withDefaults(defineProps<IProps>(), defaultProps)
47
+ const { text, allowPreview } = toRefs(props)
48
+ const emit = defineEmits(['result', 'preview', 'longPress'])
49
49
 
50
- const instance = getCurrentInstance();
51
- const loading = ref(false);
52
- const qrcode = ref("");
53
- const result = ref("");
50
+ const instance = getCurrentInstance()
51
+ const loading = ref(false)
52
+ const qrcode = ref('')
53
+ const result = ref('')
54
54
 
55
55
  onMounted(() => {
56
- console.log(111);
57
- initQrCode();
58
- });
56
+ initQrCode()
57
+ })
59
58
 
60
59
  const initQrCode = () => {
61
60
  if (text.value) {
62
- loading.value = true;
61
+ loading.value = true
63
62
  qrcode.value = new QRCode({
64
63
  context: instance, // 上下文环境
65
64
  canvasId: props.cid, // canvas-id
@@ -76,34 +75,34 @@ const initQrCode = () => {
76
75
  imageSize: props.iconSize, // 二维码图标大小
77
76
  cbResult: function (res: any) {
78
77
  // 生成二维码的回调
79
- _result(res);
78
+ _result(res)
80
79
  },
81
- });
80
+ })
82
81
  } else {
83
- error("二维码内容不能为空");
82
+ error('二维码内容不能为空')
84
83
  }
85
- };
84
+ }
86
85
 
87
86
  const _result = (res: any) => {
88
- loading.value = false;
89
- result.value = res;
90
- emit("result", res);
91
- };
87
+ loading.value = false
88
+ result.value = res
89
+ emit('result', res)
90
+ }
92
91
 
93
92
  const _saveCode = () => {
94
- if (result.value != "") {
93
+ if (result.value != '') {
95
94
  uni.saveImageToPhotosAlbum({
96
95
  filePath: result.value,
97
96
  success: function () {
98
97
  uni.showToast({
99
- title: "二维码保存成功",
100
- icon: "success",
98
+ title: '二维码保存成功',
99
+ icon: 'success',
101
100
  duration: 2000,
102
- });
101
+ })
103
102
  },
104
- });
103
+ })
105
104
  }
106
- };
105
+ }
107
106
  /**
108
107
  * @description 预览
109
108
  * */
@@ -114,29 +113,29 @@ const preview = (e) => {
114
113
  uni.previewImage({
115
114
  urls: [result.value],
116
115
  longPressActions: {
117
- itemList: ["保存二维码图片"],
116
+ itemList: ['保存二维码图片'],
118
117
  success: function (data) {
119
118
  // console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
120
119
  switch (data.tapIndex) {
121
120
  case 0:
122
- _saveCode();
123
- break;
121
+ _saveCode()
122
+ break
124
123
  }
125
124
  },
126
125
  fail: function (err) {
127
- console.error(err.errMsg);
126
+ console.error(err.errMsg)
128
127
  },
129
128
  },
130
- });
129
+ })
131
130
  }
132
- emit("preview", result.value, e);
133
- };
131
+ emit('preview', result.value, e)
132
+ }
134
133
 
135
134
  const onLongPress = () => {
136
- emit("longPress");
137
- };
135
+ emit('longPress')
136
+ }
138
137
  </script>
139
138
 
140
139
  <style lang="scss" scoped>
141
- @import "./index.scss";
140
+ @import './index.scss';
142
141
  </style>
@@ -1,5 +1,5 @@
1
- import { ColorConfig, IconConfig } from "../../config";
2
- import type IProps from "./typing";
1
+ import { ColorConfig, IconConfig } from '../../config'
2
+ import type IProps from './typing'
3
3
 
4
4
  const defaultProps: IProps = {
5
5
  modelValue: 1,
@@ -7,13 +7,13 @@ const defaultProps: IProps = {
7
7
  disabled: false,
8
8
  readonly: false,
9
9
  size: 18,
10
- inactiveColor: "#b2b2b2",
11
- activeColor: "#FFF00D",
10
+ inactiveColor: '#b2b2b2',
11
+ activeColor: '#FFF00D',
12
12
  gutter: 4,
13
13
  minCount: 1,
14
14
  allowHalf: false,
15
15
  activeIcon: IconConfig.STAR_FILL,
16
16
  inactiveIcon: IconConfig.STAR,
17
17
  touchable: true,
18
- };
19
- export default defaultProps;
18
+ }
19
+ export default defaultProps