REVIEW 公众号的实现

pull/121/MERGE
YunaiV 2023-04-13 22:25:35 +08:00
parent 3aefedff6a
commit 1a1bfe0ebb
9 changed files with 20 additions and 334 deletions

View File

@ -75,7 +75,8 @@ const include = [
'element-plus/es/components/dropdown-item/style/css', 'element-plus/es/components/dropdown-item/style/css',
'element-plus/es/components/badge/style/css', 'element-plus/es/components/badge/style/css',
'element-plus/es/components/breadcrumb/style/css', 'element-plus/es/components/breadcrumb/style/css',
'element-plus/es/components/breadcrumb-item/style/css' 'element-plus/es/components/breadcrumb-item/style/css',
'element-plus/es/components/image/style/css'
] ]
const exclude = ['@iconify/json'] const exclude = ['@iconify/json']

View File

@ -3,7 +3,7 @@
<el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</template> </template>
<!-- TODO @芋艿WxMpSelect 改成 WxAccountSelect然后挪到现有的 wx-account-select 包下 -->
<script lang="ts" setup name="WxMpSelect"> <script lang="ts" setup name="WxMpSelect">
import * as MpAccountApi from '@/api/mp/account' import * as MpAccountApi from '@/api/mp/account'

View File

@ -102,5 +102,3 @@ const uploadError = () => {
</div> </div>
</div> </div>
</template> </template>
<style></style>

View File

@ -252,7 +252,6 @@ import * as MpFreePublishApi from '@/api/mp/freePublish'
import type { UploadFiles, UploadProps, UploadRawFile } from 'element-plus' import type { UploadFiles, UploadProps, UploadRawFile } from 'element-plus'
// API // API
// import drafts from './mock' // import drafts from './mock'
const message = useMessage() // const message = useMessage() //
const loading = ref(true) // const loading = ref(true) //
@ -362,7 +361,7 @@ const submitForm = async () => {
} finally { } finally {
dialogNewsVisible.value = false dialogNewsVisible.value = false
addMaterialLoading.value = false addMaterialLoading.value = false
getList() await getList()
} }
} }

View File

