This commit is contained in:
2025-05-12 19:45:27 +08:00
parent 2e9c403632
commit ce0587d2b6
47 changed files with 1355 additions and 310 deletions

View File

@@ -1,12 +1,16 @@
<script setup>
import {onMounted} from "vue";
import {onMounted, reactive} from "vue";
import XModal from "./XModal.vue";
import XQrCode from "./XQrCode.vue";
import Api from "../api/index.js";
const show = defineModel('show');
const detail = reactive({});
onMounted(() => {
Api.system.getQrcode(1).then(({data}) => {
Object.assign(detail, data);
});
});
</script>
@@ -14,11 +18,12 @@ onMounted(() => {
<x-modal
v-model:show="show">
<view class="px-[30rpx] py-[40rpx] relative">
<image @click="show=false" class="!w-[52rpx] !h-[52rpx] absolute top-[-110rpx] right-[calc(-100%-10rpx)]" src="/static/icons/close.png"></image>
<image @click="show=false" class="!w-[52rpx] !h-[52rpx] absolute top-[-110rpx] right-[calc(-100%-10rpx)]"
src="/static/icons/close.png"></image>
<view class="title">微信扫码添加</view>
<view class="!mt-[24rpx] w-[320rpx] !mx-auto aspect-square">
<x-qr-code size="320rpx" :qrSize="180" content="公众号"></x-qr-code>
<image class="!size-full" :src="detail.qrcode"></image>
</view>
<view class="desc !mt-[24rpx]">请发送 [我的] 页面截图给客服</view>
<view class="desc">再描述您的问题</view>

View File

@@ -3,6 +3,9 @@ import ICON1 from '../static/icons/path1.png';
import ICON2 from '../static/icons/path2.png';
import ICON3 from '../static/icons/path3.png';
import ICON4 from '../static/icons/path4.png';
import {useUserStore} from "../pinia/UserStore/index.js";
const UserStore = useUserStore();
</script>
<template>
@@ -14,7 +17,7 @@ import ICON4 from '../static/icons/path4.png';
<view class="!absolute left-1/2 top-1/2 -translate-1/2 !flex flex-col justify-center items-center">
<view class="score">
90
{{ UserStore?.userInfo?.score }}
</view>
<view class="score-info">
信用分

View File

@@ -2,6 +2,7 @@
import {computed} from 'vue';
import messageIcon from "../static/icons/messageIcon.png";
import XActionsheet from "./XActionsheet.vue";
import OpenTypeFun from "./OpenTypeFun.js";
const itemList = computed(() => {
const item = [];
@@ -10,10 +11,18 @@ const itemList = computed(() => {
item.push({text: '标记已读', type: 1});
return item;
})
const {contextRow} = defineProps({
const {contextRow, type, data} = defineProps({
contextRow: {
type: String,
default: 'ellipsis-1'
},
type: {
type: Number,
default: 0
},
data: {
type: Object,
default: null
}
});
@@ -27,19 +36,20 @@ const selectActionsheet = (e) => {
@success="selectActionsheet"
:itemList="itemList">
<view
@click.stop="OpenTypeFun(data)"
class="!py-[30rpx] !px-[24rpx] bg-[#fff] rounded-[8rpx] !flex items-center gap-[20rpx] overflow-hidden relative !mb-[20rpx]">
<image class="!size-[72rpx] flex-shrink-0" mode="aspectFill" :src="messageIcon"></image>
<view class="flex-grow !flex flex-col gap-[12rpx]">
<view class="!flex justify-between items-center">
<view class="bh">任务编号: DF12122</view>
<view class="bh">{{ type === 0 ? '任务编号: DF12122' : data.title }}</view>
<view class="time">2024-01-26 14:00</view>
</view>
<view :class="['context', contextRow]">
商家:您的回填数据1由于***未通过请按照文档文档文档文档文档文档文档文档文档文档文档文档文档文档文档文档文档文档中操作
{{ data.content }}
</view>
</view>
<view class="status">置顶</view>
<view class="status" v-if="data.is_top === 1">置顶</view>
</view>
</x-actionsheet>
</template>

View File

@@ -0,0 +1,32 @@
import {toPage} from "../utils/uils.js";
const OpenTypeFun = async (options) => {
console.log('OpenTypeFun打开', options);
const {type, url, single_id} = options;
switch (type) {
case 0: { // 空
break;
}
case 1: { // 站内url
await toPage(url);
break;
}
case 2: { // 站内富文本
await toPage(`/pages/richPage/index?id=${single_id}`);
break;
}
case 3: { // 微信连接
break;
}
case 4: { // 外部连接
window.open(url);
break;
}
case 5: { // 弹窗
console.log('弹窗');
break;
}
}
}
export default OpenTypeFun;

View File

@@ -1,30 +1,39 @@
<script setup>
import dy from "../static/images/抖音.png";
import qrw from "../static/icons/qrw.png";
import {numberToCharacter, toPage} from "../utils/uils.js";
import dayjs from "dayjs";
const {data} = defineProps({
data: {
type: Object,
default: null
}
});
</script>
<template>
<view class="rounded-[8rpx] bg-[#fff] !p-[24rpx]">
<view class="rounded-[8rpx] bg-[#fff] !p-[24rpx]" @click="toPage(`/pages/taskDetails/index?id=${data.id}`)">
<view class="!flex gap-[26rpx]">
<image class="!size-[88rpx] rounded-[50%] overflow-hidden" mode="aspectFill" :src="dy"></image>
<view class="!h-[88rpx] !flex flex-col justify-between">
<view class="title">美白祛斑洗面奶</view>
<view class="title">{{ data.goods_name }}</view>
<view class="!flex gap-[8rpx]">
<view class="tag">抖音</view>
<view class="tag">连发</view>
<view class="tag">{{ data.platform }}</view>
<view class="tag">{{ numberToCharacter(data.fb_num - 1) }}连发</view>
</view>
</view>
<view class="!h-[88rpx] !ml-auto">
<view class="price">
<text class="unit">¥</text>
8.56
{{ data.real_price.toFixed(2) }}
</view>
<view class="price-info">剩余3个名额</view>
<view class="price-info">剩余{{ data.children_num }}个名额</view>
</view>
</view>
<view class="!mt-[34rpx] !px-[20rpx] !py-[10rpx] bg-[#F2F3F5] info relative">
截止时间08月23日 14:00
截止时间{{ dayjs(data.end_time).format('MM月DD日 HH:mm') }}
<view class="absolute top-1/2 -translate-y-1/2 right-0">
<image class="!w-[168rpx]" :src="qrw" mode="widthFix"></image>
</view>

View File

@@ -37,7 +37,8 @@ const success = () => {
<view class="py-[40rpx] px-[32rpx] !flex justify-center flex-col items-center gap-[20rpx]">
<template v-if="!$slots.context">
<view class="title">{{ title }}</view>
<view class="info">{{ info }}</view>
<view class="info" v-if="!$slots.info">{{ info }}</view>
<slot name="info" v-else></slot>
</template>
<slot name="context" v-else></slot>
</view>

View File

@@ -1,9 +1,14 @@
<script setup>
const {active} = defineProps({
active: {
type: Boolean,
default: false,
}
});
</script>
<template>
<view class="!py-[14rpx] !px-[24rpx] text">
<view :class="['!py-[14rpx] !px-[24rpx] text', active ? 'active' : '']">
<slot></slot>
</view>
</template>
@@ -16,5 +21,11 @@
line-height: 140%;
letter-spacing: 0;
text-align: left;
background-color: #fff;
transition: 500ms;
}
.active {
background-color: rgba(106, 161, 255, 0.2);
}
</style>

View File

@@ -1,13 +1,29 @@
<script setup>
import {ref} from "vue";
import XDropdownItem from "./XDropdownItem.vue";
const show = ref(false);
const modelValue = defineModel();
const emits = defineEmits(['change']);
const {option} = defineProps({
option: {
type: Array,
default: [],
}
});
const change = (id) => {
modelValue.value = id;
emits('change');
}
</script>
<template>
<view class="relative z-[99]">
<view class="relative z-[9990]">
<view @click="show=!show">
<slot></slot>
<view class="bg-[#fff] !py-[14rpx] !px-[24rpx] rounded-[8rpx]">
{{ option.find(v => v.id === modelValue)?.name }}
</view>
<tui-icon
:style="{
@@ -20,8 +36,11 @@ const show = ref(false);
</view>
<transition name="fade">
<view v-if="show" class="absolute top-[calc(100%+10rpx)] min-w-full bg-[#fff] rounded-[8rpx] x-dropdown-card">
<slot name="menu"></slot>
<view v-if="show"
class="absolute top-[calc(100%+10rpx)] min-w-full bg-[#fff] rounded-[8rpx] x-dropdown-card">
<x-dropdown-item v-for="v in option" @click="change(v.id)" :active="modelValue===v.id">
{{ v.name }}
</x-dropdown-item>
</view>
</transition>
</view>

View File

@@ -14,6 +14,7 @@ const {model, rules} = defineProps({
const verify = () => {
Object.entries(model).forEach(([key, value]) => {
console.log(rules[key], key)
if (!rules[key].reg.test(value)) {
showToast({
icon: 'error',

View File

@@ -9,7 +9,7 @@ const {label} = defineProps({
<template>
<view class="x-form-item">
<view class="!mb-[8rpx]" v-if="label">{{ label }}</view>
<view class="!mb-[8rpx] x-form-item-label" v-if="label">{{ label }}</view>
<slot></slot>
</view>
</template>

View File

@@ -16,7 +16,7 @@ const modelValue = defineModel();
<template>
<view class="x-input rounded-[12rpx] !flex items-center px-[32rpx]">
<slot name="prefix"></slot>
<input v-model="modelValue" :placeholder="placeholder"></input>
<input v-model="modelValue" v-bind="$attrs" :placeholder="placeholder"></input>
<slot name="suffix"></slot>
</view>
</template>

View File

@@ -0,0 +1,29 @@
<script setup>
import {ref} from "vue";
import ICON from "../static/icons/prompt.png";
import XConfirmModal from "./XConfirmModal.vue";
const show = ref(false);
</script>
<template>
<image v-if="!$slots.button" class="!size-[24rpx]" :src="ICON" mode="aspectFill" @click="show=true"></image>
<div v-else @click="show=true">
<slot name="button"></slot>
</div>
<x-confirm-modal
width="500rpx"
v-bind="$attrs"
:cancel="false"
confirm-text="知道了"
v-model:show="show">
<template #info v-if="$slots.info">
<slot name="info"></slot>
</template>
</x-confirm-modal>
</template>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,51 @@
<script setup lang="ts">
import DOWNICON from "../static/icons/down.png";
import {onMounted, reactive} from "vue";
const {placeholder, api} = defineProps({
placeholder: {
type: String,
default: "请选择"
},
api: {
type: Function,
default: () => {
}
}
});
const list = reactive([]);
const modelValue = defineModel();
const change = ({detail: {value}}) => {
modelValue.value = list[value].id;
}
onMounted(() => {
api && api().then(({data}) => {
list.length = 0;
list.push(...data);
});
});
</script>
<template>
<picker :range="list.filter(v => !v.hidden).map(v => v.name)" @change="change">
<view class="x-select">
<view v-if="modelValue === null" class="text-[#86909C] test-28r">
{{ placeholder }}
</view>
<view v-else>
{{ list.find(v => v.id === modelValue)?.name }}
</view>
<image :src="DOWNICON" class="!size-[24rpx]" mode="aspectFill"></image>
</view>
</picker>
</template>
<style scoped lang="scss">
.x-select {
@apply px-[24rpx] py-[16rpx] bg-[#F2F3F5] rounded-[4rpx] h-[80rpx] flex items-center justify-between;
}
</style>

View File

@@ -0,0 +1,60 @@
<script setup lang="ts">
import ADDICON from "../static/icons/add.png";
import {uploadFile} from "../utils/uils";
import XImage from "./XImage.vue";
const {size} = defineProps({
size: {
type: String,
default: "160rpx"
}
});
const emits = defineEmits(['success']);
const files = defineModel('files');
const upload = async () => {
uploadFile({
count: 1,
}).then(({data}) => {
files.value.push(data);
emits('success', data);
})
}
</script>
<template>
<view class="!flex gap-[12rpx] flex-wrap">
<view class="x-upload" @click="upload">
<image class="!size-[28rpx]" :src="ADDICON"></image>
<view>上传图片</view>
</view>
<x-image
:style="{
width: size,
height: size,
}"
class="border border-[rgb(229,230,235)]"
v-for="v in files"
:src="v"
:list="[v]"
:key="v">
</x-image>
</view>
</template>
<style scoped lang="scss">
.x-upload {
border: 1px dashed rgb(229, 230, 235);
background-color: #F2F3F5;
width: v-bind(size);
height: v-bind(size);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 22rpx;
font-size: 24rpx;
border-radius: 4px;
}
</style>