This commit is contained in:
xingyu4j
2025-11-07 19:06:34 +08:00
parent 31a8d38174
commit 15215b4f4c
19 changed files with 57 additions and 57 deletions

View File

@@ -7,7 +7,7 @@ import { DICT_TYPE } from '@vben/constants';
import { WxAccountSelect } from '#/views/mp/modules/wx-account-select'; import { WxAccountSelect } from '#/views/mp/modules/wx-account-select';
import { MsgType } from './modules/types'; import { MsgType } from './components/types';
/** 获取表格列配置 */ /** 获取表格列配置 */
export function useGridColumns(msgType: MsgType): VxeGridPropTypes.Columns { export function useGridColumns(msgType: MsgType): VxeGridPropTypes.Columns {

View File

@@ -18,10 +18,10 @@ import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import * as MpAutoReplyApi from '#/api/mp/autoReply'; import * as MpAutoReplyApi from '#/api/mp/autoReply';
import { $t } from '#/locales'; import { $t } from '#/locales';
import ReplyContentCell from './components/ReplyTable.vue';
import { MsgType } from './components/types';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue'; import Form from './modules/form.vue';
import ReplyContentCell from './modules/ReplyTable.vue';
import { MsgType } from './modules/types';
defineOptions({ name: 'MpAutoReply' }); defineOptions({ name: 'MpAutoReply' });

View File

@@ -7,12 +7,12 @@ import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import * as MpAutoReplyApi from '#/api/mp/autoReply'; import { createAutoReply, updateAutoReply } from '#/api/mp/autoReply';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { ReplyType } from '#/views/mp/modules/wx-reply/types'; import { ReplyType } from '#/views/mp/modules/wx-reply/types';
import ReplyForm from './ReplyForm.vue'; import ReplyForm from '../components/ReplyForm.vue';
import { MsgType } from './types'; import { MsgType } from '../components/types';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
@@ -52,10 +52,10 @@ const [Modal, modalApi] = useVbenModal({
modalApi.lock(); modalApi.lock();
try { try {
if (replyForm.value.id === undefined) { if (replyForm.value.id === undefined) {
await MpAutoReplyApi.createAutoReply(submitForm); await createAutoReply(submitForm);
message.success('新增成功'); message.success('新增成功');
} else { } else {
await MpAutoReplyApi.updateAutoReply(submitForm); await updateAutoReply(submitForm);
message.success('修改成功'); message.success('修改成功');
} }
await modalApi.close(); await modalApi.close();

View File

@@ -97,7 +97,7 @@ function onUploadError(err: Error) {
/> />
<IconifyIcon <IconifyIcon
v-else v-else
icon="ep:plus" icon="lucide:plus"
class="avatar-uploader-icon" class="avatar-uploader-icon"
:class="isFirst ? 'avatar' : 'avatar1'" :class="isFirst ? 'avatar' : 'avatar1'"
/> />

View File

@@ -11,15 +11,9 @@ const props = defineProps<{
</script> </script>
<template> <template>
<div class="draft-content"> <div class="p-2.5">
<div v-if="props.row.content && props.row.content.newsItem"> <div v-if="props.row.content && props.row.content.newsItem">
<WxNews :articles="props.row.content.newsItem" /> <WxNews :articles="props.row.content.newsItem" />
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" scoped>
.draft-content {
padding: 10px;
}
</style>

View File

@@ -109,7 +109,7 @@ function plusNews() {
size="small" size="small"
@click="() => moveDownNews(index)" @click="() => moveDownNews(index)"
> >
<IconifyIcon icon="ep:arrow-down-bold" /> <IconifyIcon icon="lucide:arrow-down" />
</Button> </Button>
<Button <Button
v-if="isCreating" v-if="isCreating"
@@ -119,7 +119,7 @@ function plusNews() {
size="small" size="small"
@click="() => removeNews(index)" @click="() => removeNews(index)"
> >
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="lucide:trash-2" />
</Button> </Button>
</div> </div>
</div> </div>
@@ -143,7 +143,7 @@ function plusNews() {
size="small" size="small"
@click="() => moveDownNews(index)" @click="() => moveDownNews(index)"
> >
<IconifyIcon icon="ep:arrow-down-bold" /> <IconifyIcon icon="lucide:arrow-down" />
</Button> </Button>
<Button <Button
v-if="index > 0" v-if="index > 0"
@@ -152,7 +152,7 @@ function plusNews() {
size="small" size="small"
@click="() => moveUpNews(index)" @click="() => moveUpNews(index)"
> >
<IconifyIcon icon="ep:arrow-up-bold" /> <IconifyIcon icon="lucide:arrow-up" />
</Button> </Button>
<Button <Button
v-if="isCreating" v-if="isCreating"
@@ -162,7 +162,7 @@ function plusNews() {
shape="circle" shape="circle"
@click="() => removeNews(index)" @click="() => removeNews(index)"
> >
<IconifyIcon icon="ep:delete" /> <IconifyIcon icon="lucide:trash-2" />
</Button> </Button>
</div> </div>
</div> </div>
@@ -174,7 +174,7 @@ function plusNews() {
@click="plusNews" @click="plusNews"
v-if="newsList.length < 8 && isCreating" v-if="newsList.length < 8 && isCreating"
> >
<IconifyIcon icon="ep:plus" /> <IconifyIcon icon="lucide:plus" />
</Button> </Button>
</Row> </Row>
</div> </div>

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Article } from './modules/types'; import type { Article } from './components/types';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
@@ -12,10 +12,10 @@ import { message } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import * as MpDraftApi from '#/api/mp/draft'; import * as MpDraftApi from '#/api/mp/draft';
import * as MpFreePublishApi from '#/api/mp/freePublish'; import * as MpFreePublishApi from '#/api/mp/freePublish';
import { createEmptyNewsItem } from '#/views/mp/draft/modules/types'; import { createEmptyNewsItem } from '#/views/mp/draft/components/types';
import DraftTableCell from './components/draft-table.vue';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
import DraftTableCell from './modules/draft-table.vue';
import Form from './modules/form.vue'; import Form from './modules/form.vue';
defineOptions({ name: 'MpDraft' }); defineOptions({ name: 'MpDraft' });

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { NewsItem } from './types'; import type { NewsItem } from '../components/types';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
@@ -7,9 +7,9 @@ import { confirm, useVbenModal } from '@vben/common-ui';
import { message, Spin } from 'ant-design-vue'; import { message, Spin } from 'ant-design-vue';
import * as MpDraftApi from '#/api/mp/draft'; import { createDraft, updateDraft } from '#/api/mp/draft';
import NewsForm from './news-form.vue'; import NewsForm from '../components/news-form.vue';
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
@@ -37,10 +37,10 @@ const [Modal, modalApi] = useVbenModal({
modalApi.lock(); modalApi.lock();
try { try {
if (formData.value.isCreating) { if (formData.value.isCreating) {
await MpDraftApi.createDraft(formData.value.accountId, newsList.value); await createDraft(formData.value.accountId, newsList.value);
message.success('新增成功'); message.success('新增成功');
} else if (formData.value.mediaId) { } else if (formData.value.mediaId) {
await MpDraftApi.updateDraft( await updateDraft(
formData.value.accountId, formData.value.accountId,
formData.value.mediaId, formData.value.mediaId,
newsList.value, newsList.value,

View File

@@ -134,7 +134,8 @@ function onChildDragEnd({ newIndex }: { newIndex: number }) {
class="menu-item" class="menu-item"
:class="{ active: props.activeIndex === `${x}` }" :class="{ active: props.activeIndex === `${x}` }"
> >
<IconifyIcon icon="ep:fold" color="black" />{{ parent.name }} <IconifyIcon icon="lucide:panel-right-open" color="black" />
{{ parent.name }}
</div> </div>
<!-- 以下为二级菜单--> <!-- 以下为二级菜单-->
<div class="submenu" v-if="props.parentIndex === x && parent.children"> <div class="submenu" v-if="props.parentIndex === x && parent.children">
@@ -164,7 +165,7 @@ function onChildDragEnd({ newIndex }: { newIndex: number }) {
v-if="!parent.children || parent.children.length < 5" v-if="!parent.children || parent.children.length < 5"
@click="addSubMenu(x, parent)" @click="addSubMenu(x, parent)"
> >
<IconifyIcon icon="ep:plus" class="plus" /> <IconifyIcon icon="lucide:plus" class="plus" />
</div> </div>
</div> </div>
</div> </div>
@@ -177,7 +178,7 @@ function onChildDragEnd({ newIndex }: { newIndex: number }) {
v-if="menuList.length < 3" v-if="menuList.length < 3"
@click="addMenu" @click="addMenu"
> >
<IconifyIcon icon="ep:plus" class="plus" /> <IconifyIcon icon="lucide:plus" class="plus" />
</div> </div>
</template> </template>

View File

@@ -8,7 +8,7 @@ import { handleTree } from '@vben/utils';
import { Button, Form, message } from 'ant-design-vue'; import { Button, Form, message } from 'ant-design-vue';
import * as MpMenuApi from '#/api/mp/menu'; import { deleteMenu, getMenuList, saveMenu } from '#/api/mp/menu';
import { MenuEditor, MenuPreviewer } from '#/views/mp/menu/components'; import { MenuEditor, MenuPreviewer } from '#/views/mp/menu/components';
import { Level, MENU_NOT_SELECTED } from '#/views/mp/menu/data'; import { Level, MENU_NOT_SELECTED } from '#/views/mp/menu/data';
import { WxAccountSelect } from '#/views/mp/modules/wx-account-select'; import { WxAccountSelect } from '#/views/mp/modules/wx-account-select';
@@ -60,7 +60,7 @@ function onAccountChanged(id: number, name: string) {
async function getList() { async function getList() {
loading.value = true; loading.value = true;
try { try {
const data = await MpMenuApi.getMenuList(accountId.value); const data = await getMenuList(accountId.value);
const menuData = menuListToFrontend(data); const menuData = menuListToFrontend(data);
menuList.value = handleTree(menuData, 'id') as Menu[]; menuList.value = handleTree(menuData, 'id') as Menu[];
} finally { } finally {
@@ -178,7 +178,7 @@ async function onSave() {
duration: 0, duration: 0,
}); });
try { try {
await MpMenuApi.saveMenu(accountId.value, menuListToBackend()); await saveMenu(accountId.value, menuListToBackend());
getList(); getList();
message.success('发布成功'); message.success('发布成功');
} finally { } finally {
@@ -198,7 +198,7 @@ async function onClear() {
duration: 0, duration: 0,
}); });
try { try {
await MpMenuApi.deleteMenu(accountId.value); await deleteMenu(accountId.value);
handleQuery(); handleQuery();
message.success('清空成功'); message.success('清空成功');
} finally { } finally {

View File

@@ -2,6 +2,8 @@
微信消息 - 定位TODO @Dhb52 目前未启用 微信消息 - 定位TODO @Dhb52 目前未启用
--> -->
<script lang="ts" setup> <script lang="ts" setup>
import { IconifyIcon } from '@vben/icons';
import { Col, Row } from 'ant-design-vue'; import { Col, Row } from 'ant-design-vue';
defineOptions({ name: 'WxLocation' }); defineOptions({ name: 'WxLocation' });
@@ -53,7 +55,7 @@ defineExpose({
/> />
</Row> </Row>
<Row> <Row>
<Icon icon="ep:location" /> <IconifyIcon icon="lucide:map-pin" />
{{ label }} {{ label }}
</Row> </Row>
</Col> </Col>

View File

@@ -6,9 +6,9 @@ import { formatTime } from '@vben/utils';
import { Button, Pagination, Row, Spin, Table } from 'ant-design-vue'; import { Button, Pagination, Row, Spin, Table } from 'ant-design-vue';
import * as MpDraftApi from '#/api/mp/draft'; import { getDraftPage } from '#/api/mp/draft';
import * as MpFreePublishApi from '#/api/mp/freePublish'; import { getFreePublishPage } from '#/api/mp/freePublish';
import * as MpMaterialApi from '#/api/mp/material'; import { getMaterialPage } from '#/api/mp/material';
import { WxNews } from '#/views/mp/modules/wx-news'; import { WxNews } from '#/views/mp/modules/wx-news';
import { WxVideoPlayer } from '#/views/mp/modules/wx-video-play'; import { WxVideoPlayer } from '#/views/mp/modules/wx-video-play';
import { WxVoicePlayer } from '#/views/mp/modules/wx-voice-play'; import { WxVoicePlayer } from '#/views/mp/modules/wx-voice-play';
@@ -69,7 +69,7 @@ async function getPage() {
/** 获取素材分页 */ /** 获取素材分页 */
async function getMaterialPageFun() { async function getMaterialPageFun() {
const data = await MpMaterialApi.getMaterialPage({ const data = await getMaterialPage({
...queryParams, ...queryParams,
type: props.type, type: props.type,
}); });
@@ -79,7 +79,7 @@ async function getMaterialPageFun() {
/** 获取已发布图文分页 */ /** 获取已发布图文分页 */
async function getFreePublishPageFun() { async function getFreePublishPageFun() {
const data = await MpFreePublishApi.getFreePublishPage(queryParams); const data = await getFreePublishPage(queryParams);
data.list.forEach((item: any) => { data.list.forEach((item: any) => {
const articles = item.content.newsItem; const articles = item.content.newsItem;
articles.forEach((article: any) => { articles.forEach((article: any) => {
@@ -92,7 +92,7 @@ async function getFreePublishPageFun() {
/** 获取草稿图文分页 */ /** 获取草稿图文分页 */
async function getDraftPageFun() { async function getDraftPageFun() {
const data = await MpDraftApi.getDraftPage(queryParams); const data = await getDraftPage(queryParams);
data.list.forEach((draft: any) => { data.list.forEach((draft: any) => {
const articles = draft.content.newsItem; const articles = draft.content.newsItem;
articles.forEach((article: any) => { articles.forEach((article: any) => {

View File

@@ -1,6 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
import { IconifyIcon } from '@vben/icons';
import { WxLocation } from '#/views/mp/modules/wx-location'; import { WxLocation } from '#/views/mp/modules/wx-location';
import { WxMusic } from '#/views/mp/modules/wx-music'; import { WxMusic } from '#/views/mp/modules/wx-music';
import { WxNews } from '#/views/mp/modules/wx-news'; import { WxNews } from '#/views/mp/modules/wx-news';
@@ -47,7 +49,7 @@ const item = ref<any>(props.item);
<div <div
class="mb-3 text-base text-[rgba(0,0,0,0.85)] hover:text-[#1890ff]" class="mb-3 text-base text-[rgba(0,0,0,0.85)] hover:text-[#1890ff]"
> >
<Icon icon="ep:link" />{{ item.title }} <IconifyIcon icon="lucide:link" />{{ item.title }}
</div> </div>
</a> </a>
<div <div

View File

@@ -1,3 +1,2 @@
export { createEmptyReply, NewsType, type Reply, ReplyType } from './types'; export * from './types';
export { default as WxReplySelect } from './wx-reply.vue'; export { default as WxReplySelect } from './wx-reply.vue';

View File

@@ -12,6 +12,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
import { IconifyIcon } from '@vben/icons';
import { Tag } from 'ant-design-vue'; import { Tag } from 'ant-design-vue';
// 因为微信语音是 amr 格式,所以需要用到 amr 解码器https://www.npmjs.com/package/benz-amr-recorder // 因为微信语音是 amr 格式,所以需要用到 amr 解码器https://www.npmjs.com/package/benz-amr-recorder
import BenzAMRRecorder from 'benz-amr-recorder'; import BenzAMRRecorder from 'benz-amr-recorder';
@@ -35,7 +37,7 @@ const playing = ref(false);
const duration = ref(); const duration = ref();
/** 处理点击,播放或暂停 */ /** 处理点击,播放或暂停 */
const playVoice = () => { function playVoice() {
// 情况一:未初始化,则创建 BenzAMRRecorder // 情况一:未初始化,则创建 BenzAMRRecorder
if (amr.value === undefined) { if (amr.value === undefined) {
amrInit(); amrInit();
@@ -47,10 +49,10 @@ const playVoice = () => {
} else { } else {
amrPlay(); amrPlay();
} }
}; }
/** 音频初始化 */ /** 音频初始化 */
const amrInit = () => { function amrInit() {
amr.value = new BenzAMRRecorder(); amr.value = new BenzAMRRecorder();
// 设置播放 // 设置播放
amr.value.initWithUrl(props.url).then(() => { amr.value.initWithUrl(props.url).then(() => {
@@ -61,26 +63,26 @@ const amrInit = () => {
amr.value.onEnded(() => { amr.value.onEnded(() => {
playing.value = false; playing.value = false;
}); });
}; }
/** 音频播放 */ /** 音频播放 */
const amrPlay = () => { function amrPlay() {
playing.value = true; playing.value = true;
amr.value.play(); amr.value.play();
}; }
/** 音频暂停 */ /** 音频暂停 */
const amrStop = () => { function amrStop() {
playing.value = false; playing.value = false;
amr.value.stop(); amr.value.stop();
}; }
// TODO 芋艿:下面样式有点问题 // TODO 芋艿:下面样式有点问题
</script> </script>
<template> <template>
<div class="wx-voice-div" @click="playVoice"> <div class="wx-voice-div" @click="playVoice">
<Icon v-if="playing !== true" icon="ep:video-play" :size="32" /> <IconifyIcon v-if="playing !== true" icon="lucide:circle-play" :size="32" />
<Icon v-else icon="ep:video-pause" :size="32" /> <IconifyIcon v-else icon="lucide:circle-pause" :size="32" />
<span class="amr-duration" v-if="duration">{{ duration }} </span> <span class="amr-duration" v-if="duration">{{ duration }} </span>
<div v-if="content"> <div v-if="content">
<Tag color="success" size="small">语音识别</Tag> <Tag color="success" size="small">语音识别</Tag>