feat: add new features, update theme and build config

- Add 40+ new UI components including chat modules, discovery cards, photo galleries, FAQ and booking tools
- Standardize brand color across all styles by replacing $theme-color-500 SCSS variables with #0ccd58
- Add sass 1.58.3 dependency and update vite config for modern scss compiler support
- Refactor existing components (AddCarCrad, login page) and remove unused /quick/list router route
- Add utility functions for URL parameter handling
- Add static assets including custom znicons font, component images and icons
- Fix scss syntax issues and deprecation warnings
This commit is contained in:
duanshuwen
2026-05-26 22:49:52 +08:00
parent 548df7020c
commit ac8f5b5f64
159 changed files with 12439 additions and 629 deletions

View File

@@ -1,19 +1,15 @@
<template>
<div class="add-car-card">
<div class="flex flex-col items-center">
<div class="description">
请绑定真实有效的车牌号否则将无法正常使用车牌付费等功能
</div>
<img
class="code-img"
src="https://one-feel-config-images-bucket.oss-cn-chengdu.aliyuncs.com/20250920102920_354_52.png"
mode="widthFix"
show-menu-by-longpress="true"
/>
<div class="tips">长按二维码识别</div>
<img class="mt-[12px] w-[250px] h-[250px] rounded-[4px]"
src="https://one-feel-config-images-bucket.oss-cn-chengdu.aliyuncs.com/20250920102920_354_52.png" />
<div class="p-[12px] text-[18px] text-600 text-[#666]">长按二维码识别</div>
</div>
</template>
<script setup>
<script setup lang="ts">
import { defineProps } from "vue";
const props = defineProps({
@@ -23,7 +19,3 @@ const props = defineProps({
},
});
</script>
<style lang="scss" scoped>
@import "./styles/index.scss";
</style>

View File

@@ -1,19 +0,0 @@
.add-car-card {
display: flex;
flex-direction: column;
align-items: center;
.code-img {
margin-top: 12px;
width: 250px;
height: 250px;
border-radius: 4px;
}
.tips {
padding: 12px;
font-size: 36rpx;
font-weight: 600;
color: #666;
}
}

View File

@@ -1,55 +1,32 @@
<template>
<div class="ai-tab-wrapper">
<div class="tab-container">
<div
class="tab-item is-left"
:class="{ active: modelValue === 0 }"
@tap="handleSwitch(0)"
>
<div class="w-full">
<div class="relative w-full h-[50px] flex overflow-hidden">
<div class="tab-item is-left" :class="{ active: modelValue === 0 }" @tap="handleSwitch(0)">
<div class="tab-content">
<img
v-if="leftSelected || leftUnselected"
:src="
modelValue === 0
? leftSelected || leftUnselected
: leftUnselected || leftSelected
"
class="tab-image"
mode="scaleToFill"
/>
<img v-if="leftSelected || leftUnselected" :src="modelValue === 0
? leftSelected || leftUnselected
: leftUnselected || leftSelected
" class="tab-image" mode="scaleToFill" />
<div class="tab-label">
<spanclass="tab-text">探索发现</text>
</div>
</div>
</div>
<div
class="tab-item is-right"
:class="{ active: modelValue === 1 }"
@tap="handleSwitch(1)"
>
<div class="tab-item is-right" :class="{ active: modelValue === 1 }" @tap="handleSwitch(1)">
<div class="tab-content">
<img
v-if="rightSelected || rightUnselected"
:src="
modelValue === 1
? rightSelected || rightUnselected
: rightUnselected || rightSelected
"
class="tab-image"
mode="scaleToFill"
/>
<img v-if="rightSelected || rightUnselected" :src="modelValue === 1
? rightSelected || rightUnselected
: rightUnselected || rightSelected
" class="tab-image" mode="scaleToFill" />
<div class="tab-label">
<spanclass="tab-text">AI伴游</text>
<div
v-if="showDot"
:class="[
<div v-if="showDot" :class="[
'status-dot',
modelValue === 1
? 'status-dot--active'
: 'status-dot--inactive',
]"
></div>
]"></div>
</div>
</div>
</div>

View File

