update
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
"@tinymce/tinymce-vue": "^6.1.0",
|
"@tinymce/tinymce-vue": "^6.1.0",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"pinia-plugin-persistedstate": "^4.2.0",
|
"pinia-plugin-persistedstate": "^4.2.0",
|
||||||
"plyr": "^3.7.8",
|
"plyr": "^3.7.8",
|
||||||
|
|||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -17,6 +17,9 @@ importers:
|
|||||||
crypto-js:
|
crypto-js:
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
version: 4.2.0
|
version: 4.2.0
|
||||||
|
dayjs:
|
||||||
|
specifier: ^1.11.13
|
||||||
|
version: 1.11.13
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^3.0.2
|
specifier: ^3.0.2
|
||||||
version: 3.0.2(vue@3.5.13)
|
version: 3.0.2(vue@3.5.13)
|
||||||
|
|||||||
@@ -567,6 +567,20 @@ const admin = {
|
|||||||
data: data,
|
data: data,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
passExchange: async (ids) => {
|
||||||
|
return request({
|
||||||
|
url: '/admin/ExchangeLog/passExchange',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {ids},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refuseExchange: async (ids) => {
|
||||||
|
return request({
|
||||||
|
url: '/admin/ExchangeLog/refuseExchange',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {ids},
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default admin;
|
export default admin;
|
||||||
|
|||||||
@@ -386,6 +386,27 @@ const merchant = {
|
|||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getTaskSettltment: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/getTaskSettltment',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addExchangeLog: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/addExchangeLog',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getExchangeLog: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/getExchangeLog',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default merchant;
|
export default merchant;
|
||||||
|
|||||||
125
src/components/Chat/Information.vue
Normal file
125
src/components/Chat/Information.vue
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<script setup>
|
||||||
|
import UploadButton from "../upload/UploadButton.vue";
|
||||||
|
import XImage from "../XImage/Index.vue";
|
||||||
|
import {reactive} from "vue";
|
||||||
|
import Api from "../../api";
|
||||||
|
import {Message} from "@arco-design/web-vue";
|
||||||
|
import useTableQuery from "../../hooks/useTableQuery.js";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const {task} = defineProps({
|
||||||
|
task: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const po = reactive({
|
||||||
|
id: task.id,
|
||||||
|
});
|
||||||
|
const vo = reactive({
|
||||||
|
rows: [],
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
const form = reactive({
|
||||||
|
content: null,
|
||||||
|
images: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const {loading, pagination, initFetchData, fetchData} = useTableQuery({
|
||||||
|
parameter: po,
|
||||||
|
api: Api.merchant.getExchangeLog,
|
||||||
|
callback: (data) => {
|
||||||
|
Object.assign(vo, data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const send = async () => {
|
||||||
|
const {msg} = await Api.merchant.addExchangeLog({
|
||||||
|
id: task.id,
|
||||||
|
...form,
|
||||||
|
});
|
||||||
|
Message.success(msg);
|
||||||
|
form.content = null;
|
||||||
|
form.images.length = 0;
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="size-full flex flex-col gap-[30px]">
|
||||||
|
<div :class="['flex gap-[18px]', v.right === 0 ? 'chat-right' : 'chat-left']" v-for="v in vo.rows">
|
||||||
|
<a-image :src="v.people.avatar" class="rounded-[50%] overflow-hidden" width="64px"
|
||||||
|
height="64px"></a-image>
|
||||||
|
<div class="content-box flex flex-col">
|
||||||
|
<div class="text-[#86909C] text-[12px]">{{ dayjs(v.createtime).format('MM月DD日 HH:mm') }}</div>
|
||||||
|
<div class="bg-white p-[16px] max-w-[330px]">
|
||||||
|
<div v-html="v.content"></div>
|
||||||
|
<div class="flex gap-[12px] mt-[12px]" v-if="v.image_arr.length > 0">
|
||||||
|
<x-image
|
||||||
|
class="flex-shrink-0"
|
||||||
|
v-for="(v, index) in v.image_arr"
|
||||||
|
:hide-delete="true"
|
||||||
|
:key="index"
|
||||||
|
width="50px"
|
||||||
|
height="50px"
|
||||||
|
:src="v">
|
||||||
|
</x-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="bg-white rounded-[2px] w-[calc(100%-40px)] h-[144px] absolute left-0 bottom-[20px] mx-[20px] py-[8px]">
|
||||||
|
<a-textarea
|
||||||
|
v-model:model-value="form.content"
|
||||||
|
class="w-full h-full"
|
||||||
|
placeholder="提示:商家可主动发起一次自定义私信,若达人没有回复,则不能继续发送。仅当达人回复后,商家可发送3次私信。">
|
||||||
|
</a-textarea>
|
||||||
|
<a-button type="primary" class="absolute right-[12px] bottom-[12px] z-[2]" @click="send">
|
||||||
|
<template #icon>
|
||||||
|
<icon-send/>
|
||||||
|
</template>
|
||||||
|
发送
|
||||||
|
</a-button>
|
||||||
|
<a-button class="absolute right-[110px] bottom-[12px] z-[2]">
|
||||||
|
<template #icon>
|
||||||
|
<icon-robot/>
|
||||||
|
</template>
|
||||||
|
申请平台介入
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<div class="flex gap-[12px] absolute bottom-[12px] left-[12px] rounded-[6px] z-[2]">
|
||||||
|
<x-image
|
||||||
|
class="flex-shrink-0"
|
||||||
|
v-for="(v, index) in form.images"
|
||||||
|
:key="index"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
:src="v">
|
||||||
|
</x-image>
|
||||||
|
<upload-button :api="Api.system.uploadFile2" @success="e => form.images.push(e)">
|
||||||
|
<template v-slot:upload-button>
|
||||||
|
<div
|
||||||
|
class="size-[32px] bg-[#F2F3F5] flex justify-center items-center flex-col rounded-[8px] cursor-pointer">
|
||||||
|
<icon-image/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</upload-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.chat-right {
|
||||||
|
@apply flex-row-reverse;
|
||||||
|
.content-box {
|
||||||
|
@apply items-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-left {
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
90
src/components/Chat/index.vue
Normal file
90
src/components/Chat/index.vue
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<script setup>
|
||||||
|
import XSelect from "../XSelect/index.vue";
|
||||||
|
import Information from "./Information.vue";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const {task} = defineProps({
|
||||||
|
task: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const visible = defineModel('visible');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
class="Chat"
|
||||||
|
width="1200px"
|
||||||
|
title="沟通记录"
|
||||||
|
:footer="false"
|
||||||
|
title-align="start"
|
||||||
|
v-model:visible="visible">
|
||||||
|
<a-alert>
|
||||||
|
平台提示:所有沟通内容均由人工审核,请勿脱离平台交易,请勿发送违规内容,违者永久封禁
|
||||||
|
</a-alert>
|
||||||
|
<div class="flex">
|
||||||
|
<div class="p-[20px] bg-[#F2F3F5] flex-grow min-h-[800px] relative">
|
||||||
|
<Information :task="task" v-if="visible"></Information>
|
||||||
|
</div>
|
||||||
|
<div class="w-[280px] h-auto flex flex-col bg-[#F2F3F5] gap-[20px]" v-if="task">
|
||||||
|
<div class="bg-white p-[20px]">
|
||||||
|
<div class="mb-[20px] text-[16px]">进度管理</div>
|
||||||
|
<x-select placeholder="待回复" api=""></x-select>
|
||||||
|
<a-divider></a-divider>
|
||||||
|
<div class="mb-[20px] text-[16px]">进度管理</div>
|
||||||
|
<div class="grid grid-cols-2 gap-y-[12px]">
|
||||||
|
<div class="text-[#86909C]">创建时间</div>
|
||||||
|
<div class="#1D2129">{{ dayjs(task.createtime * 1000).format('MM-DD HH:mm') }}</div>
|
||||||
|
<div class="text-[#86909C]">任务编号</div>
|
||||||
|
<div class="#1D2129">{{ task.taskcode }}</div>
|
||||||
|
<div class="text-[#86909C]">子任务编号</div>
|
||||||
|
<div class="#1D2129">{{ task.uid }}</div>
|
||||||
|
<div class="text-[#86909C]">子任务状态</div>
|
||||||
|
<div class="#1D2129">
|
||||||
|
<a-tag v-if="task.status === 0" color="red">待上传素材</a-tag>
|
||||||
|
<a-tag v-if="task.status === 1" color="orangered">素材审核中</a-tag>
|
||||||
|
<a-tag v-if="task.status === 2" color="orangered">重新上传素材</a-tag>
|
||||||
|
<a-tag v-if="task.status === 3" color="gray">待领取</a-tag>
|
||||||
|
<a-tag v-if="task.status === 4" color="green">已领取</a-tag>
|
||||||
|
<a-tag v-if="task.status === 5" color="green">已结算</a-tag>
|
||||||
|
<a-tag v-if="task.status === 6" color="arcoblue">已终止</a-tag>
|
||||||
|
</div>
|
||||||
|
<div class="text-[#86909C]">子任务结算进度</div>
|
||||||
|
<div class="#1D2129">
|
||||||
|
<a-tag v-if="task.is_settlement === 0" color="orangered">{{ task.settlement_text }}</a-tag>
|
||||||
|
<a-tag v-if="task.is_settlement === 1" color="gray">{{ task.settlement_text }}</a-tag>
|
||||||
|
<a-tag v-if="task.is_settlement === 2" color="green">{{ task.settlement_text }}</a-tag>
|
||||||
|
<a-tag v-if="task.is_settlement === -1" color="arcoblue">{{ task.settlement_text }}</a-tag>
|
||||||
|
</div>
|
||||||
|
<div class="text-[#86909C]">结算金额(元)</div>
|
||||||
|
<div class="#1D2129">{{ (task.real_coin / 100).toFixed(2) }}</div>
|
||||||
|
<div class="text-[#86909C]">达人账号</div>
|
||||||
|
<div class="#1D2129">{{ task.account }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-grow bg-white p-[20px]">
|
||||||
|
<div class="mb-[20px] text-[16px]">达人回填信息</div>
|
||||||
|
/
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.Chat {
|
||||||
|
.arco-modal-body {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.arco-textarea-wrapper {
|
||||||
|
background-color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -38,6 +38,8 @@ function useTableQuery({
|
|||||||
pagination.pageSize = data.page;
|
pagination.pageSize = data.page;
|
||||||
pagination.total = data.total;
|
pagination.total = data.total;
|
||||||
|
|
||||||
|
console.log('我看看看', data);
|
||||||
|
|
||||||
callback && callback({
|
callback && callback({
|
||||||
...data,
|
...data,
|
||||||
rows: data.list.map(v => ({...v, key: v.id})),
|
rows: data.list.map(v => ({...v, key: v.id})),
|
||||||
|
|||||||
@@ -1,26 +1,28 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import Filter from "../../../../components/Filter/index.vue";
|
import Filter from "../../../../components/Filter/index.vue";
|
||||||
import {reactive} from "vue";
|
import {reactive, ref} from "vue";
|
||||||
import useTableQuery from "../../../../hooks/useTableQuery.js";
|
import useTableQuery from "../../../../hooks/useTableQuery.js";
|
||||||
import Api from "../../../../api/index.js";
|
import Api from "../../../../api/index.js";
|
||||||
|
import {Message} from "@arco-design/web-vue";
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '编号',
|
title: '编号',
|
||||||
dataIndex: 'key',
|
dataIndex: 'code',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '任务编号',
|
title: '任务编号',
|
||||||
dataIndex: 'key',
|
dataIndex: 'm_code',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '子任务编号',
|
title: '子任务编号',
|
||||||
dataIndex: 'key',
|
dataIndex: 'uid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文字',
|
title: '文字',
|
||||||
dataIndex: 'key',
|
dataIndex: 'content',
|
||||||
|
slotName: 'content',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '图片',
|
title: '图片',
|
||||||
@@ -29,19 +31,19 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '来源',
|
title: '来源',
|
||||||
dataIndex: 'key',
|
dataIndex: 'type_text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
dataIndex: 'key',
|
dataIndex: 'type_uid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '类型',
|
title: '类型',
|
||||||
dataIndex: 'key',
|
dataIndex: 'pattern_text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '时间',
|
title: '时间',
|
||||||
dataIndex: 'key',
|
dataIndex: 'createtime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@@ -87,12 +89,14 @@ const FilterConfig = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const selectedKeys = ref([]);
|
||||||
const rowSelection = reactive({
|
const rowSelection = reactive({
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
showCheckedAll: true,
|
showCheckedAll: true,
|
||||||
onlyCurrent: false,
|
onlyCurrent: false,
|
||||||
});
|
});
|
||||||
const po = reactive({
|
const po = reactive({
|
||||||
|
pass: 0,
|
||||||
rangeTime: null,
|
rangeTime: null,
|
||||||
});
|
});
|
||||||
const vo = reactive({
|
const vo = reactive({
|
||||||
@@ -101,14 +105,38 @@ const vo = reactive({
|
|||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {loading, pagination, initFetchData} = useTableQuery({
|
const {loading, pagination, initFetchData, fetchData} = useTableQuery({
|
||||||
parameter: po,
|
parameter: po,
|
||||||
api: Api.system.getData,
|
api: Api.admin.getExchangeLog,
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
Object.assign(vo, data);
|
Object.assign(vo, data);
|
||||||
console.log(vo);
|
console.log(vo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const passExchange = async (id) => {
|
||||||
|
const {msg} = await Api.admin.passExchange([id]);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const refuseExchange = async (id) => {
|
||||||
|
const {msg} = await Api.admin.refuseExchange([id]);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const passExchangeAll = async () => {
|
||||||
|
const {msg} = await Api.admin.passExchange(selectedKeys.value);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const refuseExchangeAll = async () => {
|
||||||
|
const {msg} = await Api.admin.refuseExchange(selectedKeys.value);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -119,7 +147,13 @@ const {loading, pagination, initFetchData} = useTableQuery({
|
|||||||
:config="FilterConfig">
|
:config="FilterConfig">
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|
||||||
|
<div class="flex gap-[20px] mb-[20px]">
|
||||||
|
<a-button type="primary" @click="passExchangeAll">批量通过</a-button>
|
||||||
|
<a-button type="primary" @click="refuseExchangeAll">批量拒绝</a-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a-table
|
<a-table
|
||||||
|
v-model:selectedKeys="selectedKeys"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
:data="vo.rows"
|
:data="vo.rows"
|
||||||
@page-change="(e) => pagination.current = e"
|
@page-change="(e) => pagination.current = e"
|
||||||
@@ -127,18 +161,25 @@ const {loading, pagination, initFetchData} = useTableQuery({
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
class="flex-grow">
|
class="flex-grow">
|
||||||
<template v-slot:image>
|
<template v-slot:content="{record}">
|
||||||
<a-image
|
<view v-html="record.content"></view>
|
||||||
width="40px"
|
|
||||||
height="40px"
|
|
||||||
src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp">
|
|
||||||
</a-image>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:action>
|
<template v-slot:image="{record}">
|
||||||
|
<div class="flex gap-[12px]">
|
||||||
|
<a-image
|
||||||
|
v-for="v in images_arr"
|
||||||
|
width="40px"
|
||||||
|
height="40px"
|
||||||
|
:src="v">
|
||||||
|
</a-image>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:action="{record}">
|
||||||
<div class="flex items-center gap-[20px]">
|
<div class="flex items-center gap-[20px]">
|
||||||
<a-link :hoverable="false" status="success">通过</a-link>
|
<a-link @click="passExchange(record.id)" :hoverable="false" status="success">通过</a-link>
|
||||||
<a-link :hoverable="false" status="danger">拒绝</a-link>
|
<a-link @click="refuseExchange(record.id)" :hoverable="false" status="danger">拒绝</a-link>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
|||||||
@@ -1,26 +1,28 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import Filter from "../../../../components/Filter/index.vue";
|
import Filter from "../../../../components/Filter/index.vue";
|
||||||
import {reactive} from "vue";
|
import {reactive, ref} from "vue";
|
||||||
import useTableQuery from "../../../../hooks/useTableQuery.js";
|
import useTableQuery from "../../../../hooks/useTableQuery.js";
|
||||||
import Api from "../../../../api/index.js";
|
import Api from "../../../../api/index.js";
|
||||||
|
import {Message} from "@arco-design/web-vue";
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '编号',
|
title: '编号',
|
||||||
dataIndex: 'key',
|
dataIndex: 'code',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '任务编号',
|
title: '任务编号',
|
||||||
dataIndex: 'key',
|
dataIndex: 'm_code',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '子任务编号',
|
title: '子任务编号',
|
||||||
dataIndex: 'key',
|
dataIndex: 'uid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文字',
|
title: '文字',
|
||||||
dataIndex: 'key',
|
dataIndex: 'content',
|
||||||
|
slotName: 'content',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '图片',
|
title: '图片',
|
||||||
@@ -29,19 +31,19 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '来源',
|
title: '来源',
|
||||||
dataIndex: 'key',
|
dataIndex: 'type_text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
dataIndex: 'key',
|
dataIndex: 'type_uid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '类型',
|
title: '类型',
|
||||||
dataIndex: 'key',
|
dataIndex: 'pattern_text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '时间',
|
title: '时间',
|
||||||
dataIndex: 'key',
|
dataIndex: 'createtime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@@ -110,13 +112,14 @@ const FilterConfig = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const selectedKeys = ref([]);
|
||||||
const rowSelection = reactive({
|
const rowSelection = reactive({
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
showCheckedAll: true,
|
showCheckedAll: true,
|
||||||
onlyCurrent: false,
|
onlyCurrent: false,
|
||||||
});
|
});
|
||||||
const po = reactive({
|
const po = reactive({
|
||||||
pass: 0
|
pass: 1,
|
||||||
});
|
});
|
||||||
const vo = reactive({
|
const vo = reactive({
|
||||||
page: '',
|
page: '',
|
||||||
@@ -124,13 +127,37 @@ const vo = reactive({
|
|||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {loading, pagination, initFetchData} = useTableQuery({
|
const {loading, pagination, initFetchData, fetchData} = useTableQuery({
|
||||||
parameter: po,
|
parameter: po,
|
||||||
api: Api.admin.getExchangeLog,
|
api: Api.admin.getExchangeLog,
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
Object.assign(vo, data);
|
Object.assign(vo, data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const passExchange = async (id) => {
|
||||||
|
const {msg} = await Api.admin.passExchange([id]);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const refuseExchange = async (id) => {
|
||||||
|
const {msg} = await Api.admin.refuseExchange([id]);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const passExchangeAll = async () => {
|
||||||
|
const {msg} = await Api.admin.passExchange(selectedKeys.value);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const refuseExchangeAll = async () => {
|
||||||
|
const {msg} = await Api.admin.refuseExchange(selectedKeys.value);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -142,7 +169,13 @@ const {loading, pagination, initFetchData} = useTableQuery({
|
|||||||
:config="FilterConfig">
|
:config="FilterConfig">
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|
||||||
|
<div class="flex gap-[20px] mb-[20px]">
|
||||||
|
<a-button type="primary" @click="passExchangeAll">批量通过</a-button>
|
||||||
|
<a-button type="primary" @click="refuseExchangeAll">批量拒绝</a-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a-table
|
<a-table
|
||||||
|
v-model:selectedKeys="selectedKeys"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
:data="vo.rows"
|
:data="vo.rows"
|
||||||
@page-change="(e) => pagination.current = e"
|
@page-change="(e) => pagination.current = e"
|
||||||
@@ -150,18 +183,25 @@ const {loading, pagination, initFetchData} = useTableQuery({
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
class="flex-grow">
|
class="flex-grow">
|
||||||
<template v-slot:image>
|
<template v-slot:content="{record}">
|
||||||
<a-image
|
<view v-html="record.content"></view>
|
||||||
width="40px"
|
|
||||||
height="40px"
|
|
||||||
src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp">
|
|
||||||
</a-image>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:action>
|
<template v-slot:image="{record}">
|
||||||
|
<div class="flex gap-[12px]">
|
||||||
|
<a-image
|
||||||
|
v-for="v in images_arr"
|
||||||
|
width="40px"
|
||||||
|
height="40px"
|
||||||
|
:src="v">
|
||||||
|
</a-image>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:action="{record}">
|
||||||
<div class="flex items-center gap-[20px]">
|
<div class="flex items-center gap-[20px]">
|
||||||
<a-link :hoverable="false" status="success">通过</a-link>
|
<a-link @click="passExchange(record.id)" :hoverable="false" status="success">通过</a-link>
|
||||||
<a-link :hoverable="false" status="danger">拒绝</a-link>
|
<a-link @click="refuseExchange(record.id)" :hoverable="false" status="danger">拒绝</a-link>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
|||||||
141
src/pages/merchant/pages/task-center/components/Settlement.vue
Normal file
141
src/pages/merchant/pages/task-center/components/Settlement.vue
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
<script setup>
|
||||||
|
import {reactive, ref, watch} from "vue";
|
||||||
|
import Api from "../../../../../api";
|
||||||
|
import XImage from "../../../../../components/XImage/Index.vue";
|
||||||
|
import UploadButton from "../../../../../components/upload/UploadButton.vue";
|
||||||
|
|
||||||
|
const {task} = defineProps({
|
||||||
|
task: {
|
||||||
|
type: Object,
|
||||||
|
default: {},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const visible = ref(false);
|
||||||
|
const TaskSettltment = reactive([]);
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '提前约定事项',
|
||||||
|
dataIndex: 'intro'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '扣除比例',
|
||||||
|
dataIndex: 'ratio'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '扣除金额(元)',
|
||||||
|
dataIndex: 'discount',
|
||||||
|
slotName: 'discount'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '截图说明',
|
||||||
|
dataIndex: 'images',
|
||||||
|
slotName: 'images',
|
||||||
|
width: 250,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const rowSelection = reactive({
|
||||||
|
type: 'checkbox',
|
||||||
|
showCheckedAll: true,
|
||||||
|
onlyCurrent: false,
|
||||||
|
});
|
||||||
|
const selectedKeys = ref([]);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(val) => {
|
||||||
|
if (val) Api.merchant.getTaskSettltment({id: task.task_id}).then(({data}) => {
|
||||||
|
TaskSettltment.length = 0;
|
||||||
|
TaskSettltment.push(...data.map((v, index) => ({
|
||||||
|
...v,
|
||||||
|
key: index,
|
||||||
|
images: [],
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const confirmTask = () => {
|
||||||
|
Api.merchant.confirmTask({
|
||||||
|
id: task.id,
|
||||||
|
content: TaskSettltment.filter((v, index) => selectedKeys.value.includes(index)).map(v => ({
|
||||||
|
id: v.id,
|
||||||
|
images: v.images,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-link @click="visible = true" :hoverable="false" status="success">
|
||||||
|
确认结算
|
||||||
|
</a-link>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="800px"
|
||||||
|
title-align="start"
|
||||||
|
@ok="confirmTask"
|
||||||
|
v-model:visible="visible">
|
||||||
|
<template v-slot:title>
|
||||||
|
<div>确认结算</div>
|
||||||
|
<div class="text-[14px] text-[#4E5969] ml-[8px]">提示:若有扣款,请提供对应截图,方便达人理解</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-table
|
||||||
|
:data="TaskSettltment"
|
||||||
|
:columns="columns"
|
||||||
|
:pagination="false"
|
||||||
|
:row-selection="rowSelection"
|
||||||
|
v-model:selectedKeys="selectedKeys">
|
||||||
|
<template v-slot:discount="{record}">
|
||||||
|
{{ record.discount.toFixed(2) }}
|
||||||
|
</template>
|
||||||
|
<template v-slot:images="{record}">
|
||||||
|
<div class="flex gap-[16px]">
|
||||||
|
<x-image
|
||||||
|
v-for="(v, index) in record.images"
|
||||||
|
class="flex-shrink-0"
|
||||||
|
:key="index"
|
||||||
|
width="40px"
|
||||||
|
height="40px"
|
||||||
|
:src="v">
|
||||||
|
</x-image>
|
||||||
|
<upload-button :api="Api.system.uploadFile2" @success="e => record.images.push(e)">
|
||||||
|
<template v-slot:upload-button>
|
||||||
|
<div
|
||||||
|
class="size-[40px] bg-[#F2F3F5] flex justify-center items-center flex-col rounded-[8px] cursor-pointer">
|
||||||
|
<icon-plus/>
|
||||||
|
<div>添加</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</upload-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
<div class="mt-[22px] flex">
|
||||||
|
该子任务需结算:
|
||||||
|
<div class="text-[#165DFF] text-[16px]">¥{{
|
||||||
|
task.coin / 100
|
||||||
|
-
|
||||||
|
TaskSettltment.filter((v, index) => selectedKeys.includes(index)).reduce((accumulator, item) => {
|
||||||
|
return accumulator + item.discount;
|
||||||
|
}, 0)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div class="text-[14px] text-[#4E5969]" v-if="selectedKeys.length > 0">
|
||||||
|
({{ task.coin / 100 }}
|
||||||
|
<span v-for="v in selectedKeys">- {{ TaskSettltment[v].discount }}</span>
|
||||||
|
= {{
|
||||||
|
task.coin / 100
|
||||||
|
-
|
||||||
|
TaskSettltment.filter((v, index) => selectedKeys.includes(index)).reduce((accumulator, item) => {
|
||||||
|
return accumulator + item.discount;
|
||||||
|
}, 0)
|
||||||
|
}})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -11,6 +11,8 @@ import {openUrl, toPath} from "../../../../utils/index.js";
|
|||||||
import PreviewTaskMaterialModal from "./components/PreviewTaskMaterialModal.vue";
|
import PreviewTaskMaterialModal from "./components/PreviewTaskMaterialModal.vue";
|
||||||
import {Message} from "@arco-design/web-vue";
|
import {Message} from "@arco-design/web-vue";
|
||||||
import EffectManagementModal from "./components/effectManagementModal.vue";
|
import EffectManagementModal from "./components/effectManagementModal.vue";
|
||||||
|
import Settlement from "./components/Settlement.vue";
|
||||||
|
import Chat from "../../../../components/Chat/index.vue";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const taskId = ref(null);
|
const taskId = ref(null);
|
||||||
@@ -43,7 +45,7 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '领取时间',
|
title: '领取时间',
|
||||||
dataIndex: 'key',
|
dataIndex: 'accept_time',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '达人反馈',
|
title: '达人反馈',
|
||||||
@@ -69,7 +71,9 @@ const columns = [
|
|||||||
];
|
];
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
openBlackjackExpertModal: false,
|
openBlackjackExpertModal: false,
|
||||||
openEffectManagementModal: false
|
openEffectManagementModal: false,
|
||||||
|
showChat: false,
|
||||||
|
task: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const vo = reactive({
|
const vo = reactive({
|
||||||
@@ -99,10 +103,6 @@ const passTask = async (id, task_backfill_id) => {
|
|||||||
Message.success(msg);
|
Message.success(msg);
|
||||||
await fetchData();
|
await fetchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmTask = async () => {
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -189,16 +189,17 @@ const confirmTask = async () => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:callback>
|
<template v-slot:callback="{record}">
|
||||||
<a-link :hoverable="false">
|
<a-link :hoverable="false" @click="() => {
|
||||||
|
state.showChat = true;
|
||||||
|
state.task = record
|
||||||
|
}">
|
||||||
沟通记录
|
沟通记录
|
||||||
</a-link>
|
</a-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:payStatus>
|
<template v-slot:payStatus="{record}">
|
||||||
<a-link :hoverable="false" status="success" @click="confirmTask">
|
<settlement :task="record"></settlement>
|
||||||
确认结算
|
|
||||||
</a-link>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:action2="{record}">
|
<template v-slot:action2="{record}">
|
||||||
@@ -247,6 +248,11 @@ const confirmTask = async () => {
|
|||||||
v-model:visible="state.openEffectManagementModal"
|
v-model:visible="state.openEffectManagementModal"
|
||||||
@success="fetchData">
|
@success="fetchData">
|
||||||
</effect-management-modal>
|
</effect-management-modal>
|
||||||
|
|
||||||
|
<Chat
|
||||||
|
:task="state.task"
|
||||||
|
v-model:visible="state.showChat">
|
||||||
|
</Chat>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user