init
This commit is contained in:
37
uni_modules/nutui-uni/components/rate/index.scss
Normal file
37
uni_modules/nutui-uni/components/rate/index.scss
Normal file
@@ -0,0 +1,37 @@
|
||||
.nut-rate {
|
||||
display: inline-flex;
|
||||
|
||||
&-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
margin-right: 14px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
flex-shrink: 0;
|
||||
color: $rate-icon-color;
|
||||
cursor: pointer;
|
||||
|
||||
&--disabled {
|
||||
color: $rate-icon-void-color;
|
||||
}
|
||||
|
||||
&--full {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&--half {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
uni_modules/nutui-uni/components/rate/index.ts
Normal file
1
uni_modules/nutui-uni/components/rate/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './rate'
|
||||
56
uni_modules/nutui-uni/components/rate/rate.ts
Normal file
56
uni_modules/nutui-uni/components/rate/rate.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '../_constants'
|
||||
import { commonProps, isNumber, makeNumericProp, makeStringProp, nullableBooleanProp } from '../_utils'
|
||||
|
||||
export const rateProps = {
|
||||
...commonProps,
|
||||
/**
|
||||
* @description 当前 `star` 数,可使用 `v-model` 双向绑定数据
|
||||
*/
|
||||
modelValue: makeNumericProp(0),
|
||||
/**
|
||||
* @description `star` 总数
|
||||
*/
|
||||
count: makeNumericProp(5),
|
||||
/**
|
||||
* @description 图标选中颜色
|
||||
*/
|
||||
activeColor: String,
|
||||
/**
|
||||
* @description 图标未选中颜色
|
||||
*/
|
||||
voidColor: String,
|
||||
/**
|
||||
* @description 是否半星
|
||||
*/
|
||||
allowHalf: Boolean,
|
||||
/**
|
||||
* @description 是否只读
|
||||
*/
|
||||
readonly: Boolean,
|
||||
/**
|
||||
* @description 是否禁用
|
||||
*/
|
||||
disabled: nullableBooleanProp,
|
||||
/**
|
||||
* @description 间距
|
||||
*/
|
||||
spacing: [String, Number],
|
||||
/**
|
||||
* @description `Icon` 尺寸大小,如 `20px` `2em` `2rem`
|
||||
*/
|
||||
size: [String, Number],
|
||||
/**
|
||||
* @description 自定义 `Icon`
|
||||
*/
|
||||
customIcon: makeStringProp('star-fill-n'),
|
||||
}
|
||||
|
||||
export type RateProps = ExtractPropTypes<typeof rateProps>
|
||||
|
||||
export const rateEmits = {
|
||||
[UPDATE_MODEL_EVENT]: (val: number) => isNumber(val),
|
||||
[CHANGE_EVENT]: (val: number) => isNumber(val),
|
||||
}
|
||||
|
||||
export type RateEmits = typeof rateEmits
|
||||
92
uni_modules/nutui-uni/components/rate/rate.vue
Normal file
92
uni_modules/nutui-uni/components/rate/rate.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent, ref, toRef } from 'vue'
|
||||
import { CHANGE_EVENT, PREFIX, UPDATE_MODEL_EVENT } from '../_constants'
|
||||
import { getMainClass, getRandomId, pxCheck } from '../_utils'
|
||||
import { useFormDisabled } from '../form/form'
|
||||
import NutIcon from '../icon/icon.vue'
|
||||
import { rateEmits, rateProps } from './rate'
|
||||
|
||||
const props = defineProps(rateProps)
|
||||
const emit = defineEmits(rateEmits)
|
||||
const disabled = useFormDisabled(toRef(props, 'disabled'))
|
||||
|
||||
const refRandomId = getRandomId()
|
||||
const rateRefs = ref<HTMLElement[]>([])
|
||||
const classes = computed(() => {
|
||||
return getMainClass(props, componentName)
|
||||
})
|
||||
function updateVal(value: number) {
|
||||
emit(UPDATE_MODEL_EVENT, value)
|
||||
emit(CHANGE_EVENT, value)
|
||||
}
|
||||
function onClick(e: number, index: number) {
|
||||
if (disabled.value || props.readonly)
|
||||
return
|
||||
let value = 0
|
||||
if (index === 1 && props.modelValue === index) {
|
||||
//
|
||||
}
|
||||
else {
|
||||
value = index
|
||||
if (props.allowHalf && e === 2)
|
||||
value -= 0.5
|
||||
}
|
||||
updateVal(value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-rate`
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view :class="classes" :style="customStyle">
|
||||
<view
|
||||
v-for="n in Number(count)"
|
||||
:id="`rateRefs-${refRandomId}${n}`"
|
||||
:key="n"
|
||||
ref="rateRefs"
|
||||
class="nut-rate-item"
|
||||
:style="n < Number(count) ? { marginRight: pxCheck(spacing!) } : {}"
|
||||
>
|
||||
<view class="nut-rate-item__icon--full" @click="onClick(1, n)">
|
||||
<NutIcon
|
||||
:size="props.size"
|
||||
:custom-class="`nut-rate-item__icon ${disabled || n > +modelValue ? 'nut-rate-item__icon--disabled' : ''}`"
|
||||
:name="customIcon"
|
||||
:custom-color="n <= +modelValue ? activeColor : voidColor"
|
||||
/>
|
||||
</view>
|
||||
<view v-if="allowHalf && Number(modelValue) + 1 > n" class="nut-rate-item__icon--half" @click="onClick(2, n)">
|
||||
<NutIcon
|
||||
:size="props.size"
|
||||
custom-class="nut-rate-item__icon"
|
||||
:name="customIcon"
|
||||
:custom-color="n <= Number(modelValue) + 1 ? activeColor : voidColor"
|
||||
@click="onClick(2, n)"
|
||||
/>
|
||||
</view>
|
||||
<view v-else-if="allowHalf && Number(modelValue) + 1 < n" class="nut-rate-item__icon--half" @click="onClick(2, n)">
|
||||
<NutIcon
|
||||
:size="props.size"
|
||||
:name="customIcon"
|
||||
custom-class="nut-rate-item__icon nut-rate-item__icon--disabled"
|
||||
:custom-color="voidColor"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import './index';
|
||||
</style>
|
||||
Reference in New Issue
Block a user