update
This commit is contained in:
46
src/components/Comment/index.vue
Normal file
46
src/components/Comment/index.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<script setup>
|
||||
import Api from "../../api/index.js";
|
||||
import {Message} from "@arco-design/web-vue";
|
||||
|
||||
const emits = defineEmits(['success']);
|
||||
const {data, hideDelete} = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
hideDelete: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
});
|
||||
const del = async (id) => {
|
||||
const {msg} = await Api.merchant.delChildrenComment(id);
|
||||
Message.success(msg);
|
||||
emits('success');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-for="(item, index) in data" :key="item.id" class="flex items-center">
|
||||
<div class="mr-[5px] min-w-[15px]">{{ index + 1 }}.</div>
|
||||
<div class="box">
|
||||
<div class="flex items-center whitespace-nowrap" v-if="item.pid>0">
|
||||
<img class="size-[9px] mr-[5px]" src="../../assets/images/back.png" alt=""/>
|
||||
回复{{ data.findIndex(k => k.pid === item.pid) }}:
|
||||
</div>
|
||||
<img class="size-[32px]" v-if="item.image" :src="item.image" alt=""/>
|
||||
<div class="whitespace-nowrap">{{ item.intro }}</div>
|
||||
</div>
|
||||
<a-popconfirm content="确认删除吗?" @ok="del(item.id)" v-if="!hideDelete">
|
||||
<a-button size="mini" shape="circle" type="text">
|
||||
<icon-delete/>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.box {
|
||||
@apply p-[4px] bg-[#F2F3F5] flex items-center gap-[10px] pr-[15px] mr-[10px] min-h-[40px] flex-grow;
|
||||
}
|
||||
</style>
|
||||
@@ -16,11 +16,11 @@ const UserStore = useUserStore();
|
||||
<a-dropdown>
|
||||
<a-link
|
||||
:hoverable="false">
|
||||
{{ UserStore.userInfo.nickname || UserStore.userInfo.mobile }}
|
||||
{{ UserStore?.userInfo?.nickname || UserStore?.userInfo?.mobile }}
|
||||
<icon-down/>
|
||||
</a-link>
|
||||
<template #content>
|
||||
<a-doption @click="UserStore.logout">退出登陆</a-doption>
|
||||
<a-doption @click="UserStore?.logout">退出登陆</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
|
||||
101
src/components/Pay/Alipay.vue
Normal file
101
src/components/Pay/Alipay.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<script setup>
|
||||
import {reactive, ref} from "vue";
|
||||
import {Message} from "@arco-design/web-vue";
|
||||
import Api from "../../api/index.ts";
|
||||
|
||||
const {money} = defineProps({
|
||||
money: {
|
||||
type: Number,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
const visible = ref(false);
|
||||
const qrInfo = reactive({});
|
||||
const open = () => {
|
||||
if (!money) {
|
||||
Message.warning('充值金额需大于0元');
|
||||
return;
|
||||
}
|
||||
visible.value = true;
|
||||
initQR();
|
||||
}
|
||||
|
||||
const initQR = async () => {
|
||||
const {data} = await Api.merchant.rechargeOrderQR({
|
||||
money: money,
|
||||
});
|
||||
Object.assign(qrInfo, data);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-button type="primary" @click="open">立即充值</a-button>
|
||||
|
||||
<a-modal
|
||||
:footer="false"
|
||||
id="Alipay-Modal"
|
||||
title-align="start"
|
||||
title="支付宝支付"
|
||||
v-model:visible="visible">
|
||||
<template v-if="true">
|
||||
<a-alert>平台提示:支付后未出现成功提示,点击【我已支付】刷新充值状态</a-alert>
|
||||
|
||||
<div class="py-[24px] px-[20px]">
|
||||
<div class="flex justify-center gap-[15px]">
|
||||
支付金额: <span class="text-[rgb(var(--arcoblue-6))]">{{ money }}元</span>
|
||||
</div>
|
||||
<div class="text-center mt-[20px]">打开支付宝扫描下方二维码支付</div>
|
||||
<div class="w-[200px] aspect-square mx-auto mt-[5px]">
|
||||
<img class="w-full h-full object-cover" src="" alt=""/>
|
||||
</div>
|
||||
<div class="flex justify-center mt-[5px] flex-col items-center">
|
||||
<a-link :hoverable="false" style="color: var(--color-neutral-6)">
|
||||
<icon-sync class="mr-[5px]"/>
|
||||
点击刷新
|
||||
</a-link>
|
||||
<a-button class="mx-auto mt-[20px]" type="primary">我已支付</a-button>
|
||||
</div>
|
||||
|
||||
<div class="mt-[20px] info mb-[40px]">
|
||||
<div>支付遇到问题?</div>
|
||||
<div>1、请先确认第三方支付网站是否交易完成。</div>
|
||||
<div>2、第三方支付网站显示交易成功,但账户中没有充值流水,请私聊客服</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="py-[24px] px-[20px]">
|
||||
<a-result status="success" title="充值成功">
|
||||
<template #subtitle>
|
||||
支付宝付款¥200.00
|
||||
</template>
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button type='primary'>确定</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-result>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.info {
|
||||
color: rgb(78, 89, 105);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
letter-spacing: 0;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
#Alipay-Modal {
|
||||
.arco-modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
89
src/components/Pay/PayTask.vue
Normal file
89
src/components/Pay/PayTask.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
|
||||
const payInfo = ref(null);
|
||||
const visible = ref(false);
|
||||
const emits = defineEmits(['close']);
|
||||
let successFun = () => {
|
||||
};
|
||||
const open = (options) => {
|
||||
const {props, success} = options;
|
||||
successFun = success;
|
||||
console.log('?????', options)
|
||||
payInfo.value = props.payInfo;
|
||||
visible.value = true;
|
||||
}
|
||||
const close = () => {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
const success = () => {
|
||||
successFun && successFun.apply();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
@ok="success"
|
||||
ok-text="确认支付"
|
||||
:ok-button-props="{
|
||||
disabled: payInfo?.user_money < payInfo?.total_money
|
||||
}"
|
||||
:width="600"
|
||||
id="PayTask-Modal"
|
||||
title-align="start"
|
||||
title="开始任务"
|
||||
v-model:visible="visible">
|
||||
<a-alert>平台提示:该款项不会直接打给达人,只有您对子任务确认结算后,才会打款给达人</a-alert>
|
||||
<div class="px-[30px] py-[16px] flex flex-col gap-[8px] justify-start items-start" v-if="payInfo">
|
||||
<div class="text-[#4E5969]">支付详情</div>
|
||||
<div class="flex">
|
||||
<div class="w-[100px]">任务金额(元):</div>
|
||||
<span class="text-[#4E5969]">¥{{ (payInfo.total_money - payInfo.serve_money).toFixed(2) }}</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="w-[100px]">服务费(元):</div>
|
||||
<span class="text-[#4E5969]">¥{{ payInfo.serve_money.toFixed(2) }}</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="w-[100px]">合计(元):</div>
|
||||
<span class="text-[#4E5969]">¥{{ payInfo.total_money.toFixed(2) }}</span>
|
||||
</div>
|
||||
<div class="text-[12px] text-[#86909C]">
|
||||
提示:①服务费按照实际消耗任务金额的百分比进行收取<br/>
|
||||
②若任务未被领取或者未支付全部金额,则只收取实际支付部分的服务费<br/>
|
||||
③剩余任务金额和服务费将退回钱包
|
||||
</div>
|
||||
<div>支付方式</div>
|
||||
<div class="mt-[5px]">
|
||||
<a-radio
|
||||
:disabled="payInfo.user_money < payInfo?.total_money"
|
||||
:default-checked="payInfo.user_money > payInfo?.total_money">
|
||||
钱包余额
|
||||
(可用¥{{ payInfo?.user_money?.toFixed(2) }})
|
||||
</a-radio>
|
||||
</div>
|
||||
<div class="text-[12px] text-[#86909C] pl-[20px]">
|
||||
*余额不足本次任务所需,请充值后再进行支付
|
||||
</div>
|
||||
<a-button class="mt-[20px]" type="primary">去充值</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#PayTask-Modal {
|
||||
.arco-modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
30
src/components/Plyr/Plyr.vue
Normal file
30
src/components/Plyr/Plyr.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import Plyr from "plyr";
|
||||
import 'plyr/dist/plyr.css';
|
||||
|
||||
const {src} = defineProps({
|
||||
src: {
|
||||
type: String,
|
||||
default: "",
|
||||
}
|
||||
});
|
||||
const plyrContainer = ref();
|
||||
onMounted(() => {
|
||||
new Plyr(plyrContainer.value, {});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="plyrContainer">
|
||||
<video ref="plyrContainer">
|
||||
<source :src="src">
|
||||
</video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.plyrContainer {
|
||||
width: 70%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup>
|
||||
import XImage from "../../components/XImage/Index.vue";
|
||||
import {reactive, ref, watch} from 'vue';
|
||||
import Api from "../../api/index.ts";
|
||||
import {Message} from "@arco-design/web-vue";
|
||||
import Comment from "../Comment/index.vue";
|
||||
|
||||
const emits = defineEmits(['success']);
|
||||
const {id} = defineProps({
|
||||
@@ -12,7 +14,7 @@ const {id} = defineProps({
|
||||
});
|
||||
const visible = ref(false);
|
||||
const detail = reactive({});
|
||||
const activeKey = ref(1);
|
||||
const activeKey = ref(0);
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
@@ -28,12 +30,14 @@ watch(
|
||||
const passTaskChildren = async () => {
|
||||
const {code, msg} = await Api.admin.passTaskChildren(id);
|
||||
if (code === 1) Message.success(msg);
|
||||
visible.value = false;
|
||||
emits('success');
|
||||
}
|
||||
|
||||
const refuseTaskChildren = async () => {
|
||||
const {code, msg} = await Api.admin.refuseTaskChildren(id);
|
||||
if (code === 1) Message.success(msg);
|
||||
visible.value = false;
|
||||
emits('success');
|
||||
}
|
||||
</script>
|
||||
@@ -64,41 +68,37 @@ const refuseTaskChildren = async () => {
|
||||
</a-textarea>
|
||||
</a-form-item>
|
||||
<a-form-item label="话题">
|
||||
<div id="tag-list" class="w-full bg-[var(--color-neutral-2)] p-[4px]">
|
||||
<div v-if="item.tags_arr.length > 0" id="tag-list"
|
||||
class="w-full bg-[var(--color-neutral-2)] p-[4px]">
|
||||
<a-tag v-for="v in item.tags_arr">#{{ v }}</a-tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
暂无话题
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="素材">
|
||||
<div class="flex flex-wrap gap-[16px]">
|
||||
<a-image
|
||||
v-for="v in item.materia_arr"
|
||||
<div v-if="item.materia_arr.length > 0" class="flex flex-wrap gap-[16px]">
|
||||
<x-image
|
||||
v-for="(v, index) in item.materia_arr"
|
||||
:hide-delete="true"
|
||||
:key="index"
|
||||
width="60px"
|
||||
height="60px"
|
||||
:src="v">
|
||||
</a-image>
|
||||
</x-image>
|
||||
</div>
|
||||
<div v-else>
|
||||
暂无话题
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="评论区内容">
|
||||
<div class="flex flex-col gap-[8px] w-full">
|
||||
<div class="w-full flex gap-[10px] items-center" v-for="v in detail.comment">
|
||||
{{ v.id }}.
|
||||
<div class="flex-grow bg-[var(--color-neutral-2)] p-[4px] h-[40px] flex items-center">
|
||||
<div class="text-[#4E5969] text-[14px] mr-[4px]" v-if="v.pid !== 0">
|
||||
<icon-redo/>
|
||||
回复{{ v.pid }}:
|
||||
</div>
|
||||
<a-image
|
||||
v-if="v.image"
|
||||
class="mr-[12px]"
|
||||
width="30px"
|
||||
height="30px"
|
||||
:src="v.image">
|
||||
</a-image>
|
||||
第三个很好用,大家可以在网上搜同款
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.comment.length > 0" class="flex flex-col gap-[8px] w-full">
|
||||
<comment :data="item.comment" :hide-delete="true"></comment>
|
||||
</div>
|
||||
<div v-else>
|
||||
暂无评论区内容
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
@@ -107,14 +107,18 @@ const refuseTaskChildren = async () => {
|
||||
|
||||
<template #footer>
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<a-checkbox-group>
|
||||
<template v-for="(item, index) in detail.content" :key="item">
|
||||
<a-checkbox v-show="activeKey === index" :value="item">选中</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
<!-- <a-checkbox-group>-->
|
||||
<!-- <template v-for="(item, index) in detail.content" :key="item">-->
|
||||
<!-- <a-checkbox v-show="activeKey === index" :value="item">选中</a-checkbox>-->
|
||||
<!-- </template>-->
|
||||
<!-- </a-checkbox-group>-->
|
||||
|
||||
<a-button @click="passTaskChildren" type="primary" class="ml-auto">通过</a-button>
|
||||
<a-button @click="refuseTaskChildren">拒绝</a-button>
|
||||
<template v-if="detail.check_status === 0">
|
||||
<a-button @click="passTaskChildren" type="primary" class="ml-auto">通过
|
||||
</a-button>
|
||||
<a-button @click="refuseTaskChildren">拒绝</a-button>
|
||||
</template>
|
||||
<a-button v-else @click="visible=false" class="ml-auto">关闭</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script setup>
|
||||
import {ref} from "vue";
|
||||
import {Modal} from "@arco-design/web-vue";
|
||||
import {determineMediaType} from "../../utils/index.js";
|
||||
import Plyr from "../Plyr/Plyr.vue";
|
||||
|
||||
const emits = defineEmits(['delete']);
|
||||
const {width, height, aspect} = defineProps({
|
||||
const {width, height, aspect, hideDelete, src} = defineProps({
|
||||
width: {
|
||||
type: String,
|
||||
default: '80px'
|
||||
@@ -15,6 +17,14 @@ const {width, height, aspect} = defineProps({
|
||||
aspect: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
hideDelete: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
default: "",
|
||||
}
|
||||
});
|
||||
const previewVisible = ref(false);
|
||||
@@ -33,28 +43,61 @@ const deleteImage = () => {
|
||||
<template>
|
||||
<div class="x-image-box" :style="{aspectRatio: aspect ? '1 / 1' : ''}">
|
||||
<a-image
|
||||
v-if="determineMediaType(src) === 'Image'"
|
||||
fit="contain"
|
||||
v-model:preview-visible="previewVisible"
|
||||
@preview-visible-change="(v)=>previewVisible=v"
|
||||
v-bind="$attrs"
|
||||
:src="src"
|
||||
:width="width"
|
||||
:height="height">
|
||||
</a-image>
|
||||
<video class="video" v-else-if="determineMediaType(src) === 'Video'" :src="src">
|
||||
</video>
|
||||
|
||||
<transition name="fade">
|
||||
<div class="video-preview-mask" v-if="determineMediaType(src) === 'Video' && previewVisible"
|
||||
@click="previewVisible=false">
|
||||
<plyr :src="src" @click.stop></plyr>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<div class="mask">
|
||||
<icon-eye @click="previewVisible=true" class="icon" style="color: #fff"/>
|
||||
<icon-delete @click="deleteImage" class="icon" style="color: #fff"/>
|
||||
<icon-delete @click="deleteImage" v-if="!hideDelete" class="icon" style="color: #fff"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.5s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.x-image-box {
|
||||
@apply cursor-pointer relative box-border rounded-[6px] overflow-hidden;
|
||||
outline: 1px solid #E5E6EB;
|
||||
width: v-bind(width);
|
||||
height: v-bind(height);
|
||||
|
||||
.video {
|
||||
width: v-bind(width);
|
||||
height: v-bind(height);
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.video-preview-mask {
|
||||
@apply size-full fixed z-[999] left-0 top-0 bg-[rgba(0,0,0,.6)] flex justify-center items-center;
|
||||
}
|
||||
|
||||
&:hover .mask {
|
||||
background-color: rgba(0, 0, 0, .4);
|
||||
|
||||
|
||||
44
src/components/XImage/XImageSmallList.vue
Normal file
44
src/components/XImage/XImageSmallList.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<script setup>
|
||||
const {list, size} = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: "40px"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="x-image-small-list">
|
||||
<a-image :width="size" :height="size" :src="list[0]" v-bind="$attrs"></a-image>
|
||||
<div class="x-image-small-list-mask" v-if="list.length > 1">
|
||||
+{{ list.length - 1 }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.x-image-small-list {
|
||||
width: v-bind(size);
|
||||
height: v-bind(size);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border-radius: 6px;
|
||||
|
||||
.x-image-small-list-mask {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user