This commit is contained in:
2025-06-21 19:27:06 +08:00
parent e50aa7cbdf
commit 9abc42de68
17 changed files with 370 additions and 99 deletions

View File

@@ -714,6 +714,69 @@ const admin = {
data: data, data: data,
}); });
}, },
addChildrenComment: async (data) => {
return request({
url: '/admin/TaskChildren/addChildrenComment',
method: Method.POST,
data: data,
});
},
getChildrenComment: async (id) => {
return request({
url: '/admin/TaskChildren/getChildrenComment',
method: Method.POST,
data: {id},
});
},
delChildrenComment: async (id) => {
return request({
url: '/admin/TaskChildren/delChildrenComment',
method: Method.POST,
data: {id},
});
},
passChildrenMaterial: async (data) => {
return request({
url: '/admin/TaskChildren/passChildrenMaterial',
method: Method.POST,
data: data,
});
},
getBackinfo: async (data) => {
return request({
url: '/admin/intervention/getBackinfo',
method: Method.POST,
data: data,
});
},
checkSettlement: async (data) => {
return request({
url: '/admin/intervention/checkSettlement',
method: Method.POST,
data: data,
});
},
settlement: async (data) => {
return request({
url: '/admin/intervention/settlement',
method: Method.POST,
data: data,
});
},
editStatus: async (data) => {
return request({
url: '/admin/intervention/editStatus',
method: Method.POST,
data: data,
});
},
stopTaskChildren: async (id) => {
return request({
url: '/admin/TaskChildren/stopTaskChildren',
method: Method.POST,
data: {id},
});
},
} }
export default admin; export default admin;

View File

@@ -575,6 +575,13 @@ const merchant = {
data: data data: data
}); });
}, },
intervention: async (data) => {
return request({
url: '/index/task/intervention',
method: Method.POST,
data: data
});
},
} }
export default merchant; export default merchant;

View File

