update
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"pinia-plugin-persistedstate": "^4.2.0",
|
"pinia-plugin-persistedstate": "^4.2.0",
|
||||||
|
"plyr": "^3.7.8",
|
||||||
"tinymce": "^7.8.0",
|
"tinymce": "^7.8.0",
|
||||||
"uqrcodejs": "^4.0.7",
|
"uqrcodejs": "^4.0.7",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
|
|||||||
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@@ -23,6 +23,9 @@ importers:
|
|||||||
pinia-plugin-persistedstate:
|
pinia-plugin-persistedstate:
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
version: 4.2.0(pinia@3.0.2(vue@3.5.13))
|
version: 4.2.0(pinia@3.0.2(vue@3.5.13))
|
||||||
|
plyr:
|
||||||
|
specifier: ^3.7.8
|
||||||
|
version: 3.7.8
|
||||||
tinymce:
|
tinymce:
|
||||||
specifier: ^7.8.0
|
specifier: ^7.8.0
|
||||||
version: 7.8.0
|
version: 7.8.0
|
||||||
@@ -1412,6 +1415,9 @@ packages:
|
|||||||
csstype@3.1.3:
|
csstype@3.1.3:
|
||||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||||
|
|
||||||
|
custom-event-polyfill@1.0.7:
|
||||||
|
resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==}
|
||||||
|
|
||||||
dayjs@1.11.13:
|
dayjs@1.11.13:
|
||||||
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
||||||
|
|
||||||
@@ -1895,6 +1901,9 @@ packages:
|
|||||||
lines-and-columns@1.2.4:
|
lines-and-columns@1.2.4:
|
||||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||||
|
|
||||||
|
loadjs@4.3.0:
|
||||||
|
resolution: {integrity: sha512-vNX4ZZLJBeDEOBvdr2v/F+0aN5oMuPu7JTqrMwp+DtgK+AryOlpy6Xtm2/HpNr+azEa828oQjOtWsB6iDtSfSQ==}
|
||||||
|
|
||||||
local-pkg@1.1.1:
|
local-pkg@1.1.1:
|
||||||
resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==}
|
resolution: {integrity: sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -2121,6 +2130,9 @@ packages:
|
|||||||
pkg-types@2.1.0:
|
pkg-types@2.1.0:
|
||||||
resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==}
|
resolution: {integrity: sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==}
|
||||||
|
|
||||||
|
plyr@3.7.8:
|
||||||
|
resolution: {integrity: sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==}
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0:
|
possible-typed-array-names@1.1.0:
|
||||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2187,6 +2199,9 @@ packages:
|
|||||||
queue-microtask@1.2.3:
|
queue-microtask@1.2.3:
|
||||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||||
|
|
||||||
|
rangetouch@2.0.1:
|
||||||
|
resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==}
|
||||||
|
|
||||||
rc9@2.1.2:
|
rc9@2.1.2:
|
||||||
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
|
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
|
||||||
|
|
||||||
@@ -2519,6 +2534,9 @@ packages:
|
|||||||
uqrcodejs@4.0.7:
|
uqrcodejs@4.0.7:
|
||||||
resolution: {integrity: sha512-84+aZmD2godCVI+93lxE3YUAPNY8zAJvNA7xRS7R7U+q57KzMDepBSfNCwoRUhWOfR6eHFoAOcHRPwsP6ka1cA==}
|
resolution: {integrity: sha512-84+aZmD2godCVI+93lxE3YUAPNY8zAJvNA7xRS7R7U+q57KzMDepBSfNCwoRUhWOfR6eHFoAOcHRPwsP6ka1cA==}
|
||||||
|
|
||||||
|
url-polyfill@1.1.13:
|
||||||
|
resolution: {integrity: sha512-tXzkojrv2SujumYthZ/WjF7jaSfNhSXlYMpE5AYdL2I3D7DCeo+mch8KtW2rUuKjDg+3VXODXHVgipt8yGY/eQ==}
|
||||||
|
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
@@ -4095,6 +4113,8 @@ snapshots:
|
|||||||
|
|
||||||
csstype@3.1.3: {}
|
csstype@3.1.3: {}
|
||||||
|
|
||||||
|
custom-event-polyfill@1.0.7: {}
|
||||||
|
|
||||||
dayjs@1.11.13: {}
|
dayjs@1.11.13: {}
|
||||||
|
|
||||||
debug@4.4.0:
|
debug@4.4.0:
|
||||||
@@ -4560,6 +4580,8 @@ snapshots:
|
|||||||
|
|
||||||
lines-and-columns@1.2.4: {}
|
lines-and-columns@1.2.4: {}
|
||||||
|
|
||||||
|
loadjs@4.3.0: {}
|
||||||
|
|
||||||
local-pkg@1.1.1:
|
local-pkg@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
mlly: 1.7.4
|
mlly: 1.7.4
|
||||||
@@ -4764,6 +4786,14 @@ snapshots:
|
|||||||
exsolve: 1.0.5
|
exsolve: 1.0.5
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
|
|
||||||
|
plyr@3.7.8:
|
||||||
|
dependencies:
|
||||||
|
core-js: 3.42.0
|
||||||
|
custom-event-polyfill: 1.0.7
|
||||||
|
loadjs: 4.3.0
|
||||||
|
rangetouch: 2.0.1
|
||||||
|
url-polyfill: 1.1.13
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0: {}
|
possible-typed-array-names@1.1.0: {}
|
||||||
|
|
||||||
postcss-import@15.1.0(postcss@8.5.3):
|
postcss-import@15.1.0(postcss@8.5.3):
|
||||||
@@ -4817,6 +4847,8 @@ snapshots:
|
|||||||
|
|
||||||
queue-microtask@1.2.3: {}
|
queue-microtask@1.2.3: {}
|
||||||
|
|
||||||
|
rangetouch@2.0.1: {}
|
||||||
|
|
||||||
rc9@2.1.2:
|
rc9@2.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
defu: 6.1.4
|
defu: 6.1.4
|
||||||
@@ -5199,6 +5231,8 @@ snapshots:
|
|||||||
|
|
||||||
uqrcodejs@4.0.7: {}
|
uqrcodejs@4.0.7: {}
|
||||||
|
|
||||||
|
url-polyfill@1.1.13: {}
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
util@0.12.5:
|
util@0.12.5:
|
||||||
|
|||||||
@@ -232,6 +232,69 @@ const merchant = {
|
|||||||
data: {id}
|
data: {id}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
addChildrenComment: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/addChildrenComment',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getChildrenComment: async (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/getChildrenComment',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {id}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
delChildrenComment: async (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/delChildrenComment',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {id}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
editChildrenMaterial: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/editChildrenMaterial',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
editChildrenMaterimal: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/editChildrenMaterimal',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
startTask: async (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/startTask',
|
||||||
|
method: Method.POST,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
moneyToTask: async (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/moneyToTask',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {id}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stopTask: async (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/stopTask',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {id}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
endTask: async (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/index/task/endTask',
|
||||||
|
method: Method.POST,
|
||||||
|
data: {id}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default merchant;
|
export default merchant;
|
||||||
|
|||||||
BIN
src/assets/images/back.png
Normal file
BIN
src/assets/images/back.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 551 B |
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-dropdown>
|
||||||
<a-link
|
<a-link
|
||||||
:hoverable="false">
|
:hoverable="false">
|
||||||
{{ UserStore.userInfo.nickname || UserStore.userInfo.mobile }}
|
{{ UserStore?.userInfo?.nickname || UserStore?.userInfo?.mobile }}
|
||||||
<icon-down/>
|
<icon-down/>
|
||||||
</a-link>
|
</a-link>
|
||||||
<template #content>
|
<template #content>
|
||||||
<a-doption @click="UserStore.logout">退出登陆</a-doption>
|
<a-doption @click="UserStore?.logout">退出登陆</a-doption>
|
||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {reactive, ref} from "vue";
|
import {reactive, ref} from "vue";
|
||||||
import {Message} from "@arco-design/web-vue";
|
import {Message} from "@arco-design/web-vue";
|
||||||
import Api from "../../../api/index.js";
|
import Api from "../../api/index.ts";
|
||||||
|
|
||||||
const {money} = defineProps({
|
const {money} = defineProps({
|
||||||
money: {
|
money: {
|
||||||
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>
|
<script setup>
|
||||||
|
import XImage from "../../components/XImage/Index.vue";
|
||||||
import {reactive, ref, watch} from 'vue';
|
import {reactive, ref, watch} from 'vue';
|
||||||
import Api from "../../api/index.ts";
|
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";
|
||||||
|
|
||||||
const emits = defineEmits(['success']);
|
const emits = defineEmits(['success']);
|
||||||
const {id} = defineProps({
|
const {id} = defineProps({
|
||||||
@@ -12,7 +14,7 @@ const {id} = defineProps({
|
|||||||
});
|
});
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const detail = reactive({});
|
const detail = reactive({});
|
||||||
const activeKey = ref(1);
|
const activeKey = ref(0);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => visible.value,
|
() => visible.value,
|
||||||
@@ -28,12 +30,14 @@ watch(
|
|||||||
const passTaskChildren = async () => {
|
const passTaskChildren = async () => {
|
||||||
const {code, msg} = await Api.admin.passTaskChildren(id);
|
const {code, msg} = await Api.admin.passTaskChildren(id);
|
||||||
if (code === 1) Message.success(msg);
|
if (code === 1) Message.success(msg);
|
||||||
|
visible.value = false;
|
||||||
emits('success');
|
emits('success');
|
||||||
}
|
}
|
||||||
|
|
||||||
const refuseTaskChildren = async () => {
|
const refuseTaskChildren = async () => {
|
||||||
const {code, msg} = await Api.admin.refuseTaskChildren(id);
|
const {code, msg} = await Api.admin.refuseTaskChildren(id);
|
||||||
if (code === 1) Message.success(msg);
|
if (code === 1) Message.success(msg);
|
||||||
|
visible.value = false;
|
||||||
emits('success');
|
emits('success');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -64,41 +68,37 @@ const refuseTaskChildren = async () => {
|
|||||||
</a-textarea>
|
</a-textarea>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="话题">
|
<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>
|
<a-tag v-for="v in item.tags_arr">#{{ v }}</a-tag>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
暂无话题
|
||||||
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="素材">
|
<a-form-item label="素材">
|
||||||
<div class="flex flex-wrap gap-[16px]">
|
<div v-if="item.materia_arr.length > 0" class="flex flex-wrap gap-[16px]">
|
||||||
<a-image
|
<x-image
|
||||||
v-for="v in item.materia_arr"
|
v-for="(v, index) in item.materia_arr"
|
||||||
|
:hide-delete="true"
|
||||||
|
:key="index"
|
||||||
width="60px"
|
width="60px"
|
||||||
height="60px"
|
height="60px"
|
||||||
:src="v">
|
:src="v">
|
||||||
</a-image>
|
</x-image>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
暂无话题
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="评论区内容">
|
<a-form-item label="评论区内容">
|
||||||
<div class="flex flex-col gap-[8px] w-full">
|
<div v-if="item.comment.length > 0" class="flex flex-col gap-[8px] w-full">
|
||||||
<div class="w-full flex gap-[10px] items-center" v-for="v in detail.comment">
|
<comment :data="item.comment" :hide-delete="true"></comment>
|
||||||
{{ v.id }}.
|
</div>
|
||||||
<div class="flex-grow bg-[var(--color-neutral-2)] p-[4px] h-[40px] flex items-center">
|
<div v-else>
|
||||||
<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>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
@@ -107,14 +107,18 @@ 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>-->
|
||||||
<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">选中</a-checkbox>-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</a-checkbox-group>
|
<!-- </a-checkbox-group>-->
|
||||||
|
|
||||||
<a-button @click="passTaskChildren" type="primary" class="ml-auto">通过</a-button>
|
<template v-if="detail.check_status === 0">
|
||||||
<a-button @click="refuseTaskChildren">拒绝</a-button>
|
<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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {Modal} from "@arco-design/web-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 emits = defineEmits(['delete']);
|
||||||
const {width, height, aspect} = defineProps({
|
const {width, height, aspect, hideDelete, src} = defineProps({
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '80px'
|
default: '80px'
|
||||||
@@ -15,6 +17,14 @@ const {width, height, aspect} = defineProps({
|
|||||||
aspect: {
|
aspect: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
},
|
||||||
|
hideDelete: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const previewVisible = ref(false);
|
const previewVisible = ref(false);
|
||||||
@@ -33,28 +43,61 @@ const deleteImage = () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="x-image-box" :style="{aspectRatio: aspect ? '1 / 1' : ''}">
|
<div class="x-image-box" :style="{aspectRatio: aspect ? '1 / 1' : ''}">
|
||||||
<a-image
|
<a-image
|
||||||
|
v-if="determineMediaType(src) === 'Image'"
|
||||||
fit="contain"
|
fit="contain"
|
||||||
v-model:preview-visible="previewVisible"
|
v-model:preview-visible="previewVisible"
|
||||||
@preview-visible-change="(v)=>previewVisible=v"
|
@preview-visible-change="(v)=>previewVisible=v"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
|
:src="src"
|
||||||
:width="width"
|
:width="width"
|
||||||
:height="height">
|
:height="height">
|
||||||
</a-image>
|
</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">
|
<div class="mask">
|
||||||
<icon-eye @click="previewVisible=true" class="icon" style="color: #fff"/>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<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 {
|
.x-image-box {
|
||||||
@apply cursor-pointer relative box-border rounded-[6px] overflow-hidden;
|
@apply cursor-pointer relative box-border rounded-[6px] overflow-hidden;
|
||||||
outline: 1px solid #E5E6EB;
|
outline: 1px solid #E5E6EB;
|
||||||
width: v-bind(width);
|
width: v-bind(width);
|
||||||
height: v-bind(height);
|
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 {
|
&:hover .mask {
|
||||||
background-color: rgba(0, 0, 0, .4);
|
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>
|
||||||
16
src/hooks/usePayTask.js
Normal file
16
src/hooks/usePayTask.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import {createApp} from "vue";
|
||||||
|
|
||||||
|
import PayTask from "../components/Pay/PayTask.vue";
|
||||||
|
|
||||||
|
export const usePayTask = () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
const app = createApp(PayTask);
|
||||||
|
const vm = app.mount(container);
|
||||||
|
|
||||||
|
const {open} = vm;
|
||||||
|
|
||||||
|
return {
|
||||||
|
open
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,20 +3,38 @@ import XSelect from "../../../components/XSelect/index.vue";
|
|||||||
import {reactive, ref} from "vue";
|
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";
|
||||||
|
|
||||||
const {id} = defineProps({
|
const emits = defineEmits(['success']);
|
||||||
id: {
|
const {item, material} = defineProps({
|
||||||
type: Number,
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
material: {
|
||||||
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
type: 0,
|
is_reply: 0,
|
||||||
files: []
|
pid: null,
|
||||||
|
files: [],
|
||||||
|
intro: null,
|
||||||
});
|
});
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const success = async () => {
|
const success = async () => {
|
||||||
|
const {msg} = await Api.merchant.addChildrenComment({
|
||||||
|
id: material.id,
|
||||||
|
material_id: item.id,
|
||||||
|
pid: form.pid,
|
||||||
|
image: form.files,
|
||||||
|
intro: form.intro,
|
||||||
|
is_reply: form.is_reply,
|
||||||
|
});
|
||||||
|
Message.success(msg);
|
||||||
|
visible.value = false;
|
||||||
|
emits('success');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -34,14 +52,18 @@ const success = async () => {
|
|||||||
v-model:visible="visible"
|
v-model:visible="visible"
|
||||||
@ok="success">
|
@ok="success">
|
||||||
<a-form layout="vertical">
|
<a-form layout="vertical">
|
||||||
<a-form-item label="是否回复之前评论">
|
<a-form-item label="是否回复之前评论" v-if="item.comment.length !== 0">
|
||||||
<a-radio-group v-model:model-value="form.type">
|
<a-radio-group v-model:model-value="form.is_reply">
|
||||||
<a-radio :value="0">否</a-radio>
|
<a-radio :value="0">否</a-radio>
|
||||||
<a-radio :value="1">是</a-radio>
|
<a-radio :value="1">是</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="需要回复的评论" v-if="form.type===1">
|
<a-form-item label="需要回复的评论" v-if="form.is_reply===1">
|
||||||
<x-select api=""></x-select>
|
<x-select
|
||||||
|
v-model:model-value="form.pid"
|
||||||
|
:apiPo="item.id"
|
||||||
|
:api="Api.merchant.getChildrenComment">
|
||||||
|
</x-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="添加图片">
|
<a-form-item label="添加图片">
|
||||||
<UploadAvatar
|
<UploadAvatar
|
||||||
@@ -50,7 +72,7 @@ const success = async () => {
|
|||||||
</UploadAvatar>
|
</UploadAvatar>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="添加文字">
|
<a-form-item label="添加文字">
|
||||||
<a-textarea placeholder="请输入评论内容"></a-textarea>
|
<a-textarea v-model:model-value="form.intro" placeholder="请输入评论内容"></a-textarea>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {reactive, ref} from "vue";
|
import {reactive, ref, watch} from "vue";
|
||||||
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 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 {Message} from "@arco-design/web-vue";
|
||||||
|
|
||||||
const MaterialSourceRef = ref();
|
const MaterialSourceRef = ref();
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const targetList = reactive([]);
|
const targetList = reactive([]);
|
||||||
const {id} = defineProps({
|
const emits = defineEmits(['success']);
|
||||||
|
const {id, material} = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null,
|
default: null,
|
||||||
|
},
|
||||||
|
material: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -23,8 +29,33 @@ const uploadSuccess = (url) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const success = async () => {
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
MaterialSourceRef.value.getMaterialList();
|
||||||
|
targetList.length = 0;
|
||||||
|
material.material_arr.forEach(v => uploadSuccess(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
});
|
||||||
|
|
||||||
|
const success = async () => {
|
||||||
|
const {msg} = await Api.merchant.editChildrenMaterial({
|
||||||
|
id: material.id,
|
||||||
|
image: targetList.map(v => v.image),
|
||||||
|
});
|
||||||
|
Message.success(msg);
|
||||||
|
emits('success');
|
||||||
|
MaterialSourceRef.value.handleImage();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -44,7 +75,7 @@ const success = async () => {
|
|||||||
v-model:visible="visible"
|
v-model:visible="visible"
|
||||||
title="添加素材">
|
title="添加素材">
|
||||||
<div class="target">
|
<div class="target">
|
||||||
<div class="text-[#1D2129] text-[14px]">已添加5个素材(长摁图片可拖动排序)</div>
|
<div class="text-[#1D2129] text-[14px]">已添加{{ targetList.length }}个素材(长摁图片可拖动排序)</div>
|
||||||
<div class="grid grid-cols-6 mt-[10px] gap-[16px]">
|
<div class="grid grid-cols-6 mt-[10px] gap-[16px]">
|
||||||
<x-image
|
<x-image
|
||||||
@delete="targetList.splice(index,1)"
|
@delete="targetList.splice(index,1)"
|
||||||
|
|||||||
@@ -12,11 +12,14 @@ const {id} = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getMaterialList = async () => {
|
||||||
|
const {data} = await Api.merchant.getMaterialList(id);
|
||||||
|
list.length = 0;
|
||||||
|
list.push(...data);
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
Api.merchant.getMaterialList(id).then(({data}) => {
|
getMaterialList();
|
||||||
list.length = 0;
|
|
||||||
list.push(...data);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
const select = (v) => {
|
const select = (v) => {
|
||||||
const flag = selectList.value.findIndex(k => k.id === v.id);
|
const flag = selectList.value.findIndex(k => k.id === v.id);
|
||||||
@@ -27,11 +30,18 @@ const select = (v) => {
|
|||||||
selectList.value.push(v);
|
selectList.value.push(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const handle = async () => {
|
const handleImage = async () => {
|
||||||
if (type === 0) {
|
if (type.value === 0) {
|
||||||
|
selectList.value.filter(v => typeof v.id === 'number').forEach(v => {
|
||||||
|
Api.merchant.delMaterial(v.id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getMaterialList,
|
||||||
|
handleImage
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
54
src/pages/merchant/components/ViewMaterial.vue
Normal file
54
src/pages/merchant/components/ViewMaterial.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<script setup>
|
||||||
|
import XImage from "../../../components/XImage/Index.vue";
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const emits = defineEmits(['edit']);
|
||||||
|
const {id, material} = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
material: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const edit = () => {
|
||||||
|
visible.value = false;
|
||||||
|
emits('edit');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-button v-if="!$slots.default" type="primary" @click="visible=true">
|
||||||
|
添加素材
|
||||||
|
</a-button>
|
||||||
|
<div @click="visible=true" v-else class="cursor-pointer">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="visible"
|
||||||
|
title-align="start"
|
||||||
|
title="素材">
|
||||||
|
<div class="grid grid-cols-4">
|
||||||
|
<div v-for="(v, index) in material.material_arr" :key="index"
|
||||||
|
class="flex flex-col justify-center items-center gap-[10px]">
|
||||||
|
<x-image :src="v" :hide-delete="true"></x-image>
|
||||||
|
素材{{ index }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="flex gap-[12px] justify-end">
|
||||||
|
<a-button @click="edit">编辑素材</a-button>
|
||||||
|
<a-button @click="visible=false" type="primary">确定</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {reactive} from "vue";
|
import {reactive} from "vue";
|
||||||
import Alipay from "../../../components/Alipay.vue";
|
import Alipay from "../../../../../components/Pay/Alipay.vue";
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
money: null,
|
money: null,
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {reactive} from "vue";
|
import Comment from "../../../../components/Comment/index.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 {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
import MaterialLibrary from "../../components/MaterialLibrary.vue";
|
import MaterialLibrary from "../../components/MaterialLibrary.vue";
|
||||||
import AddMaterial from "../../components/AddMaterial.vue";
|
import AddMaterial from "../../components/AddMaterial.vue";
|
||||||
import AddComment from "../../components/AddComment.vue";
|
import AddComment from "../../components/AddComment.vue";
|
||||||
|
import XImageSmallList from "../../../../components/XImage/XImageSmallList.vue";
|
||||||
|
import ViewMaterial from "../../components/ViewMaterial.vue";
|
||||||
|
import {Message} from "@arco-design/web-vue";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const AddMaterialRef = ref();
|
||||||
const columns = reactive([
|
const columns = reactive([
|
||||||
{
|
{
|
||||||
title: '子任务编号',
|
title: '子任务编号',
|
||||||
@@ -49,13 +54,31 @@ const vo = reactive({
|
|||||||
pageSize: 9,
|
pageSize: 9,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {loading, pagination} = useTableQuery({
|
const {loading, pagination, fetchData} = useTableQuery({
|
||||||
parameter: po,
|
parameter: po,
|
||||||
api: Api.merchant.getTaskChildrenList,
|
api: Api.merchant.getTaskChildrenList,
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
Object.assign(vo, data);
|
Object.assign(vo, data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const editMaterial = (index) => {
|
||||||
|
AddMaterialRef.value[index].open();
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = async () => {
|
||||||
|
const {msg} = await Api.merchant.editChildrenMaterimal({
|
||||||
|
id: vo.rows[0]?.task_id,
|
||||||
|
data: vo.rows.map(v => v.childrenMaterial.map(k => ({
|
||||||
|
id: k.id,
|
||||||
|
title: k.title,
|
||||||
|
content: k.content,
|
||||||
|
tags: k.tags,
|
||||||
|
}))).flat()
|
||||||
|
});
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -63,16 +86,17 @@ const {loading, pagination} = useTableQuery({
|
|||||||
<a-card class="flex-grow text-[14px]">
|
<a-card class="flex-grow text-[14px]">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<MaterialLibrary :id="po.id"></MaterialLibrary>
|
<MaterialLibrary :id="po.id"></MaterialLibrary>
|
||||||
<a-button type="primary">确认修改</a-button>
|
<a-button type="primary" @click="success">确认修改</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-table
|
<a-table
|
||||||
:data="vo.rows"
|
:data="vo.rows"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
:scroll="{x: 'auto'}"
|
||||||
class="w-full mt-[20px] flex-grow"
|
class="w-full mt-[20px] flex-grow"
|
||||||
@page-change="(e) => pagination.current = e"
|
@page-change="(e) => pagination.current = e"
|
||||||
:pagination="pagination">
|
:pagination="false">
|
||||||
<template v-slot:title="{record}">
|
<template v-slot:title="{record}">
|
||||||
<div class="flex flex-col gap-[12px]">
|
<div class="flex flex-col gap-[12px]">
|
||||||
<a-input
|
<a-input
|
||||||
@@ -100,28 +124,46 @@ const {loading, pagination} = useTableQuery({
|
|||||||
</a-input>
|
</a-input>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:material="{record}">
|
<template v-slot:material="{record, rowIndex}">
|
||||||
<div class="flex flex-col gap-[12px]">
|
<div class="flex flex-col gap-[12px]">
|
||||||
<add-material
|
<div class="flex gap-[12px]" v-for="v in record.childrenMaterial">
|
||||||
v-for="v in record.childrenMaterial"
|
<add-material
|
||||||
:id="po.id">
|
ref="AddMaterialRef"
|
||||||
<div class="add-materials">
|
@success="fetchData"
|
||||||
<icon-plus/>
|
:id="po.id"
|
||||||
<div>添加</div>
|
:material="v">
|
||||||
</div>
|
<div class="add-materials">
|
||||||
</add-material>
|
<icon-plus/>
|
||||||
|
<div>添加</div>
|
||||||
|
</div>
|
||||||
|
</add-material>
|
||||||
|
<view-material
|
||||||
|
@edit="editMaterial(rowIndex)"
|
||||||
|
:material="v"
|
||||||
|
:id="po.id">
|
||||||
|
<x-image-small-list
|
||||||
|
:preview="false"
|
||||||
|
v-if="v.material_arr.length>0"
|
||||||
|
:list="v.material_arr">
|
||||||
|
</x-image-small-list>
|
||||||
|
</view-material>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:pl="{record}">
|
<template v-slot:pl="{record}">
|
||||||
<div class="flex flex-col gap-[12px]">
|
<div class="flex flex-col gap-[12px]">
|
||||||
<add-comment
|
<div v-for="(v, index) in record.childrenMaterial" :key="index" class="flex gap-[12px]">
|
||||||
v-for="v in record.childrenMaterial"
|
<add-comment
|
||||||
:id="v.id">
|
@success="fetchData"
|
||||||
<div class="add-materials">
|
:material="record"
|
||||||
<icon-plus/>
|
:item="v">
|
||||||
<div>添加</div>
|
<div class="add-materials">
|
||||||
</div>
|
<icon-plus/>
|
||||||
</add-comment>
|
<div>添加</div>
|
||||||
|
</div>
|
||||||
|
</add-comment>
|
||||||
|
<comment @success="fetchData" :data="v.comment"></comment>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import useTableQuery from "../../../../hooks/useTableQuery.js";
|
|||||||
import Api from "../../../../api/index.js";
|
import Api from "../../../../api/index.js";
|
||||||
import {toPath} from "../../../../utils/index.js";
|
import {toPath} from "../../../../utils/index.js";
|
||||||
import {Message} from "@arco-design/web-vue";
|
import {Message} from "@arco-design/web-vue";
|
||||||
|
import {usePayTask} from "../../../../hooks/usePayTask.js";
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@@ -100,13 +101,44 @@ const po = reactive({
|
|||||||
wd: null,
|
wd: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {loading, pagination, initFetchData} = useTableQuery({
|
const {loading, pagination, initFetchData, fetchData} = useTableQuery({
|
||||||
parameter: po,
|
parameter: po,
|
||||||
api: Api.merchant.getTaskList,
|
api: Api.merchant.getTaskList,
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
Object.assign(vo, data);
|
Object.assign(vo, data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const {open: openPayTask} = usePayTask();
|
||||||
|
|
||||||
|
const startTask = async (_value, record) => {
|
||||||
|
const {status, id} = record;
|
||||||
|
|
||||||
|
const showMessageAndFetch = async (msg) => {
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (status === -2 || status === 4) {
|
||||||
|
const {msg} = await Api.merchant.endTask(id);
|
||||||
|
await showMessageAndFetch(msg);
|
||||||
|
} else {
|
||||||
|
const {data} = await Api.merchant.startTask({id});
|
||||||
|
openPayTask({
|
||||||
|
props: {payInfo: data},
|
||||||
|
success: async () => {
|
||||||
|
const {msg} = await Api.merchant.moneyToTask(id);
|
||||||
|
await showMessageAndFetch(msg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopTask = async (id) => {
|
||||||
|
const {msg} = await Api.merchant.stopTask(id);
|
||||||
|
Message.success(msg);
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -150,7 +182,8 @@ const {loading, pagination, initFetchData} = useTableQuery({
|
|||||||
</template>
|
</template>
|
||||||
<template v-slot:start="{record}">
|
<template v-slot:start="{record}">
|
||||||
<a-switch
|
<a-switch
|
||||||
:disabled="record.status !== -2 || record.status !== 3"
|
@change="startTask($event, record)"
|
||||||
|
:disabled="record.status !== -2 && record.status !== 3 && record.status !== 4"
|
||||||
:model-value="record.status === 4">
|
:model-value="record.status === 4">
|
||||||
</a-switch>
|
</a-switch>
|
||||||
</template>
|
</template>
|
||||||
@@ -170,7 +203,9 @@ const {loading, pagination, initFetchData} = useTableQuery({
|
|||||||
@click="record.status >= 2 ? toPath('/home/task-center/look-min-task', {id: record.id}) : Message.warning('审核未通过')">
|
@click="record.status >= 2 ? toPath('/home/task-center/look-min-task', {id: record.id}) : Message.warning('审核未通过')">
|
||||||
查看子任务
|
查看子任务
|
||||||
</a-link>
|
</a-link>
|
||||||
<a-link :hoverable="false" status="danger">终止</a-link>
|
<a-popconfirm content="确认终止吗?" @ok="stopTask(record.id)">
|
||||||
|
<a-link :hoverable="false" status="danger">终止</a-link>
|
||||||
|
</a-popconfirm>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:exp>
|
<template v-slot:exp>
|
||||||
|
|||||||
@@ -21,3 +21,18 @@ export const baseImage = (url) => {
|
|||||||
if (!url) url = '';
|
if (!url) url = '';
|
||||||
return url.startsWith('http') ? url : import.meta.env.VITE_API_URL + url;
|
return url.startsWith('http') ? url : import.meta.env.VITE_API_URL + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const determineMediaType = (url) => {
|
||||||
|
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg'];
|
||||||
|
const videoExtensions = ['.mp4', '.mov', '.avi', '.mkv', '.webm'];
|
||||||
|
|
||||||
|
const extension = url.substring(url.lastIndexOf('.')).toLowerCase();
|
||||||
|
|
||||||
|
if (imageExtensions.includes(extension)) {
|
||||||
|
return 'Image';
|
||||||
|
} else if (videoExtensions.includes(extension)) {
|
||||||
|
return 'Video';
|
||||||
|
} else {
|
||||||
|
return 'Unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user