@ -277,14 +277,11 @@ const uploadRules: FormRules = {
} }
// //
type MatertialType = 'image' | 'voice' | 'video' type MaterialType = 'image' | 'voice' | 'video'
const type = ref<MatertialType>('image') const type = ref<MaterialType>('image')
// const loading = ref(false) //
const loading = ref(false) const list = ref<any[]>([]) //
// const total = ref(0) //
//
const list = ref<any[]>([])
const total = ref(0)
// //
interface QueryParams { interface QueryParams {
pageNo: number pageNo: number
@ -302,7 +299,7 @@ const queryParams: QueryParams = reactive({
const fileList = ref<UploadUserFile[]>([]) const fileList = ref<UploadUserFile[]>([])
interface UploadData { interface UploadData {
type: MatertialType type: MaterialType
title: string title: string
introduction: string introduction: string
} }
@ -346,7 +343,7 @@ const handleQuery = () => {
const onTabChange = (tabName: TabPaneName) => { const onTabChange = (tabName: TabPaneName) => {
// type // type
uploadData.type = tabName as MatertialType uploadData.type = tabName as MaterialType
// tab // tab
list.value = [] list.value = []

View File

@ -71,11 +71,10 @@
<TagForm ref="formRef" @success="getList" /> <TagForm ref="formRef" @success="getList" />
</template> </template>
<script setup lang="ts" name="MpTag"> <script setup lang="ts" name="MpTag">
import { dateFormatter } from '@/utils/formatTime'
import * as MpTagApi from '@/api/mp/tag' import * as MpTagApi from '@/api/mp/tag'
import TagForm from './TagForm.vue' import TagForm from './TagForm.vue'
import WxMpSelect from '@/views/mp/components/WxMpSelect.vue' import WxMpSelect from '@/views/mp/components/WxMpSelect.vue'
import { dateFormatter } from '@/utils/formatTime'
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
@ -93,7 +92,6 @@ const queryParams: QueryParams = reactive({
pageSize: 10, pageSize: 10,
accountId: undefined accountId: undefined
}) })
const formRef = ref<InstanceType<typeof TagForm> | null>(null) const formRef = ref<InstanceType<typeof TagForm> | null>(null)
/** 侦听公众号变化 **/ /** 侦听公众号变化 **/

View File

@ -121,15 +121,8 @@ const queryParams: QueryParams = reactive({
openid: null, openid: null,
nickname: null nickname: null
}) })
const tagList = ref<any[]>([]) //
const queryFormRef = ref<FormInstance | null>(null) // const queryFormRef = ref<FormInstance | null>(null) //
const formRef = ref<InstanceType<typeof UserForm> | null>(null) const tagList = ref<any[]>([]) //
/** 初始化 */
onMounted(async () => {
tagList.value = await MpTagApi.getSimpleTagList()
})
/** 侦听公众号变化 **/ /** 侦听公众号变化 **/
const onAccountChanged = (id?: number) => { const onAccountChanged = (id?: number) => {
@ -165,6 +158,7 @@ const resetQuery = () => {
} }
/** 添加/修改操作 */ /** 添加/修改操作 */
const formRef = ref<InstanceType<typeof UserForm> | null>(null)
const openForm = (id: number) => { const openForm = (id: number) => {
formRef.value?.open(id) formRef.value?.open(id)
} }
@ -175,7 +169,12 @@ const handleSync = async () => {
await message.confirm('是否确认同步粉丝?') await message.confirm('是否确认同步粉丝?')
await MpUserApi.syncUser(queryParams.accountId) await MpUserApi.syncUser(queryParams.accountId)
message.success('开始从微信公众号同步粉丝信息,同步需要一段时间,建议稍后再查询') message.success('开始从微信公众号同步粉丝信息,同步需要一段时间,建议稍后再查询')
getList() await getList()
} catch {} } catch {}
} }
/** 初始化 */
onMounted(async () => {
tagList.value = await MpTagApi.getSimpleTagList()
})
</script> </script>

View File

@ -1,152 +0,0 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="商户名称">{{ orderDetail.merchantName }}</el-descriptions-item>
<el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item>
<el-descriptions-item label="商品名称">{{ orderDetail.subject }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="商户订单号">
<el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="渠道订单号">
<el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="支付订单号">
<el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small">
{{ orderDetail.payOrderExtension.no }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="金额">
<el-tag type="success" size="small">{{ parseFloat(orderDetail.amount / 100, 2) }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="手续费">
<el-tag type="warning" size="small"
>{{ parseFloat(orderDetail.channelFeeAmount / 100, 2) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="手续费比例">
{{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}%
</el-descriptions-item>
<el-descriptions-item label="支付状态">
<dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" />
</el-descriptions-item>
<el-descriptions-item label="回调状态">
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="orderDetail.notifyStatus" />
</el-descriptions-item>
<el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item>
<el-descriptions-item label="创建时间" :formatter="dateFormatter">
{{ formatDate(orderDetail.createTime) }}
</el-descriptions-item>
<el-descriptions-item label="支付时间" :formatter="dateFormatter">
{{ formatDate(orderDetail.successTime) }}
</el-descriptions-item>
<el-descriptions-item label="失效时间" :formatter="dateFormatter">
{{ formatDate(orderDetail.expireTime) }}
</el-descriptions-item>
<el-descriptions-item label="通知时间" :formatter="dateFormatter">
{{ formatDate(orderDetail.notifyTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="支付渠道"
>{{ orderDetail.channelCodeName }}
</el-descriptions-item>
<el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item>
<el-descriptions-item label="退款状态">
<dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="orderDetail.refundStatus" />
</el-descriptions-item>
<el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item>
<el-descriptions-item label="退款金额">
<el-tag type="warning">
{{ parseFloat(orderDetail.refundAmount / 100, 2) }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
<el-descriptions-item label="商品描述">
{{ orderDetail.body }}
</el-descriptions-item>
<el-descriptions-item label="支付通道异步回调内容">
{{ orderDetail.payOrderExtension.channelNotifyData }}
</el-descriptions-item>
</el-descriptions>
</Dialog>
</template>
<script setup lang="ts" name="orderForm">
import { DICT_TYPE } from '@/utils/dict'
import * as OrderApi from '@/api/pay/order'
import { dateFormatter, formatDate } from '@/utils/formatTime'
const { t } = useI18n() //
// const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('订单详情') //
const formLoading = ref(false) // 12
const defaultOrderDetail = {
merchantName: '',
appName: '',
channelCodeName: '',
subject: '',
merchantOrderId: null,
channelOrderNo: '',
body: '',
amount: null,
channelFeeRate: null,
channelFeeAmount: null,
userIp: '',
status: null,
notifyUrl: '',
notifyStatus: null,
refundStatus: null,
refundTimes: '',
refundAmount: null,
createTime: '',
successTime: '',
notifyTime: '',
expireTime: '',
payOrderExtension: {
channelNotifyData: '',
no: ''
}
}
const orderDetail = ref(JSON.parse(JSON.stringify(defaultOrderDetail)))
/** 打开弹窗 */
const open = async (id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.preview')
//
if (id) {
formLoading.value = true
try {
orderDetail.value = await OrderApi.getOrderDetail(id)
if (orderDetail.value.payOrderExtension === null) {
orderDetail.value.payOrderExtension = Object.assign(
defaultOrderDetail.payOrderExtension,
{}
)
}
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
</script>
<style>
.tag-purple {
color: #722ed1;
background: #f9f0ff;
border-color: #d3adf7;
}
.tag-pink {
color: #eb2f96;
background: #fff0f6;
border-color: #ffadd2;
}
</style>

View File

@ -1,154 +0,0 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="商户名称">{{ refundDetail.merchantName }}</el-descriptions-item>
<el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item>
<el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="商户退款单号">
<el-tag size="small">{{ refundDetail.merchantRefundNo }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="商户订单号"
>{{ refundDetail.merchantOrderId }}
</el-descriptions-item>
<el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="支付金额">
{{ parseFloat(refundDetail.payAmount / 100).toFixed(2) }}
</el-descriptions-item>
<el-descriptions-item label="退款金额" size="small">
<el-tag class="tag-purple" size="small">
{{ parseFloat(refundDetail.refundAmount / 100).toFixed(2) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="退款类型">
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="refundDetail.type" />
</el-descriptions-item>
<el-descriptions-item label="退款状态">
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="refundDetail.status" />
</el-descriptions-item>
<el-descriptions-item label="创建时间"
>{{ formatDate(refundDetail.createTime) }}
</el-descriptions-item>
<el-descriptions-item label="退款成功时间"
>{{ formatDate(refundDetail.successTime) }}
</el-descriptions-item>
<el-descriptions-item label="退款失效时间"
>{{ formatDate(refundDetail.expireTime) }}
</el-descriptions-item>
<el-descriptions-item label="更新时间"
>{{ formatDate(refundDetail.updateTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="支付渠道">
{{ refundDetail.channelCodeName }}
</el-descriptions-item>
<el-descriptions-item label="支付IP" size="small">
{{ refundDetail.userIp }}
</el-descriptions-item>
<el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item>
<el-descriptions-item label="回调状态">
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="refundDetail.notifyStatus" />
</el-descriptions-item>
<el-descriptions-item label="回调时间"
>{{ formatDate(refundDetail.notifyTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="渠道订单号"
>{{ refundDetail.channelOrderNo }}
</el-descriptions-item>
<el-descriptions-item label="渠道退款单号"
>{{ refundDetail.channelRefundNo }}
</el-descriptions-item>
<el-descriptions-item label="渠道错误码"
>{{ refundDetail.channelErrorCode }}
</el-descriptions-item>
<el-descriptions-item label="渠道错误码描述"
>{{ refundDetail.channelErrorMsg }}
</el-descriptions-item>
</el-descriptions>
<br />
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
<el-descriptions-item label="渠道额外参数"
>{{ refundDetail.channelExtras }}
</el-descriptions-item>
<el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item>
</el-descriptions>
</Dialog>
</template>
<script setup lang="ts" name="refundForm">
import { DICT_TYPE } from '@/utils/dict'
import * as RefundApi from '@/api/pay/refund'
import { formatDate } from '@/utils/formatTime'
const { t } = useI18n() //
// const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('退款订单详情') //
const formLoading = ref(false) // 12
const defaultrefundDetail = {
id: null,
appId: null,
appName: '',
channelCode: '',
channelCodeName: '',
channelErrorCode: '',
channelErrorMsg: '',
channelExtras: '',
channelId: null,
channelOrderNo: '',
channelRefundNo: '',
createTime: null,
expireTime: null,
merchantId: null,
merchantName: '',
merchantOrderId: '',
merchantRefundNo: '',
notifyStatus: null,
notifyTime: null,
notifyUrl: '',
orderId: null,
payAmount: null,
reason: '',
refundAmount: null,
status: null,
subject: '',
successTime: null,
tradeNo: '',
type: null,
userIp: ''
}
const refundDetail = ref(JSON.parse(JSON.stringify(defaultrefundDetail)))
/** 打开弹窗 */
const open = async (id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.preview')
//
if (id) {
formLoading.value = true
try {
refundDetail.value = await RefundApi.getRefundApi(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
</script>
<style>
.tag-purple {
color: #722ed1;
background: #f9f0ff;
border-color: #d3adf7;
}
</style>