@@ -79,6 +79,13 @@ const addIntervention = async () => {
await fetchData(); await fetchData();
emits('success') emits('success')
} }
const intervention = async () => {
const {msg} = await Api.merchant.intervention({...form, id: task.id});
Message.success(msg);
await fetchData();
emits('success')
}
</script> </script>
<template> <template>
@@ -114,7 +121,7 @@ const addIntervention = async () => {
</div> </div>
</div> </div>
<div v-if="SystemStore.isRoot && vo.info?.id" class="flex justify-center"> <div v-if="vo.info?.id" class="flex justify-center">
<a-card class="w-[528px]" title="达人发起了平台介入" :header-style="{textAlign: 'center'}"> <a-card class="w-[528px]" title="达人发起了平台介入" :header-style="{textAlign: 'center'}">
<div class="font-bold text-[#1D2129] mb-[6px]">达人申诉理由:</div> <div class="font-bold text-[#1D2129] mb-[6px]">达人申诉理由:</div>
<div class="px-[16px] py-[12px] bg-[#F7F8FA]"> <div class="px-[16px] py-[12px] bg-[#F7F8FA]">
@@ -126,7 +133,7 @@ const addIntervention = async () => {
</div> </div>
</div> </div>
<div class="font-bold text-[#1D2129] mt-[20px] mb-[6px]">平台处理结果:</div> <div class="font-bold text-[#1D2129] mt-[20px] mb-[6px]">平台处理结果:</div>
<div id="ROOT" class="flex flex-col justify-center items-center"> <div id="ROOT" class="flex flex-col justify-center items-center" v-if="SystemStore.isRoot">
<a-textarea v-model:model-value="form.content" class="w-full h-[140px]" <a-textarea v-model:model-value="form.content" class="w-full h-[140px]"
placeholder="输入平台介入结果"></a-textarea> placeholder="输入平台介入结果"></a-textarea>
<div class="flex flex-wrap gap-[16px] mt-[10px] mr-auto"> <div class="flex flex-wrap gap-[16px] mt-[10px] mr-auto">
@@ -147,6 +154,14 @@ const addIntervention = async () => {
</div> </div>
<a-button type="primary" class="mt-[10px]" @click="addIntervention">平台介入</a-button> <a-button type="primary" class="mt-[10px]" @click="addIntervention">平台介入</a-button>
</div> </div>
<div v-else class="px-[16px] py-[12px] bg-[#F7F8FA]">
<div>
{{ vo.info.intro }}
</div>
<div class="grid grid-cols-5 gap-[12px] mt-[4px]">
<x-image hideDelete v-for="v in vo.info.intro_image_arr" :src="v"></x-image>
</div>
</div>
</a-card> </a-card>
</div> </div>
</div> </div>
@@ -165,7 +180,7 @@ const addIntervention = async () => {
</template> </template>
发送 发送
</a-button> </a-button>
<a-button class="absolute right-[110px] bottom-[12px] z-[2]"> <a-button class="absolute right-[110px] bottom-[12px] z-[2]" @click="intervention">
<template #icon> <template #icon>
<icon-robot/> <icon-robot/>
</template> </template>

View File

@@ -5,7 +5,9 @@ import Information from "./Information.vue";
import dayjs from "dayjs"; import dayjs from "dayjs";
import Api from "../../api/index.js"; import Api from "../../api/index.js";
import {Message} from "@arco-design/web-vue"; import {Message} from "@arco-design/web-vue";
import {useSystemStore} from "../../pinia/SystemStore/index.js";
const SystemStore = useSystemStore();
const InformationRef = ref(); const InformationRef = ref();
const {task} = defineProps({ const {task} = defineProps({
task: { task: {
@@ -57,16 +59,18 @@ const changeStatus = async () => {
</div> </div>
<div class="w-[280px] h-auto flex flex-col bg-[#F2F3F5] gap-[20px]" v-if="task"> <div class="w-[280px] h-auto flex flex-col bg-[#F2F3F5] gap-[20px]" v-if="task">
<div class="bg-white p-[20px]"> <div class="bg-white p-[20px]">
<template v-if="!SystemStore.isRoot">
<div class="mb-[20px] text-[16px]">进度管理</div> <div class="mb-[20px] text-[16px]">进度管理</div>
<x-select v-model:model-value="task.is_reply" placeholder="待回复" :api="getStatus" <x-select v-model:model-value="task.is_reply" placeholder="待回复" :api="getStatus"
@change="changeStatus" :init="true"></x-select> @change="changeStatus" :init="true"></x-select>
<a-divider></a-divider> <a-divider></a-divider>
</template>
<div class="mb-[20px] text-[16px]">进度管理</div> <div class="mb-[20px] text-[16px]">进度管理</div>
<div class="grid grid-cols-2 gap-y-[12px]"> <div class="grid grid-cols-2 gap-y-[12px]">
<div class="text-[#86909C]">创建时间</div> <div class="text-[#86909C]">创建时间</div>
<div class="#1D2129">{{ dayjs(task.createtime * 1000).format('MM-DD HH:mm') }}</div> <div class="#1D2129">{{ dayjs(task.createtime * 1000).format('MM-DD HH:mm') }}</div>
<div class="text-[#86909C]">任务编号</div> <div class="text-[#86909C]">任务编号</div>
<div class="#1D2129">{{ task.taskcode }}</div> <div class="#1D2129">{{ task?.taskcode || task.m_code }}</div>
<div class="text-[#86909C]">子任务编号</div> <div class="text-[#86909C]">子任务编号</div>
<div class="#1D2129">{{ task.uid }}</div> <div class="#1D2129">{{ task.uid }}</div>
<div class="text-[#86909C]">子任务状态</div> <div class="text-[#86909C]">子任务状态</div>

View File

@@ -2,8 +2,10 @@
import {computed} from "vue"; import {computed} from "vue";
import Api from "../../api/index.js"; import Api from "../../api/index.js";
import {Message} from "@arco-design/web-vue"; import {Message} from "@arco-design/web-vue";
import {useSystemStore} from "../../pinia/SystemStore/index.js";
const emits = defineEmits(['success']); const emits = defineEmits(['success']);
const SystemStore = useSystemStore();
const {data, hideDelete} = defineProps({ const {data, hideDelete} = defineProps({
data: { data: {
type: Object, type: Object,
@@ -16,7 +18,8 @@ const {data, hideDelete} = defineProps({
}); });
const list = computed(() => data?.flatMap(v => v.children ? [v, ...v.children] : [v])); const list = computed(() => data?.flatMap(v => v.children ? [v, ...v.children] : [v]));
const del = async (id) => { const del = async (id) => {
const {msg} = await Api.merchant.delChildrenComment(id); const api = SystemStore.isRoot ? Api.admin.delChildrenComment : Api.merchant.delChildrenComment;
const {msg} = await api(id);
Message.success(msg); Message.success(msg);
emits('success'); emits('success');
} }

View File

@@ -5,8 +5,12 @@ import Api from "../../api/index.ts";
import {Message} from "@arco-design/web-vue"; import {Message} from "@arco-design/web-vue";
import Comment from "../Comment/index.vue"; import Comment from "../Comment/index.vue";
import Talk from "../Talk/index.vue"; import Talk from "../Talk/index.vue";
import AddMaterial from "../../pages/merchant/components/AddMaterial.vue";
import AddComment from "../../pages/merchant/components/AddComment.vue";
import RejectTaskModal from "../../pages/manage/pages/manage-reward-mission/components/RejectTaskModal.vue";
const emits = defineEmits(['success']); const emits = defineEmits(['success']);
const selecdKey = ref([]);
const {id} = defineProps({ const {id} = defineProps({
id: { id: {
type: Number, type: Number,
@@ -17,22 +21,65 @@ const visible = ref(false);
const detail = reactive({}); const detail = reactive({});
const activeKey = ref(0); const activeKey = ref(0);
const getData = async (update) => {
Api.admin.getTaskChildrenInfo(id).then(({data}) => {
if (update) {
detail.content.forEach((v, index) => {
v.comment = data.content[index].comment;
});
} else {
Object.assign(detail, data);
}
});
}
watch( watch(
() => visible.value, () => visible.value,
(val) => { (val) => {
if (val) Api.admin.getTaskChildrenInfo(id).then(({data}) => { if (val) getData();
Object.assign(detail, data);
console.log('我看看我看看', data);
});
}, },
{deep: true} {deep: true}
) )
const passTaskChildren = async () => { const passTaskChildren = async () => {
const {code, msg} = await Api.admin.passTaskChildren(id); console.log(selecdKey.value);
if (code === 1) Message.success(msg);
const pro_list = [];
if (selecdKey.value.length === 0) {
pro_list.push(new Promise((reactive, reject) => {
Api.admin.passChildrenMaterial(detail.content[activeKey.value]).then((res) => {
reactive(res);
}).catch((err) => {
reject(err);
})
}));
}
selecdKey.value.forEach(v => {
pro_list.push(new Promise((reactive, reject) => {
Api.admin.passChildrenMaterial(v).then((res) => {
reactive(res);
}).catch((err) => {
reject(err);
})
}));
})
const res = await Promise.all(pro_list);
let flag = true;
for (const v of res) {
if (v.code !== 1) {
Message.warning(v.msg)
flag = false;
}
}
if (flag) {
Message.success(res[0].msg);
visible.value = false; visible.value = false;
emits('success'); emits('success');
}
} }
const refuseTaskChildren = async () => { const refuseTaskChildren = async () => {
@@ -57,41 +104,66 @@ const refuseTaskChildren = async () => {
<a-tab-pane v-for="(item, index) in detail.content" :title="`素材${index+1}`" :key="index"> <a-tab-pane v-for="(item, index) in detail.content" :title="`素材${index+1}`" :key="index">
<a-form <a-form
layout="vertical"> layout="vertical">
<a-form-item label="标题"> <a-form-item label="标题" v-if="item?.material_type?.title_limit > 0">
<a-input v-model:model-value="item.title" :disabled="detail.check_status !== 0"></a-input> <a-input v-model:model-value="item.title" :disabled="detail.check_status !== 0"
:max-length="item.material_type.title_limit"></a-input>
</a-form-item> </a-form-item>
<a-form-item label="正文"> <a-form-item label="正文" v-if="item?.material_type?.desc_limit > 0">
<a-textarea <a-textarea
auto-size v-model:model-value="item.content"
:max-length="1000" :max-length="item.material_type.desc_limit"
show-word-limit show-word-limit
:disabled="detail.check_status !== 0" :disabled="detail.check_status !== 0"
:model-value="item.content"> :model-value="item.content">
</a-textarea> </a-textarea>
</a-form-item> </a-form-item>
<a-form-item label="话题"> <a-form-item label="话题" v-if="item?.material_type?.tags_limit > 0">
<Talk v-model:model-value="item.tags_arr" :disabled="detail.check_status !== 0"></Talk> <Talk v-model:model-value="item.tags" :disabled="detail.check_status !== 0"
:limit="item?.material_type?.tags_limit"></Talk>
</a-form-item> </a-form-item>
<a-form-item label="素材"> <a-form-item label="素材">
<div v-if="item.materia_arr.length > 0" class="flex flex-wrap gap-[16px]"> <div class="flex flex-wrap gap-[16px]">
<x-image <x-image
v-for="(v, index) in item.materia_arr" v-for="(v, index) in item.material"
@delete="item.material.splice(index, 1)"
:hide-delete="detail.check_status !== 0" :hide-delete="detail.check_status !== 0"
:key="index" :key="index"
width="60px" width="60px"
height="60px" height="60px"
:src="v"> :src="v">
</x-image> </x-image>
<add-material
v-if="detail.check_status === 0"
@success="val => item.material = val"
ref="AddMaterialRef"
:id="item.task_id"
:material="item">
<div
class="size-[60px] bg-[#F2F3F5] flex justify-center items-center flex-col rounded-[8px] cursor-pointer">
<icon-plus/>
<div>添加</div>
</div> </div>
<div v-else> </add-material>
暂无素材
</div> </div>
</a-form-item> </a-form-item>
<a-form-item label="评论区内容"> <a-form-item label="评论区内容">
<div v-if="item?.comment?.length > 0" class="flex flex-col gap-[8px] w-full"> <div class="flex-grow">
<comment :data="item.comment" :hide-delete="true"></comment> <div v-if="item.comment.length > 0" class="flex flex-col gap-[8px] w-full mb-[12px]">
<comment :data="item.comment" :hide-delete="detail.check_status !== 0"
@success="getData(true)"></comment>
</div>
<add-comment
v-if="detail.check_status === 0"
@success="getData(true)"
:material="{id: id}"
:item="item">
<a-button>
<icon-plus/>
<div>添加评论</div>
</a-button>
</add-comment>
</div> </div>
</a-form-item> </a-form-item>
</a-form> </a-form>
@@ -100,16 +172,25 @@ const refuseTaskChildren = async () => {
<template #footer> <template #footer>
<div class="flex items-center gap-[8px]"> <div class="flex items-center gap-[8px]">
<!-- <a-checkbox-group>--> <a-checkbox-group v-model:model-value="selecdKey">
<!-- <template v-for="(item, index) in detail.content" :key="item">--> <template v-for="(item, index) in detail.content" :key="item">
<!-- <a-checkbox v-show="activeKey === index" :value="item">选中</a-checkbox>--> <a-checkbox v-show="activeKey === index" :value="item">选中
<!-- </template>--> </a-checkbox>
<!-- </a-checkbox-group>--> </template>
</a-checkbox-group>
<template v-if="detail.check_status === 0"> <template v-if="detail.check_status === 0">
<a-button @click="passTaskChildren" type="primary" class="ml-auto">通过 <a-button @click="passTaskChildren" type="primary" class="ml-auto">通过
</a-button> </a-button>
<a-button @click="refuseTaskChildren">拒绝</a-button> <RejectTaskModal
:api="Api.admin.refuseTaskChildren"
:id="detail.id"
@success="() => {
visible = false;
emits('success')
}">
<a-button>拒绝</a-button>
</RejectTaskModal>
</template> </template>
<a-button v-else @click="visible=false" class="ml-auto">关闭</a-button> <a-button v-else @click="visible=false" class="ml-auto">关闭</a-button>
</div> </div>

View File

@@ -34,7 +34,11 @@ const success = async () => {
</script> </script>
<template> <template>
<a-link :hoverable="false" status="danger" @click="visible=true" :disabled="disabled">拒绝</a-link> <a-link v-if="!$slots.default" :hoverable="false" status="danger" @click="visible=true" :disabled="disabled">拒绝
</a-link>
<div v-else @click="visible=true">
<slot></slot>
</div>
<a-modal <a-modal
title-align="start" title-align="start"

View File

@@ -147,7 +147,17 @@ const refuseTaskChildren = async (id) => {
:id="record.id" :id="record.id"
@success="fetchData"> @success="fetchData">
</RejectTaskModal> </RejectTaskModal>
<a-link :hoverable="false" status="danger" @click="openTerminateTask">终止子任务</a-link> <a-link
:hoverable="false"
status="danger"
@click="openTerminateTask({
Api: Api.admin.stopTaskChildren,
status_text: record.stattus_text,
type: record.status === 6 || record.status === 4 ? 'warning' : 'success',
taskId: record.id,
callback: fetchData,
})">终止子任务
</a-link>
</div> </div>
</template> </template>
</a-table> </a-table>

View File

@@ -60,35 +60,37 @@ const columns = [
]; ];
const FilterConfig = [ const FilterConfig = [
{ {
key: 'wd', key: 'm_code',
type: 'input', type: 'input',
label: '任务编号', label: '任务编号',
placeholder: '请输入任务编号', placeholder: '请输入任务编号',
}, },
{ {
key: 'wd', key: 'uid',
type: 'input', type: 'input',
label: '子任务编号', label: '子任务编号',
placeholder: '请输入子任务编号', placeholder: '请输入子任务编号',
}, },
{ {
key: 'wd', key: 'status',
type: 'select', type: 'select',
label: '标签', label: '审核状态',
placeholder: '请选择标签', placeholder: '请选择审核状态',
span: 6, span: 6,
api: async () => { api: async () => {
return await Api.admin.getStatusAttr(); return await Api.admin.getStatusAttr();
}, },
}, },
{ {
key: 'wd', key: 'bid',
type: 'input', type: 'input',
label: '商家ID', label: '商家ID',
placeholder: '请输入商家ID', placeholder: '请输入商家ID',
}, },
{ {
key: 'rangeTime', key: 'rangeTime',
start: 'start_time',
end: 'end_time',
type: 'datetime', type: 'datetime',
label: '创建日期', label: '创建日期',
} }
@@ -147,6 +149,7 @@ const refuseExchangeAll = async () => {
<!-- 免审审核 --> <!-- 免审审核 -->
<a-card> <a-card>
<Filter <Filter
@search="initFetchData"
v-model:from="po" v-model:from="po"
:config="FilterConfig"> :config="FilterConfig">
</Filter> </Filter>

View File

@@ -5,6 +5,10 @@ import Api from "../../../../api/index.js";
import Filter from "../../../../components/Filter/index.vue"; import Filter from "../../../../components/Filter/index.vue";
import XSelect from "../../../../components/XSelect/index.vue"; import XSelect from "../../../../components/XSelect/index.vue";
import Chat from "../../../../components/Chat/index.vue"; import Chat from "../../../../components/Chat/index.vue";
import LookBackfillModal from "../../../merchant/pages/communication-center/components/look-backfill-modal.vue";
import Settlement from "../../../merchant/pages/task-center/components/Settlement.vue";
import XTagSelect from "../../../../components/XSelect/XTagSelect.vue";
import {Message} from "@arco-design/web-vue";
const columns = [ const columns = [
{ {
@@ -154,12 +158,37 @@ const {loading, pagination, initFetchData, fetchData} = useTableQuery({
Object.assign(vo, data); Object.assign(vo, data);
} }
}); });
const getStatus = () => Promise.resolve({
data: [
{
id: 0,
name: '未处理',
color: 'green',
},
{
id: 1,
name: '已处理',
color: 'cyan',
},
]
});
const changeStatus = async (record) => {
const {msg} = await Api.admin.editStatus({
id: record.id,
status: record.status,
});
Message.success(msg);
await fetchData();
}
</script> </script>
<template> <template>
<!-- 平台介入 --> <!-- 平台介入 -->
<a-card> <a-card>
<Filter <Filter
@search="initFetchData"
v-model:from="po" v-model:from="po"
:config="FilterConfig"> :config="FilterConfig">
<template v-slot:deduct> <template v-slot:deduct>
@@ -197,16 +226,23 @@ const {loading, pagination, initFetchData, fetchData} = useTableQuery({
state.task = data; state.task = data;
}">沟通记录 }">沟通记录
</a-link> </a-link>
<a-link :hoverable="false">查看回填</a-link> <look-backfill-modal :item="record"></look-backfill-modal>
<a-link :hoverable="false" status="success">确认结算</a-link> <settlement :task="record" :disabled="record.is_settlement === 2"
@success="fetchData"></settlement>
</div> </div>
</template> </template>
<template v-slot:why> <template v-slot:why="{record}">
<settlement :yy="true" :task="record" :disabled="record.is_settlement > 0" @success="fetchData">
<a-link :hoverable="false">原因</a-link> <a-link :hoverable="false">原因</a-link>
</settlement>
</template> </template>
<template v-slot:status="{record}"> <template v-slot:status="{record}">
<a-tag color="green" v-if="record.status===1">已处理</a-tag> <XTagSelect
<a-tag color="cyan" v-if="record.status===0">未处理</a-tag> @change="changeStatus(record)"
v-model:model-value="record.status"
:api="getStatus"
init>
</XTagSelect>
</template> </template>
<template v-slot:settlement="{record}"> <template v-slot:settlement="{record}">
<div v-if="record.status===2" class="status success">{{ record.settlement_text }}</div> <div v-if="record.status===2" class="status success">{{ record.settlement_text }}</div>

View File

@@ -4,7 +4,9 @@ import {reactive, ref} from "vue";
import UploadAvatar from "../../../components/upload/UploadAvatar.vue"; import UploadAvatar from "../../../components/upload/UploadAvatar.vue";
import Api from "../../../api/index.js"; import Api from "../../../api/index.js";
import {Message} from "@arco-design/web-vue"; import {Message} from "@arco-design/web-vue";
import {useSystemStore} from "../../../pinia/SystemStore/index.js";
const SystemStore = useSystemStore();
const emits = defineEmits(['success']); const emits = defineEmits(['success']);
const {item, material} = defineProps({ const {item, material} = defineProps({
item: { item: {
@@ -24,7 +26,8 @@ const form = reactive({
}); });
const visible = ref(false); const visible = ref(false);
const success = async () => { const success = async () => {
const {msg} = await Api.merchant.addChildrenComment({ const api = SystemStore.isRoot ? Api.admin.addChildrenComment : Api.merchant.addChildrenComment;
const {msg} = await api({
id: material.id, id: material.id,
material_id: item.id, material_id: item.id,
pid: form.pid, pid: form.pid,
@@ -34,6 +37,7 @@ const success = async () => {
}); });
Message.success(msg); Message.success(msg);
Object.keys(form).forEach(key => form[key] = null); Object.keys(form).forEach(key => form[key] = null);
form.files = [];
form.is_reply = 0; form.is_reply = 0;
visible.value = false; visible.value = false;
emits('success'); emits('success');
@@ -65,14 +69,14 @@ const success = async () => {
:disabled="form.is_reply===0" :disabled="form.is_reply===0"
v-model:model-value="form.pid" v-model:model-value="form.pid"
:apiPo="item.id" :apiPo="item.id"
:api="Api.merchant.getChildrenComment"> :api="SystemStore.isRoot ? Api.admin.getChildrenComment : Api.merchant.getChildrenComment">
</x-select> </x-select>
</a-form-item> </a-form-item>
<a-form-item label="添加图片"> <a-form-item label="添加图片">
<UploadAvatar <UploadAvatar
:multiple="false" :multiple="false"
v-model:files="form.files" v-model:files="form.files"
:api="Api.system.uploadFile2"> :api="SystemStore.isRoot ? Api.system.uploadFile : Api.system.uploadFile2">
</UploadAvatar> </UploadAvatar>
</a-form-item> </a-form-item>
<a-form-item label="添加文字"> <a-form-item label="添加文字">

View File

@@ -5,7 +5,9 @@ import UploadButton from "../../../components/upload/UploadButton.vue";
import Api from "../../../api/index.js"; import Api from "../../../api/index.js";
import {v4} from "uuid"; import {v4} from "uuid";
import MaterialSource from "./MaterialSource.vue"; import MaterialSource from "./MaterialSource.vue";
import {useSystemStore} from "../../../pinia/SystemStore/index.js";
const SystemStore = useSystemStore();
const MaterialSourceRef = ref(); const MaterialSourceRef = ref();
const visible = ref(false); const visible = ref(false);
const targetList = reactive([]); const targetList = reactive([]);
@@ -32,7 +34,7 @@ watch(
() => visible.value, () => visible.value,
(val) => { (val) => {
if (val) { if (val) {
MaterialSourceRef.value.getMaterialList(); MaterialSourceRef.value?.getMaterialList();
targetList.length = 0; targetList.length = 0;
material.material?.forEach(v => uploadSuccess(v)); material.material?.forEach(v => uploadSuccess(v));
} }
@@ -85,7 +87,8 @@ const success = async () => {
<div class="mt-[20px]"> <div class="mt-[20px]">
<div class="text-[#1D2129] text-[14px] mb-[12px]">从本地添加</div> <div class="text-[#1D2129] text-[14px] mb-[12px]">从本地添加</div>
<UploadButton :multiple="true" :api="Api.system.uploadFile2" @success="uploadSuccess"> <UploadButton :multiple="true" :api="SystemStore.isRoot ? Api.system.uploadFile : Api.system.uploadFile2"
@success="uploadSuccess">
<template #upload-button> <template #upload-button>
<a-button> <a-button>
<template #icon> <template #icon>
@@ -97,7 +100,7 @@ const success = async () => {
</UploadButton> </UploadButton>
</div> </div>
<div class="mt-[20px]"> <div class="mt-[20px]" v-if="!SystemStore.isRoot">
<div class="text-[#1D2129] text-[14px] mb-[12px]">从素材库添加</div> <div class="text-[#1D2129] text-[14px] mb-[12px]">从素材库添加</div>
<MaterialSource <MaterialSource
ref="MaterialSourceRef" ref="MaterialSourceRef"

View File

@@ -1,11 +1,14 @@
<script setup> <script setup>
import {reactive, ref} from 'vue'; import {computed, reactive, ref} from 'vue';
import RefuseModal from "../../task-center/components/RefuseModal.vue"; import RefuseModal from "../../task-center/components/RefuseModal.vue";
import OriginTag from "../../../../../components/OriginTag/index.vue"; import OriginTag from "../../../../../components/OriginTag/index.vue";
import Api from "../../../../../api/index.js"; import Api from "../../../../../api/index.js";
import {Message} from "@arco-design/web-vue"; import {Message} from "@arco-design/web-vue";
import {useSystemStore} from "../../../../../pinia/SystemStore/index.js";
const columns = [ const SystemStore = useSystemStore();
const columns = computed(() => {
const temp = [
{ {
title: '回传数据', title: '回传数据',
dataIndex: 'backData', dataIndex: 'backData',
@@ -21,7 +24,10 @@ const columns = [
dataIndex: 'backStatus', dataIndex: 'backStatus',
slotName: 'backStatus', slotName: 'backStatus',
}, },
]; ];
if (SystemStore.isRoot) temp.splice(1, 1);
return temp;
});
const {item} = defineProps({ const {item} = defineProps({
item: { item: {
type: Object, type: Object,
@@ -32,7 +38,9 @@ const visible = ref(false);
const data = reactive([]); const data = reactive([]);
const getData = async () => { const getData = async () => {
const {data: _data} = await Api.merchant.getBackinfo({id: item.id}); const api = SystemStore.isRoot ? Api.admin.getBackinfo : Api.merchant.getBackinfo;
const id = SystemStore.isRoot ? item.tc_id : item.id;
const {data: _data} = await api({id: id});
data.length = 0; data.length = 0;
data.push(..._data); data.push(..._data);
} }
@@ -65,7 +73,7 @@ const passTask = async (id, task_backfill_id) => {
:columns="columns"> :columns="columns">
<template v-slot:backData="{record}"> <template v-slot:backData="{record}">
<div class="flex flex-col"> <div class="flex flex-col">
<a-link v-for="v in record.back.content_arr" :hoverable="false" :href="v">{{ v }}</a-link> <a-link v-for="v in record.back?.content_arr" :hoverable="false" :href="v">{{ v }}</a-link>
</div> </div>
</template> </template>

View File

@@ -116,7 +116,7 @@ const vo = reactive({
rows: [], rows: [],
total: 0, total: 0,
}); });
const {loading, pagination, initFetchData} = useTableQuery({ const {loading, pagination, initFetchData, fetchData} = useTableQuery({
parameter: po, parameter: po,
api: Api.merchant.findTask, api: Api.merchant.findTask,
callback: (data) => { callback: (data) => {
@@ -172,15 +172,16 @@ const {loading, pagination, initFetchData} = useTableQuery({
<template v-slot:drfk="{record}"> <template v-slot:drfk="{record}">
<a-badge :count="record.is_read" dot :dotStyle="{ width: '10px', height: '10px' }"> <a-badge :count="record.is_read" dot :dotStyle="{ width: '10px', height: '10px' }">
<a-link :hoverable="false" @click="async () => { <a-link :hoverable="false" @click="async () => {
state.showChat = true;
const {data} = await Api.merchant.getChildrenInfo(record.id); const {data} = await Api.merchant.getChildrenInfo(record.id);
state.showChat = true;
state.task = data; state.task = data;
}">沟通记录 }">沟通记录
</a-link> </a-link>
</a-badge> </a-badge>
</template> </template>
<template v-slot:zfzt="{record}"> <template v-slot:zfzt="{record}">
<settlement :task="record" :disabled="record.is_settlement > 0"></settlement> <settlement :task="record" :disabled="record.is_settlement > 0"
@success="fetchData"></settlement>
</template> </template>
</a-table> </a-table>
</div> </div>

View File

@@ -3,8 +3,12 @@ import {reactive, ref, watch} from "vue";
import Api from "../../../../../api"; import Api from "../../../../../api";
import XImage from "../../../../../components/XImage/Index.vue"; import XImage from "../../../../../components/XImage/Index.vue";
import UploadButton from "../../../../../components/upload/UploadButton.vue"; import UploadButton from "../../../../../components/upload/UploadButton.vue";
import {Message} from "@arco-design/web-vue";
import {useSystemStore} from "../../../../../pinia/SystemStore/index.js";
const {task, disabled} = defineProps({ const SystemStore = useSystemStore();
const emits = defineEmits(['success']);
const {task, disabled, yy} = defineProps({
task: { task: {
type: Object, type: Object,
default: {}, default: {},
@@ -12,6 +16,10 @@ const {task, disabled} = defineProps({
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false, default: false,
},
yy: {
type: Boolean,
default: false,
} }
}); });
const visible = ref(false); const visible = ref(false);
@@ -47,37 +55,56 @@ const selectedKeys = ref([]);
watch( watch(
() => visible.value, () => visible.value,
(val) => { (val) => {
if (val) Api.merchant.getTaskSettltment({id: task.task_id}).then(({data}) => { if (val) {
const api = SystemStore.isRoot ? Api.admin.checkSettlement : Api.merchant.getTaskSettltment;
api({id: task.task_id || task.id}).then(({data}) => {
TaskSettltment.length = 0; TaskSettltment.length = 0;
TaskSettltment.push(...data.map((v, index) => ({ TaskSettltment.push(...data.map((v, index) => ({
...v, ...v,
key: index, key: v.id,
images: [], images: v?.images ? [...v.images] : [],
}))); })));
if (yy) {
selectedKeys.value = data.filter(v => v.is_check === 1).map(v => v.id);
console.log(selectedKeys.value);
}
}); });
} }
}
) )
const confirmTask = () => { const confirmTask = async () => {
Api.merchant.confirmTask({ const api = SystemStore.isRoot ? Api.admin.settlement : Api.merchant.confirmTask
const {msg} = await api({
id: task.id, id: task.id,
content: TaskSettltment.filter((v, index) => selectedKeys.value.includes(index)).map(v => ({ content: TaskSettltment.filter(v => selectedKeys.value.includes(v.id)).map(v => ({
...v,
id: v.id, id: v.id,
images: v.images, images: v.images,
})), })),
}); });
Message.success(msg);
emits('success');
} }
</script> </script>
<template> <template>
<a-link @click="visible = true" :hoverable="false" :disabled="disabled" status="success"> <a-link v-if="!$slots.default" @click="visible = true" :hoverable="false" :disabled="disabled" status="success">
确认结算 确认结算
</a-link> </a-link>
<div v-else @click="visible = true">
<slot></slot>
</div>
<a-modal <a-modal
width="800px" width="800px"
title-align="start" title-align="start"
@ok="confirmTask" @ok="confirmTask"
:footer="!yy"
v-model:visible="visible"> v-model:visible="visible">
<template v-slot:title> <template v-slot:title>
<div>确认结算</div> <div>确认结算</div>
@@ -91,19 +118,21 @@ const confirmTask = () => {
:row-selection="rowSelection" :row-selection="rowSelection"
v-model:selectedKeys="selectedKeys"> v-model:selectedKeys="selectedKeys">
<template v-slot:discount="{record}"> <template v-slot:discount="{record}">
{{ record.discount.toFixed(2) }} {{ record?.discount?.toFixed(2) }}
</template> </template>
<template v-slot:images="{record}"> <template v-slot:images="{record}">
<div class="flex gap-[16px]"> <div class="flex gap-[16px]">
<x-image <x-image
v-for="(v, index) in record.images" v-for="(v, index) in record.images"
:hide-delete="yy"
class="flex-shrink-0" class="flex-shrink-0"
:key="index" :key="index"
width="40px" width="40px"
height="40px" height="40px"
:src="v"> :src="v">
</x-image> </x-image>
<upload-button :api="Api.system.uploadFile2" @success="e => record.images.push(e)"> <upload-button v-if="!yy" :api="SystemStore.isRoot ? Api.system.uploadFile : Api.system.uploadFile2"
@success="e => record.images.push(e)">
<template v-slot:upload-button> <template v-slot:upload-button>
<div <div
class="size-[40px] bg-[#F2F3F5] flex justify-center items-center flex-col rounded-[8px] cursor-pointer"> class="size-[40px] bg-[#F2F3F5] flex justify-center items-center flex-col rounded-[8px] cursor-pointer">
@@ -127,7 +156,7 @@ const confirmTask = () => {
</div> </div>
<div class="text-[14px] text-[#4E5969]" v-if="selectedKeys.length > 0"> <div class="text-[14px] text-[#4E5969]" v-if="selectedKeys.length > 0">
{{ task.coin / 100 }} {{ task.coin / 100 }}
<span v-for="v in selectedKeys">- {{ TaskSettltment[v].discount }}</span> <span v-for="v in selectedKeys">- {{ TaskSettltment.find(k => k.id === v)?.discount }}</span>
= {{ = {{
task.coin / 100 task.coin / 100
- -

View File

@@ -115,7 +115,7 @@ const passTask = async (id, task_backfill_id) => {
<!-- 查看子任务 --> <!-- 查看子任务 -->
<div class="mb-[20px]"> <div class="mb-[20px]">
<a-breadcrumb <a-breadcrumb
:routes="[{path: '/', label: '任务中心'}, {path: '/', label: '悬赏任务'}, {path: '/', label: '查看子任务'}]"> :routes="[{path: '/home/task-center', label: '任务中心'}, {path: '/reward-mission', label: '悬赏任务'}, {path: '/', label: '查看子任务'}]">
</a-breadcrumb> </a-breadcrumb>
</div> </div>

View File

@@ -1,10 +1,10 @@
import {createMemoryHistory, createRouter} from 'vue-router'; import {createRouter, createWebHashHistory} from 'vue-router';
import routes from "./routes.js"; import routes from "./routes.js";
import {useUserStore} from "../pinia/UserStore/index.js"; import {useUserStore} from "../pinia/UserStore/index.js";
import {useSystemStore} from "../pinia/SystemStore/index.js"; import {useSystemStore} from "../pinia/SystemStore/index.js";
const router = createRouter({ const router = createRouter({
history: createMemoryHistory(), history: createWebHashHistory(),
routes, routes,
}) })