feat: 添加自定义字体和图标资源,优化登录和首页界面

refactor(login): 使用自定义输入框组件替换原生输入框
refactor(index): 重构网格布局代码,使用动态渲染方式
style: 更新全局字体样式,移除默认字体设置
chore: 添加多个字体文件和图标资源
docs: 更新应用名称和版本号
This commit is contained in:
2025-08-20 16:21:13 +08:00
parent ca4d93b902
commit 7a3d4f8c8a
40 changed files with 473 additions and 90 deletions

View File

@@ -0,0 +1,253 @@
<template>
<view class="custom-input" :class="inputClass" :style="[wrapperStyle]">
<view class="custom-input__content">
<view class="custom-input__content__prefix-icon" v-if="prefixIcon">
<u-icon
:name="prefixIcon"
:width="iconSize"
:height="iconSize"
:customStyle="prefixIconStyle"
></u-icon>
</view>
<view class="custom-input__content__field-wrapper" @tap="clickHandler">
<input
class="custom-input__content__field-wrapper__field"
:style="[inputStyle]"
:type="type"
:focus="focus"
:value="value"
:disabled="disabled"
:maxlength="maxlength"
:placeholder="placeholder"
:password="password || type === 'password' || false"
@input="onInput"
@blur="onBlur"
@focus="onFocus"
@confirm="onConfirm"
/>
</view>
<view
class="custom-input__content__suffix-icon"
v-if="$slots.suffix"
>
<slot name="suffix"></slot>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'CustomInput',
props: {
// 输入框的值
value: {
type: [String, Number],
default: ''
},
// 输入框类型
type: {
type: String,
default: 'text'
},
// 是否禁用输入框
disabled: {
type: Boolean,
default: false
},
// 最大输入长度
maxlength: {
type: [String, Number],
default: -1
},
// 占位符
placeholder: {
type: String,
default: ''
},
// 是否密码类型
password: {
type: Boolean,
default: false
},
// 前置图标
prefixIcon: {
type: String,
default: ''
},
// 前置图标样式
prefixIconStyle: {
type: [String, Object],
default: () => ({})
},
// 图标大小
iconSize: {
type: [String, Number],
default: 32
},
// 输入框字体大小
fontSize: {
type: [String, Number],
default: '14px'
},
// 输入框字体颜色
color: {
type: String,
default: '#333'
},
// 是否自动获取焦点
focus: {
type: Boolean,
default: false
},
// 边框类型
border: {
type: String,
default: 'bottom' // none, bottom, surround
},
// 自定义样式
customStyle: {
type: Object,
default: () => ({})
}
},
data() {
return {
// 输入框的值
innerValue: this.value
};
},
watch: {
value(newVal) {
this.innerValue = newVal;
}
},
computed: {
// 组件的类名
inputClass() {
let classes = [];
const { border } = this;
if (border === 'surround') {
classes = classes.concat(['custom-border', 'custom-input--radius']);
} else if (border === 'bottom') {
classes = classes.concat(['custom-border-bottom', 'custom-input--no-radius']);
}
return classes.join(' ');
},
// 组件的样式
wrapperStyle() {
const style = {};
// 无边框时,去除内边距
if (this.border === 'none') {
style.padding = '0';
} else {
// 由于uni-app的iOS开发者能力有限导致需要分开写才有效
style.paddingTop = '6px';
style.paddingBottom = '6px';
style.paddingLeft = '9px';
style.paddingRight = '9px';
}
return Object.assign(style, this.customStyle);
},
// 输入框的样式
inputStyle() {
const style = {
color: this.color,
fontSize: this.fontSize,
flex: 1
};
return style;
}
},
methods: {
// 当键盘输入时触发input事件
onInput(e) {
const { value = '' } = e.detail || {};
this.innerValue = value;
this.$emit('input', value);
// 为了支持v-model需要同时触发update:value事件
this.$emit('update:value', value);
this.$emit('change', value);
},
// 输入框失去焦点时触发
onBlur(event) {
this.$emit('blur', event.detail.value);
},
// 输入框聚焦时触发
onFocus(event) {
this.$emit('focus');
},
// 点击完成按钮时触发
onConfirm(event) {
this.$emit('confirm', this.innerValue);
},
// 点击事件
clickHandler() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
.custom-input {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
flex: 1;
&--radius {
border-radius: 4px;
}
&--no-radius {
border-radius: 0;
}
.custom-border {
border: 1px solid #dcdfe6;
}
.custom-border-bottom {
border-bottom: 1px solid #dcdfe6;
}
&__content {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
flex: 1;
&__prefix-icon {
margin-right: 5px;
}
&__field-wrapper {
flex: 1;
&__field {
width: 100%;
font-size: 14px;
color: #333;
// 去除input的默认样式
outline: none;
border: none;
background: none;
}
}
&__suffix-icon {
margin-left: 5px;
}
}
}
</style>