@@ -1,15 +1,3 @@
.ai-tab-wrapper {
width: 100%;
}
.tab-container {
position: relative;
width: 100%;
height: 50px;
display: flex;
overflow: hidden;
}
.tab-item {
position: relative;
flex: 1;

View File

@@ -80,7 +80,7 @@ $font-size-label: 10px;
justify-content: center;
width: 32px;
height: 32px;
border-radius: $uni-border-radius-circle;
border-radius: 50%;
transition: background-color 0.2s;
&:active {

View File

@@ -5,6 +5,6 @@
.checkbox-icon {
margin-right: 6px;
color: $theme-color-500;
color: #0ccd58;
}
}

View File

@@ -1,5 +1,5 @@
.command-wrapper {
background-color: $theme-color-500;
background-color: #0ccd58;
border-radius: 20px 4px 20px 20px;
padding: 8px 24px;
width: max-content;

View File

@@ -1,84 +1,42 @@
<template>
<div class="create-service-order">
<div
class="w-full bg-white border-box border-ff overflow-hidden rounded-20"
>
<div
class="border-box order-header w-vw flex flex-items-center flex-justify-between bg-theme-color-50"
>
<div class="w-full bg-white border-box border-ff overflow-hidden rounded-20">
<div class="border-box order-header w-vw flex flex-items-center flex-justify-between bg-theme-color-50">
<spanclass="font-size-18 font-500 color-171717 text-left ml-12">
{{ isCallSuccess ? "服务已创建" : "呼叫服务" }}
</text>
<img
class="header-icon"
src="https://oss.nianxx.cn/mp/static/version_101/home/feedback.png"
/>
</text>
<img class="header-icon" src="https://oss.nianxx.cn/mp/static/version_101/home/feedback.png" />
</div>
<div v-if="!isCallSuccess" class="border-box p-12">
<div
class="bg-F5F7FA border-box flex flex-items-center p-12 rounded-10 font-size-14 color-171717 mb-12"
>
<div class="bg-F5F7FA border-box flex flex-items-center p-12 rounded-10 font-size-14 color-171717 mb-12">
<spanclass="font-500 line-height-22 mr-20">所在位置</text>
<input placeholder="请填写所在位置" v-model="roomId" />
<input placeholder="请填写所在位置" v-model="roomId" />
</div>
<div
class="bg-F5F7FA border-box flex flex-items-center p-12 rounded-10 font-size-14 color-171717 mb-12"
>
<div class="bg-F5F7FA border-box flex flex-items-center p-12 rounded-10 font-size-14 color-171717 mb-12">
<spanclass="font-500 line-height-22 mr-20">联系电话</text>
<input
placeholder="请填写联系电话"
v-model="contactPhone"
@input="handleContactPhoneInput"
/>
<input placeholder="请填写联系电话" v-model="contactPhone" @input="handleContactPhoneInput" />
</div>
<div
class="bg-F5F7FA border-box p-12 rounded-10 font-size-14 font-500 color-171717 mb-12"
>
<div class="bg-F5F7FA border-box p-12 rounded-10 font-size-14 font-500 color-171717 mb-12">
<div class="font-500 line-height-22 mb-12">需求信息描述</div>
<textarea
class="h-80"
placeholder="请输入需求信息描述"
placeholder-class="font-size-14 font-400"
maxlength="100"
v-model="contactText"
/>
<textarea class="h-80" placeholder="请输入需求信息描述" placeholder-class="font-size-14 font-400" maxlength="100"
v-model="contactText" />
</div>
<div
class="bg-F5F7FA border-box p-12 rounded-10 font-size-14 font-500 color-171717 mb-12"
>
<div class="bg-F5F7FA border-box p-12 rounded-10 font-size-14 font-500 color-171717 mb-12">
<div class="font-500 line-height-22 mb-12">照片上传</div>
<div
class="w-80 h-80 bg-white rounded-8 overflow-hidden flex flex-items-center flex-justify-center"
>
<div
v-if="contentImgUrl"
class="w-full h-full relative inline-block"
>
<img
class="w-full h-full block"
:src="contentImgUrl"
mode="aspectFill"
/>
<uni-icons
class="close-btn absolute z-10"
type="close"
size="20"
color="#6A717F"
@click="handleDeleteImage"
>
<div class="w-80 h-80 bg-white rounded-8 overflow-hidden flex flex-items-center flex-justify-center">
<div v-if="contentImgUrl" class="w-full h-full relative inline-block">
<img class="w-full h-full block" :src="contentImgUrl" mode="aspectFill" />
<uni-icons class="close-btn absolute z-10" type="close" size="20" color="#6A717F"
@click="handleDeleteImage">
</uni-icons>
</div>
<div
v-else
class="w-full h-full flex flex-items-center flex-justify-center"
@click="handleChooseImage"
>
<div v-else class="w-full h-full flex flex-items-center flex-justify-center" @click="handleChooseImage">
<uni-icons fontFamily="znicons" size="24" color="#6A717F">
{{ zniconsMap["zn-camera"] }}
</uni-icons>
@@ -96,22 +54,15 @@
联系方式: {{ contactPhone }}
</div>
<div class="font-size-12 color-525866 line-height-20 ellipsis-2">
需求描述: {{ contactspan}}
需求描述: {{ contactspan }}
</div>
</div>
<img
v-if="contentImgUrl"
class="right rounded-6"
:src="contentImgUrl"
mode="aspectFill"
/>
<img v-if="contentImgUrl" class="right rounded-6" :src="contentImgUrl" mode="aspectFill" />
</div>
<div
class="btn rounded-50 color-white bg-button flex flex-items-center flex-justify-center ml-12 mr-12 mb-12"
@click="handleCall"
>
<div class="btn rounded-50 color-white bg-button flex flex-items-center flex-justify-center ml-12 mr-12 mb-12"
@click="handleCall">
{{ isCallSuccess ? "查看服务" : "立即呼叫" }}
</div>
</div>
@@ -123,7 +74,7 @@ import { ref, computed, onMounted, nextTick, defineProps, watch } from "vue";
import { SCROLL_TO_BOTTOM } from "@/constant/constant";
import { createWorkOrder } from "@/request/api/WorkOrderApi";
import { updateImageFile } from "@/request/api/UpdateFile";
import { zniconsMap } from "@/static/fonts/znicons.js";
import { zniconsMap } from "@/assets/fonts/znicons";
const props = defineProps({
toolCall: {
@@ -150,7 +101,7 @@ const contactPhone = ref("");
// 是否用户已编辑过手机号(一旦编辑则不再脱敏)
const hasEditedPhone = ref(false);
// 需求信息描述:使用可写的 ref并从工具结果初始化
const contactspan= ref("");
const contactspan = ref("");
// 手机号脱敏138****1234仅对11位数字进行处理
const maskPhone = (phone) => {

View File

@@ -14,13 +14,8 @@
<!-- 示例1: 基础用法 -->
<div class="demo-section">
<div class="section-title">示例1: 基础用法</div>
<FormCard
:form="form1"
title="游客1"
@update:name="form1.name = $event"
@update:phone="form1.phone = $event"
@delete="handleDelete1"
/>
<FormCard :form="form1" title="游客1" @update:name="form1.name = $event" @update:phone="form1.phone = $event"
@delete="handleDelete1" />
<div class="form-data">
<text>姓名: {{ form1.name }}</text>
<text>手机号: {{ form1.phone }}</text>
@@ -30,13 +25,8 @@
<!-- 示例2: 自定义标题 -->
<div class="demo-section">
<div class="section-title">示例2: 自定义标题</div>
<FormCard
:form="form2"
title="成人票"
@update:name="form2.name = $event"
@update:phone="form2.phone = $event"
@delete="handleDelete2"
/>
<FormCard :form="form2" title="成人票" @update:name="form2.name = $event" @update:phone="form2.phone = $event"
@delete="handleDelete2" />
<div class="form-data">
<text>姓名: {{ form2.name }}</text>
<text>手机号: {{ form2.phone }}</text>
@@ -46,13 +36,8 @@
<!-- 示例3: 隐藏删除图标 -->
<div class="demo-section">
<div class="section-title">示例3: 隐藏删除图标</div>
<FormCard
:form="form3"
title="联系人信息"
:show-delete-icon="false"
@update:name="form3.name = $event"
@update:phone="form3.phone = $event"
/>
<FormCard :form="form3" title="联系人信息" :show-delete-icon="false" @update:name="form3.name = $event"
@update:phone="form3.phone = $event" />
<div class="form-data">
<text>姓名: {{ form3.name }}</text>
<text>手机号: {{ form3.phone }}</text>
@@ -62,15 +47,8 @@
<!-- 示例4: 多个表单卡片 -->
<div class="demo-section">
<div class="section-title">示例4: 多个表单卡片</div>
<FormCard
v-for="(item, index) in formList"
:key="index"
:form="item"
:title="`游客${index + 1}`"
@update:name="item.name = $event"
@update:phone="item.phone = $event"
@delete="handleDeleteForm(index)"
/>
<FormCard v-for="(item, index) in formList" :key="index" :form="item" :title="`游客${index + 1}`"
@update:name="item.name = $event" @update:phone="item.phone = $event" @delete="handleDeleteForm(index)" />
<button class="add-btn" @click="addForm">添加游客</button>
<div class="form-list-data">
@@ -188,7 +166,7 @@ const addForm = () => {
font-weight: 600;
margin-bottom: 20rpx;
color: #333;
border-left: 6rpx solid $theme-color-500;
border-left: 6rpx solid #0CCD58;
padding-left: 16rpx;
}
@@ -214,7 +192,7 @@ const addForm = () => {
.add-btn {
width: 100%;
height: 80rpx;
background: $theme-color-500;
background: #0CCD58;
color: #fff;
border: none;
border-radius: 8rpx;

View File

@@ -30,7 +30,7 @@ $form-transition: all 0.2s ease;
min-height: 44px;
.uni-color {
color: $theme-color-500;
color: #0ccd58;
}
.minus,
@@ -54,7 +54,7 @@ $form-transition: all 0.2s ease;
margin-left: 8px;
font-size: $uni-font-size-lg;
font-weight: 500;
color: $theme-color-500;
color: #0ccd58;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
@@ -114,7 +114,7 @@ $form-transition: all 0.2s ease;
}
&:focus {
border-bottom-color: $theme-color-500;
border-bottom-color: #0ccd58;
&::placeholder {
opacity: 0.5;

View File

@@ -1,53 +1,37 @@
<template>
<div class="border-box border-top-8">
<div
v-if="goodsData.commodityPurchaseInstruction"
class="border-box pl-12 pr-12"
>
<ModuleTitle
v-if="showTitle"
:title="goodsData.commodityPurchaseInstruction.templateTitle"
/>
<div
v-for="(moduleItem, index) in goodsData.commodityPurchaseInstruction
.commodityPurchaseInstructionModuleEntityList"
:key="index"
>
<div
class="flex flex-items-start flex-col pt-12 pb-12"
:class="{
'border-bottom':
index <
goodsData.commodityPurchaseInstruction
.commodityPurchaseInstructionModuleEntityList.length -
1,
}"
>
<div v-if="goodsData.commodityPurchaseInstruction" class="border-box pl-12 pr-12">
<ModuleTitle v-if="showTitle" :title="goodsData.commodityPurchaseInstruction.templateTitle" />
<div v-for="(moduleItem, index) in goodsData.commodityPurchaseInstruction
.commodityPurchaseInstructionModuleEntityList" :key="index">
<div class="flex flex-items-start flex-col pt-12 pb-12" :class="{
'border-bottom':
index <
goodsData.commodityPurchaseInstruction
.commodityPurchaseInstructionModuleEntityList.length -
1,
}">
<div class="flex flex-items-center flex-row flex-shrink-0 mr-8">
<uni-icons fontFamily="znicons" size="20" color="#333">
{{ zniconsMap[moduleItem.moduleIcon] }}
</uni-icons>
<spanclass="ml-4 font-size-14 color-171717 line-height-20">
{{ moduleItem.moduleTitle }}
</text>
</text>
</div>
<spanclass="flex-full font-size-12 color-525866 line-height-20 mt-4">
{{ moduleItem.moduleContent }}
</text>
</text>
</div>
</div>
</div>
<zero-markdown-div
v-else
:markdown="goodsData.commodityTip"
:aiMode="true"
/>
<zero-markdown-div v-else :markdown="goodsData.commodityTip" :aiMode="true" />
</div>
</template>
<script setup>
import ModuleTitle from "@/components/ModuleTitle/index.vue";
import { zniconsMap } from "@/static/fonts/znicons.js";
import { zniconsMap } from "@/assets/fonts/znicons";
import { defineProps } from "vue";
// Props定义
@@ -66,6 +50,6 @@ const props = defineProps({
<style scoped lang="scss">
@font-face {
font-family: znicons;
src: url("@/static/fonts/znicons.ttf");
src: url("@/assets/fonts/znicons.ttf");
}
</style>

View File

@@ -1,53 +1,21 @@
<template>
<div class="image-swiper">
<swiper
class="swiper-box"
:style="swiperStyle"
:autoplay="false"
:interval="3000"
:duration="1000"
:current="active"
@change="handleSwiperChange"
>
<swiper-item
class="swiper-item"
v-for="(item, index) in thumbnails"
:key="index"
>
<img
class="swiper-item-image"
:src="item.photoUrl"
mode="aspectFill"
></image>
<swiper class="swiper-box" :style="swiperStyle" :autoplay="false" :interval="3000" :duration="1000"
:current="active" @change="handleSwiperChange">
<swiper-item class="swiper-item" v-for="(item, index) in thumbnails" :key="index">
<img class="swiper-item-image" :src="item.photoUrl" mode="aspectFill"></image>
</swiper-item>
</swiper>
<!-- 缩略图部分 -->
<div
v-if="showThumbnails && thumbnails.length > 0"
class="thumbnail-box"
:style="thumbnailBoxStyle"
>
<scroll-div
class="thumbnail-scroll"
scroll-x="true"
:scroll-left="scrollLeft"
:scroll-with-animation="true"
show-scrollbar="false"
>
<div v-if="showThumbnails && thumbnails.length > 0" class="thumbnail-box" :style="thumbnailBoxStyle">
<scroll-div class="thumbnail-scroll" scroll-x="true" :scroll-left="scrollLeft" :scroll-with-animation="true"
show-scrollbar="false">
<div class="thumbnail-list" v-if="thumbnails.length > 1">
<div
v-for="(thumb, index) in thumbnails"
:key="index"
:class="['thumbnail-item', { active: index === active }]"
:id="`thumbnail-${index}`"
@click="handleThumbnailClick(index)"
>
<img
class="thumbnail-image"
:src="thumb.photoUrl"
mode="aspectFill"
></image>
<div v-for="(thumb, index) in thumbnails" :key="index"
:class="['thumbnail-item', { active: index === active }]" :id="`thumbnail-${index}`"
@click="handleThumbnailClick(index)">
<img class="thumbnail-image" :src="thumb.photoUrl" mode="aspectFill"></image>
</div>
</div>
</scroll-div>
@@ -57,9 +25,9 @@
zniconsMap["zn-camera"]
}}</uni-icons>
<spanclass="custom-indicator-text">{{ thumbnails.length }}</text>
<uni-icons fontFamily="znicons" size="10" color="#fff">{{
zniconsMap["zn-nav-arrow-right"]
}}</uni-icons>
<uni-icons fontFamily="znicons" size="10" color="#fff">{{
zniconsMap["zn-nav-arrow-right"]
}}</uni-icons>
</div>
</div>
</div>
@@ -67,7 +35,7 @@
<script setup>
import { ref, computed, nextTick } from "vue";
import { zniconsMap } from "@/static/fonts/znicons.js";
import { zniconsMap } from "@/assets/fonts/znicons";
import { usePictureStore } from "@/store";
const pictureStore = usePictureStore();

View File

@@ -1,6 +1,6 @@
@font-face {
font-family: znicons;
src: url("@/static/fonts/znicons.ttf");
src: url("@/assets/fonts/znicons.ttf");
}
.image-swiper {

View File

@@ -3,23 +3,14 @@
<div class="content">
<div class="title">隐私保护指引</div>
<div class="des">
请您仔细阅读并充分理解<text
class="link"
@click="handleOpenPrivacyContract"
>{{ privacyContractName }}</text
>
如您同意前述协议的全部内容请点击同意开始使用<spanclass="cancel"
>如您不同意将被限制使用部分功能或将在您使用具体功能前再次询问以取得您的授权同意</text
>
请您仔细阅读并充分理解<text class="link" @click="handleOpenPrivacyContract">{{ privacyContractName }}</text>
如您同意前述协议的全部内容请点击同意开始使用<spanclass="cancel">如您不同意将被限制使用部分功能或将在您使用具体功能前再次询问以取得您的授权同意</text>
</div>
<div class="btns">
<button class="reject" @click="handleDisagree">拒绝</button>
<button
class="agree"
open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handleAgreePrivacyAuthorization"
>
<button class="agree" open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handleAgreePrivacyAuthorization">
同意
</button>
</div>
@@ -29,37 +20,10 @@
<script setup>
import { ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
const showPrivacy = ref(false);
const privacyContractName = ref("隐私保护指引");
onShow(() => {
// 条件编译微信小程序
// #ifdef MP-WEIXIN
wx.getPrivacySetting({
success: (res) => {
console.log("cj隐私配置", res);
if (res.errMsg == "getPrivacySetting:ok") {
privacyContractName.value = res.privacyContractName;
showPrivacy.value = !!res.needAuthorization;
}
},
});
// #endif
// 条件编译抖音小程序
// #ifdef MP-TOUTIAO
uni.getPrivacySetting({
success: (res) => {
console.log(res);
showPrivacy.value = !!res.needAuthorization;
},
});
// #endif
});
// 拒绝
const handleDisagree = () => {
showPrivacy.value = false;
@@ -75,7 +39,7 @@ const handleOpenPrivacyContract = () => {
// 条件编译微信小程序
// #ifdef MP-WEIXIN
wx.openPrivacyContract({
fail: () => {},
fail: () => { },
});
// #endif
};

View File

@@ -48,6 +48,6 @@
);
font-size: $uni-font-size-sm;
font-weight: 500;
color: $theme-color-500;
color: #0ccd58;
border-radius: $uni-border-radius-50px;
}

View File

@@ -1,15 +1,10 @@
<template>
<div class="recording-wave-btn">
<div class="audio-visualizer">
<div
v-for="(bar, index) in audioBars"
:key="index"
class="audio-bar"
:style="{
height: bar.height + 'px',
transition: 'height 0.1s ease-out',
}"
></div>
<div v-for="(bar, index) in audioBars" :key="index" class="audio-bar" :style="{
height: bar.height + 'px',
transition: 'height 0.1s ease-out',
}"></div>
</div>
</div>
</template>
@@ -107,7 +102,7 @@ defineExpose({
display: flex;
justify-content: center;
align-items: center;
background-color: $theme-color-500;
background-color: #0CCD58;
height: 44px;
border-radius: $uni-border-radius-50px;
}

View File

@@ -21,7 +21,6 @@
height: 193px;
}
.album-item {
width: 96px;
height: 60px;
@@ -34,7 +33,7 @@
/* 底部价格与购买按钮 */
.card-footer {
border-top: 1px solid rgba(0,0,0,0.04);
border-top: 1px solid rgba(0, 0, 0, 0.04);
}
.card-footer .price-left {
@@ -44,7 +43,7 @@
}
.buy-btn {
background-color: $theme-color-500;
background-color: #0ccd58;
color: #fff;
margin-top: 12px;
padding: 12px 24px;

View File

@@ -8,6 +8,6 @@
border-radius: 10px;
padding: 8px 16px;
font-size: $uni-font-size-sm;
color: $theme-color-500;
color: #0ccd58;
white-space: nowrap;
}

View File

@@ -11,7 +11,7 @@
height: 86px;
background: #fff;
border-radius: 10px;
box-shadow: 0 0 0 1px rgba(0,0,0,0.04);
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
margin-right: 12px;
padding: 8px 10px;
box-sizing: border-box;
@@ -22,25 +22,26 @@
align-items: center;
overflow: hidden;
}
.date-item .label {
margin-bottom: 6px;
color: #999;
.date-item .label {
margin-bottom: 6px;
color: #999;
}
.date-item .md {
margin-bottom: 6px;
color: #000;
.date-item .md {
margin-bottom: 6px;
color: #000;
}
.date-item .status {
font-size: 12px;
color: #999;
}
.date-item .status {
font-size: 12px;
color: #999; }
.date-item.selected {
border: 1px solid $theme-color-500;
border: 1px solid #0ccd58;
background: $theme-color-50;
}
.date-item.selected .label,
.date-item.selected .md,
.date-item.selected .status {
color: $theme-color-500;
color: #0ccd58;
}
.date-item.disabled {
opacity: 0.45;
@@ -49,7 +50,7 @@
position: absolute;
right: 0;
bottom: 0;
background: $theme-color-500;
background: #0ccd58;
color: #fff;
width: 18px;
height: 18px;
@@ -59,4 +60,4 @@
align-items: center;
justify-content: center;
font-size: 11px;
}
}

View File

@@ -0,0 +1,43 @@
<template>
<span class="inline-flex items-center justify-center leading-none select-none" :style="computedStyle" :title="title"
:aria-hidden="title ? undefined : 'true'" :role="title ? 'img' : undefined">
{{ glyph }}
</span>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { zniconsMap } from "@/assets/fonts/znicons.js";
const props = withDefaults(
defineProps<{
name: string;
size?: number | string;
color?: string;
title?: string;
}>(),
{
size: 16,
},
);
const glyph = computed(() => {
const value = (zniconsMap as Record<string, string>)[props.name];
return value ?? "";
});
const computedStyle = computed(() => {
const style: Record<string, string> = {
fontFamily: "znicons",
};
const size = props.size;
style.fontSize = typeof size === "number" ? `${size}px` : size;
if (props.color) {
style.color = props.color;
}
return style;
});
</script>