feat:【antd】【mp】mp 的代码评审(components)

This commit is contained in:
YunaiV
2025-11-20 21:09:02 +08:00
parent c39a445d77
commit 8d2da0a4d1
62 changed files with 631 additions and 583 deletions

View File

@@ -1,4 +1,4 @@
export { default as WxAccountSelect } from './wx-account-select/account-select.vue'; export { default as WxAccountSelect } from './wx-account-select/wx-account-select.vue';
export { default as WxLocation } from './wx-location/wx-location.vue'; export { default as WxLocation } from './wx-location/wx-location.vue';
export { default as WxMaterialSelect } from './wx-material-select/wx-material-select.vue'; export { default as WxMaterialSelect } from './wx-material-select/wx-material-select.vue';
export { default as WxMsg } from './wx-msg/msg.vue'; export { default as WxMsg } from './wx-msg/msg.vue';

View File

@@ -1 +1,3 @@
export { default as WxAccountSelect } from './account-select.vue'; export { default as WxAccountSelect } from './wx-account-select.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,2 +1,4 @@
export * from './types'; export * from './types';
export { default as WxLocation } from './wx-location.vue'; export { default as WxLocation } from './wx-location.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,3 +1,4 @@
// TODO @hwele 没这个文件,是不是也要搞个?
export interface WxLocationProps { export interface WxLocationProps {
label: string; label: string;
locationX: number; locationX: number;

View File

@@ -9,7 +9,7 @@ import { Col, Row } from 'ant-design-vue';
defineOptions({ name: 'WxLocation' }); defineOptions({ name: 'WxLocation' });
// TODO @dylanapps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue 参考这个,从后端拿 key 哈 // TODO @dylan@hwapps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue 参考这个,从后端拿 key 哈
const props = withDefaults(defineProps<WxLocationProps>(), { const props = withDefaults(defineProps<WxLocationProps>(), {
qqMapKey: 'TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E', // QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc qqMapKey: 'TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E', // QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
}); });

View File

@@ -1 +1,3 @@
export { default as WxMaterialSelect } from './wx-material-select.vue'; export { default as WxMaterialSelect } from './wx-material-select.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -15,6 +15,7 @@ import { getFreePublishPage } from '#/api/mp/freePublish';
import { getMaterialPage } from '#/api/mp/material'; import { getMaterialPage } from '#/api/mp/material';
import { WxNews, WxVideoPlayer, WxVoicePlayer } from '#/views/mp/components'; import { WxNews, WxVideoPlayer, WxVoicePlayer } from '#/views/mp/components';
/** 微信素材选择 */
defineOptions({ name: 'WxMaterialSelect' }); defineOptions({ name: 'WxMaterialSelect' });
const props = withDefaults( const props = withDefaults(
@@ -42,7 +43,7 @@ const queryParams = reactive({
}); // 查询参数 }); // 查询参数
const voiceGridColumns: VxeTableGridOptions<any>['columns'] = [ const voiceGridColumns: VxeTableGridOptions<any>['columns'] = [
// TODO @dylanany 有 linter 告警;看看别的模块哈 // TODO @hw@dylanany 有 linter 告警;看看别的模块哈
{ {
field: 'mediaId', field: 'mediaId',
title: '编号', title: '编号',
@@ -77,7 +78,7 @@ const voiceGridColumns: VxeTableGridOptions<any>['columns'] = [
]; ];
const videoGridColumns: VxeTableGridOptions<any>['columns'] = [ const videoGridColumns: VxeTableGridOptions<any>['columns'] = [
// TODO @dylanany 有 linter 告警;看看别的模块哈 // TODO @hw@dylanany 有 linter 告警;看看别的模块哈
{ {
field: 'mediaId', field: 'mediaId',
title: '编号', title: '编号',
@@ -381,7 +382,7 @@ watch(
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan看看有没适合 tindwind 的哈。 */ /** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
@media (width >= 992px) and (width <= 1300px) { @media (width >= 992px) and (width <= 1300px) {
.waterfall { .waterfall {
column-count: 3; column-count: 3;

View File

@@ -1,3 +1,5 @@
export * from './types'; export * from './types';
export { default as WxMsg } from './wx-msg.vue'; export { default as WxMsg } from './wx-msg.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -17,7 +17,7 @@ const props = defineProps<{
const SendFrom = { const SendFrom = {
MpBot: 2, MpBot: 2,
User: 1, User: 1,
} as const; } as const; // 发送来源
function getAvatar(sendFrom: number) { function getAvatar(sendFrom: number) {
return sendFrom === SendFrom.User return sendFrom === SendFrom.User
@@ -63,7 +63,7 @@ function getNickname(sendFrom: number) {
<style lang="scss" scoped> <style lang="scss" scoped>
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */ /* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
/** TODO @dylan看看有没适合 tindwind 的哈。 */ /** TODO @dylan@hw 看看有没适合 tindwind 的哈。 */
@import url('./comment.scss'); @import url('./comment.scss');
@import url('./card.scss'); @import url('./card.scss');

View File

@@ -1,3 +1,5 @@
// TODO @hw用 MpUserApi 里的 user 可以么?
export interface User { export interface User {
accountId: number; accountId: number;
avatar: string; avatar: string;

View File

@@ -1 +1,3 @@
export { default as WxMusic } from './wx-music.vue'; export { default as WxMusic } from './wx-music.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -3,6 +3,7 @@ import type { WxMusicProps } from './types';
import { computed } from 'vue'; import { computed } from 'vue';
/** 微信消息 - 音乐 */
defineOptions({ name: 'WxMusic' }); defineOptions({ name: 'WxMusic' });
const props = withDefaults(defineProps<WxMusicProps>(), { const props = withDefaults(defineProps<WxMusicProps>(), {
@@ -21,8 +22,8 @@ defineExpose({
</script> </script>
<template> <template>
<!-- 微信消息 - 音乐 -->
<div> <div>
<!-- TODO @hw是不是用 antd link 更好 -->
<a :href="href" target="_blank" class="text-success no-underline"> <a :href="href" target="_blank" class="text-success no-underline">
<div class="music-card"> <div class="music-card">
<div class="music-avatar"> <div class="music-avatar">
@@ -38,7 +39,7 @@ defineExpose({
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan看看有没适合 tindwind 的哈。 */ /** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
.music-card { .music-card {
display: flex; display: flex;

View File

@@ -1 +1,3 @@
export { default as WxNews } from './wx-news.vue'; export { default as WxNews } from './wx-news.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Image } from 'ant-design-vue'; import { Image } from 'ant-design-vue';
/** 微信消息 - 图文 */
defineOptions({ name: 'WxNews' }); defineOptions({ name: 'WxNews' });
const props = withDefaults( const props = withDefaults(
@@ -18,7 +19,6 @@ defineExpose({
</script> </script>
<template> <template>
<!-- 微信消息 - 图文 -->
<div class="news-home"> <div class="news-home">
<div v-for="(article, index) in articles" :key="index" class="news-div"> <div v-for="(article, index) in articles" :key="index" class="news-div">
<!-- 头条 --> <!-- 头条 -->
@@ -52,7 +52,7 @@ defineExpose({
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan看看有没适合 tindwind 的哈。 */ /** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
.news-home { .news-home {
width: 100%; width: 100%;

View File

@@ -1,3 +1,5 @@
export * from './types'; export * from './types';
export { default as WxReply } from './wx-reply.vue'; export { default as WxReply } from './wx-reply.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -26,7 +26,6 @@ const emit = defineEmits<{
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`; const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`;
const HEADERS = { Authorization: `Bearer ${accessStore.accessToken}` }; const HEADERS = { Authorization: `Bearer ${accessStore.accessToken}` };
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue, get: () => props.modelValue,
set: (val) => emit('update:modelValue', val), set: (val) => emit('update:modelValue', val),
@@ -41,6 +40,7 @@ const uploadData = reactive({
type: 'image', type: 'image',
}); });
/** 图片上传前校验 */
function beforeImageUpload(rawFile: UploadRawFile) { function beforeImageUpload(rawFile: UploadRawFile) {
return useBeforeUpload(UploadType.Image, 2)(rawFile); return useBeforeUpload(UploadType.Image, 2)(rawFile);
} }
@@ -65,6 +65,7 @@ async function customRequest(options: any) {
const result = await response.json(); const result = await response.json();
// TODO @hwif return 风格简化掉。if (result.code !=== 0) { ... }
if (result.code === 0) { if (result.code === 0) {
// 清空上传时的各种数据 // 清空上传时的各种数据
fileList.value = []; fileList.value = [];

View File

@@ -21,6 +21,8 @@ import {
import { WxMaterialSelect } from '#/views/mp/components'; import { WxMaterialSelect } from '#/views/mp/components';
import { UploadType, useBeforeUpload } from '#/views/mp/hooks/useUpload'; import { UploadType, useBeforeUpload } from '#/views/mp/hooks/useUpload';
// TODO @hw类似 tab-image.vue 的建议
defineOptions({ name: 'TabMusic' }); defineOptions({ name: 'TabMusic' });
const props = defineProps<{ const props = defineProps<{
@@ -46,9 +48,10 @@ const uploadData = reactive({
accountId: reply.value.accountId, accountId: reply.value.accountId,
introduction: '', introduction: '',
title: '', title: '',
type: 'thumb', // 音乐类型为thumb type: 'thumb', // 音乐类型为 thumb
}); });
/** 图片上传前校验 */
function beforeImageUpload(rawFile: UploadRawFile) { function beforeImageUpload(rawFile: UploadRawFile) {
return useBeforeUpload(UploadType.Image, 2)(rawFile); return useBeforeUpload(UploadType.Image, 2)(rawFile);
} }

View File

@@ -28,11 +28,13 @@ const reply = computed<Reply>({
const showDialog = ref(false); const showDialog = ref(false);
/** 选择素材 */
function selectMaterial(item: any) { function selectMaterial(item: any) {
showDialog.value = false; showDialog.value = false;
reply.value.articles = item.content.newsItem; reply.value.articles = item.content.newsItem;
} }
/** 删除图文 */
function onDelete() { function onDelete() {
reply.value.articles = []; reply.value.articles = [];
} }
@@ -72,7 +74,6 @@ function onDelete() {
</Col> </Col>
</Row> </Row>
</Col> </Col>
<Modal <Modal
v-model:open="showDialog" v-model:open="showDialog"
title="选择图文" title="选择图文"
@@ -92,7 +93,7 @@ function onDelete() {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan看看有没适合 tindwind 的哈。 */ /** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
.select-item { .select-item {
width: 280px; width: 280px;
padding: 10px; padding: 10px;

View File

@@ -49,6 +49,7 @@ const uploadData = reactive({
type: 'video', type: 'video',
}); });
/** 视频上传前校验 */
function beforeVideoUpload(rawFile: UploadRawFile) { function beforeVideoUpload(rawFile: UploadRawFile) {
return useBeforeUpload(UploadType.Video, 10)(rawFile); return useBeforeUpload(UploadType.Video, 10)(rawFile);
} }
@@ -73,6 +74,7 @@ async function customRequest(options: any) {
const result = await response.json(); const result = await response.json();
// TODO @hw也采用类似 ele 的 if return(res.code !== 0) return 写法;
if (result.code === 0) { if (result.code === 0) {
// 清空上传时的各种数据 // 清空上传时的各种数据
fileList.value = []; fileList.value = [];

View File

@@ -41,6 +41,7 @@ const uploadData = reactive({
type: 'voice', type: 'voice',
}); });
/** 语音上传前校验 */
function beforeVoiceUpload(rawFile: UploadRawFile) { function beforeVoiceUpload(rawFile: UploadRawFile) {
return useBeforeUpload(UploadType.Voice, 10)(rawFile); return useBeforeUpload(UploadType.Voice, 10)(rawFile);
} }
@@ -65,6 +66,7 @@ async function customRequest(options: any) {
const result = await response.json(); const result = await response.json();
// TODO @hwif result.code !== 0 return代码简洁一点。
if (result.code === 0) { if (result.code === 0) {
// 清空上传时的各种数据 // 清空上传时的各种数据
fileList.value = []; fileList.value = [];
@@ -85,12 +87,14 @@ async function customRequest(options: any) {
} }
} }
/** 删除语音 */
function onDelete() { function onDelete() {
reply.value.mediaId = null; reply.value.mediaId = null;
reply.value.url = null; reply.value.url = null;
reply.value.name = null; reply.value.name = null;
} }
/** 选择素材 */
function selectMaterial(item: Reply) { function selectMaterial(item: Reply) {
showDialog.value = false; showDialog.value = false;
reply.value.mediaId = item.mediaId; reply.value.mediaId = item.mediaId;
@@ -165,7 +169,7 @@ function selectMaterial(item: Reply) {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan看看有没适合 tindwind 的哈。 */ /** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
.select-item { .select-item {
padding: 10px; padding: 10px;
margin: 0 auto 10px; margin: 0 auto 10px;

View File

@@ -21,7 +21,7 @@ export interface Reply {
url?: null | string; url?: null | string;
} }
/** 利用旧的reply[accountId, type]初始化新的Reply */ /** 利用旧的 reply[accountId, type] 初始化新的 Reply */
export function createEmptyReply(old: Ref<Reply> | Reply): Reply { export function createEmptyReply(old: Ref<Reply> | Reply): Reply {
return { return {
accountId: unref(old).accountId, accountId: unref(old).accountId,

View File

@@ -1,12 +1,3 @@
<!--
- Copyright (C) 2018-2019
- All rights reserved, Designed By www.joolun.com
芋道源码
移除多余的 rep 为前缀的变量 message 消息更简单
代码优化补充注释提升阅读性
优化消息的临时缓存策略发送消息时只清理被发送消息的 tab不会强制切回到 text 输入
支持发送视频消息时支持新建视频
-->
<script lang="ts" setup> <script lang="ts" setup>
import type { Reply } from './types'; import type { Reply } from './types';
@@ -25,6 +16,7 @@ import TabVideo from './tab-video.vue';
import TabVoice from './tab-voice.vue'; import TabVoice from './tab-voice.vue';
import { createEmptyReply } from './types'; import { createEmptyReply } from './types';
/** 消息回复选择 */
defineOptions({ name: 'WxReplySelect' }); defineOptions({ name: 'WxReplySelect' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
@@ -34,16 +26,16 @@ const emit = defineEmits<{
(e: 'update:modelValue', v: Reply): void; (e: 'update:modelValue', v: Reply): void;
}>(); }>();
// TODO @hwantd 和 ele 风格不同,需要统一;
interface Props { interface Props {
modelValue: Reply | undefined; modelValue: Reply | undefined;
newsType?: NewsType; newsType?: NewsType;
} }
// 提供一个默认的 Reply 对象,避免 undefined 导致的错误
const defaultReply: Reply = { const defaultReply: Reply = {
accountId: -1, accountId: -1,
type: ReplyType.Text, type: ReplyType.Text,
}; }; // 提供一个默认的 Reply 对象,避免 undefined 导致的错误
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue || defaultReply, get: () => props.modelValue || defaultReply,
@@ -53,6 +45,7 @@ const reply = computed<Reply>({
const tabCache = new Map<ReplyType, Reply>(); // 作为多个标签保存各自 Reply 的缓存 const tabCache = new Map<ReplyType, Reply>(); // 作为多个标签保存各自 Reply 的缓存
const currentTab = ref<ReplyType>(props.modelValue?.type || ReplyType.Text); // 采用独立的 ref 来保存当前 tab避免在 watch 标签变化,对 reply 进行赋值会产生了循环调用 const currentTab = ref<ReplyType>(props.modelValue?.type || ReplyType.Text); // 采用独立的 ref 来保存当前 tab避免在 watch 标签变化,对 reply 进行赋值会产生了循环调用
// TODO @hwantd 和 ele 风格不同,需要统一;
// 监听 modelValue 变化,同步更新 currentTab 和缓存 // 监听 modelValue 变化,同步更新 currentTab 和缓存
watch( watch(
() => props.modelValue, () => props.modelValue,
@@ -71,6 +64,7 @@ watch(
{ immediate: true, deep: true }, { immediate: true, deep: true },
); );
// TODO @hwantd 和 ele 风格不同,需要统一;
watch( watch(
currentTab, currentTab,
(newTab, oldTab) => { (newTab, oldTab) => {

View File

@@ -1 +1,3 @@
export { default as WxVideoPlayer } from './wx-video-play.vue'; export { default as WxVideoPlayer } from './wx-video-play.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -8,6 +8,7 @@ import { Modal } from 'ant-design-vue';
import 'video.js/dist/video-js.css'; import 'video.js/dist/video-js.css';
/** 微信消息 - 视频 */
defineOptions({ name: 'WxVideoPlayer' }); defineOptions({ name: 'WxVideoPlayer' });
const props = defineProps<{ const props = defineProps<{
@@ -22,7 +23,6 @@ function playVideo() {
</script> </script>
<template> <template>
<!-- 微信消息 - 视频播放 -->
<div class="cursor-pointer" @click="playVideo()"> <div class="cursor-pointer" @click="playVideo()">
<!-- 提示 --> <!-- 提示 -->
<div class="flex items-center"> <div class="flex items-center">

View File

@@ -1 +1,3 @@
export { default as WxVoicePlayer } from './wx-voice-play.vue'; export { default as WxVoicePlayer } from './wx-voice-play.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -6,6 +6,7 @@ import { IconifyIcon } from '@vben/icons';
import { Tag } from 'ant-design-vue'; import { Tag } from 'ant-design-vue';
import BenzAMRRecorder from 'benz-amr-recorder'; // 因为微信语音是 amr 格式,所以需要用到 amr 解码器https://www.npmjs.com/package/benz-amr-recorder import BenzAMRRecorder from 'benz-amr-recorder'; // 因为微信语音是 amr 格式,所以需要用到 amr 解码器https://www.npmjs.com/package/benz-amr-recorder
/** 微信消息 - 语音 */
defineOptions({ name: 'WxVoicePlayer' }); defineOptions({ name: 'WxVoicePlayer' });
const props = withDefaults( const props = withDefaults(
@@ -62,10 +63,10 @@ function amrStop() {
playing.value = false; playing.value = false;
amr.value.stop(); amr.value.stop();
} }
// TODO 芋艿:下面样式有点问题
</script> </script>
<template> <template>
<!-- 微信消息 - 语音播放 -->
<div class="wx-voice-div cursor-pointer" @click="playVoice"> <div class="wx-voice-div cursor-pointer" @click="playVoice">
<div class="flex items-center"> <div class="flex items-center">
<IconifyIcon <IconifyIcon

View File

@@ -12,7 +12,7 @@ import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { WxVideoPlayer } from '#/views/mp/components'; import { WxVideoPlayer } from '#/views/mp/components';
// TODO @dylanvue 组件名小写 + 中划线 // TODO @dylan@hwvue 组件名小写 + 中划线
const props = defineProps<{ const props = defineProps<{
list: any[]; list: any[];

View File

@@ -1,5 +1,6 @@
// 消息类型Follow: 关注时回复Message: 消息回复Keyword: 关键词回复) // 消息类型Follow: 关注时回复Message: 消息回复Keyword: 关键词回复)
// 作为 tab.nameenum 的数字不能随意修改,与 api 参数相关 // 作为 tab.nameenum 的数字不能随意修改,与 api 参数相关
// TODO @hwele 相比 antd 多了,看看要不要统一下;
export enum MsgType { export enum MsgType {
Follow = 1, Follow = 1,
Keyword = 3, Keyword = 3,

View File

@@ -1,5 +1,3 @@
// 统一导出所有模块组件
export { default as WxAccountSelect } from './wx-account-select/wx-account-select.vue'; export { default as WxAccountSelect } from './wx-account-select/wx-account-select.vue';
export { default as WxLocation } from './wx-location/wx-location.vue'; export { default as WxLocation } from './wx-location/wx-location.vue';
@@ -20,3 +18,5 @@ export { default as WxReplySelect } from './wx-reply/wx-reply.vue';
export { default as WxVideoPlayer } from './wx-video-play/wx-video-play.vue'; export { default as WxVideoPlayer } from './wx-video-play/wx-video-play.vue';
export { default as WxVoicePlayer } from './wx-voice-play/wx-voice-play.vue'; export { default as WxVoicePlayer } from './wx-voice-play/wx-voice-play.vue';
// TODO @hw是不是要和 antd 保持一致哈?

View File

@@ -1 +1,3 @@
export { default } from './wx-account-select.vue'; export { default } from './wx-account-select.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -10,6 +10,7 @@ import { ElMessage, ElOption, ElSelect } from 'element-plus';
import { getSimpleAccountList } from '#/api/mp/account'; import { getSimpleAccountList } from '#/api/mp/account';
// TODO @hw调整下代码和 antd 代码风格,尽量保持一致;
defineOptions({ name: 'AccountSelect' }); defineOptions({ name: 'AccountSelect' });
const props = defineProps<{ const props = defineProps<{

View File

@@ -1 +1,3 @@
export { default } from './wx-location.vue'; export { default as WxLocation } from './wx-location.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,13 +1,15 @@
<!-- <!--
微信消息 - 定位TODO @Dhb52 目前未启用 微信消息 - 定位TODO @Dhb52 目前未启用@hw看看目前是不是没用起来哈
--> -->
<script lang="ts" setup> <script lang="ts" setup>
import { IconifyIcon } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
// TODO @dylan@hwapps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue 参考这个,从后端拿 key 哈
import { ElCol, ElLink, ElRow } from 'element-plus'; import { ElCol, ElLink, ElRow } from 'element-plus';
defineOptions({ name: 'Location' }); defineOptions({ name: 'Location' });
// TODO @hwantd 和 ele 这里的风格,看看怎么统一!
const props = defineProps({ const props = defineProps({
locationX: { locationX: {
required: true, required: true,
@@ -39,6 +41,7 @@ defineExpose({
</script> </script>
<template> <template>
<!-- 微信消息 - 定位 -->
<div> <div>
<ElLink <ElLink
type="primary" type="primary"

View File

@@ -1,3 +1,5 @@
export { MaterialType, NewsType } from './types'; export { MaterialType, NewsType } from './types';
export { default } from './wx-material-select.vue'; export { default } from './wx-material-select.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,3 +1,4 @@
// TODO @hw这里的枚举看看要不要统一
export enum NewsType { export enum NewsType {
Draft = '2', Draft = '2',
Published = '1', Published = '1',

View File

@@ -1,8 +1,3 @@
<!--
- Copyright (C) 2018-2019
- All rights reserved, Designed By www.joolun.com
芋道源码
-->
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
@@ -26,6 +21,9 @@ import VoicePlayer from '#/views/mp/components/wx-voice-play/wx-voice-play.vue';
import { NewsType } from './types'; import { NewsType } from './types';
// TODO @hw代码风格看看 antd 和 ele 是不是统一下;
/** 微信素材选择 */
defineOptions({ name: 'MaterialSelect' }); defineOptions({ name: 'MaterialSelect' });
const props = withDefaults( const props = withDefaults(
@@ -41,18 +39,14 @@ const props = withDefaults(
const emit = defineEmits(['selectMaterial']); const emit = defineEmits(['selectMaterial']);
// 遮罩层 const loading = ref(false); // 遮罩层
const loading = ref(false); const total = ref(0); // 总条数
// 总条数 const list = ref<any[]>([]); // 数据列表
const total = ref(0);
// 数据列表
const list = ref<any[]>([]);
// 查询参数
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
accountId: props.accountId, accountId: props.accountId,
}); }); // 查询参数
/** 选择素材 */ /** 选择素材 */
function selectMaterialFun(item: any) { function selectMaterialFun(item: any) {
@@ -288,6 +282,8 @@ onMounted(async () => {
} }
} }
/** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
.waterfall { .waterfall {
column-gap: 10px; column-gap: 10px;
width: 100%; width: 100%;

View File

@@ -1,3 +1,5 @@
export { MsgType } from './types'; export { MsgType } from './types';
export { default } from './wx-msg.vue'; export { default } from './wx-msg.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -7,6 +7,7 @@ const props = defineProps<{
item: any; item: any;
}>(); }>();
// TODO @hw看看用 antd 的风格,还是 ele 的风格,就是下面的 item。
const item = ref(props.item); const item = ref(props.item);
</script> </script>

View File

@@ -8,6 +8,7 @@ import avatarWechat from '#/assets/imgs/wechat.png';
import Msg from './wx-msg.vue'; import Msg from './wx-msg.vue';
// 确保 User 类型被识别为已使用 // 确保 User 类型被识别为已使用
// TODO @hw是不是不用 PropsUser 哈?
type PropsUser = User; type PropsUser = User;
defineOptions({ name: 'MsgList' }); defineOptions({ name: 'MsgList' });
@@ -18,15 +19,16 @@ const props = defineProps<{
user: PropsUser; user: PropsUser;
}>(); }>();
// 使用常量对象替代枚举,避免 linter 误报
const SendFrom = { const SendFrom = {
MpBot: 2, MpBot: 2,
User: 1, User: 1,
} as const; } as const; // 发送来源
// TODO @hw是不是用 SendFrom ,或者 number
type SendFromType = (typeof SendFrom)[keyof typeof SendFrom]; type SendFromType = (typeof SendFrom)[keyof typeof SendFrom];
// 显式引用枚举成员供模板使用 // 显式引用枚举成员供模板使用
// TODO @hw是不是用 SendFrom 就好啦?
const MpBotValue = SendFrom.MpBot; const MpBotValue = SendFrom.MpBot;
const UserValue = SendFrom.User; const UserValue = SendFrom.User;
@@ -72,6 +74,8 @@ const getNickname = (sendFrom: SendFromType) =>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */ /* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
/** TODO @dylan@hw 看看有没适合 tindwind 的哈。 */
@import url('../comment.scss'); @import url('../comment.scss');
@import url('../card.scss'); @import url('../card.scss');
</style> </style>

View File

@@ -1,3 +1,4 @@
// TODO @hw是不是放枚举里
export enum MsgType { export enum MsgType {
Event = 'event', Event = 'event',
Image = 'image', Image = 'image',
@@ -10,6 +11,7 @@ export enum MsgType {
Voice = 'voice', Voice = 'voice',
} }
// TODO @hw用 MpUserApi 里的 user 可以么?
export interface User { export interface User {
nickname: string; nickname: string;
avatar: string; avatar: string;

View File

@@ -12,6 +12,8 @@ import MsgEvent from './msg-event.vue';
defineOptions({ name: 'Msg' }); defineOptions({ name: 'Msg' });
// TODO @hw这个貌似和 antd 的差很多?
const props = defineProps<{ const props = defineProps<{
item: any; item: any;
}>(); }>();
@@ -86,5 +88,3 @@ const item = ref<any>(props.item);
</div> </div>
</div> </div>
</template> </template>
<style scoped></style>

View File

@@ -1 +1,3 @@
export { default } from './wx-music.vue'; export { default } from './wx-music.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,7 +1,5 @@
<!--
微信消息 - 音乐
-->
<script lang="ts" setup> <script lang="ts" setup>
/** 微信消息 - 音乐 */
defineOptions({ name: 'Music' }); defineOptions({ name: 'Music' });
const props = defineProps({ const props = defineProps({
@@ -38,6 +36,7 @@ defineExpose({
<template> <template>
<div> <div>
<!-- TODO @hwElLink -->
<el-link <el-link
type="success" type="success"
:underline="false" :underline="false"
@@ -62,6 +61,8 @@ defineExpose({
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 card.scss */ /* 因为 joolun 实现依赖 avue 组件,该页面使用了 card.scss */
@import url('../wx-msg/card.scss'); @import url('../wx-msg/card.scss');
</style> </style>

View File

@@ -1 +1,3 @@
export { default } from './wx-news.vue'; export { default as WxNews } from './wx-news.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -8,6 +8,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ElImage } from 'element-plus'; import { ElImage } from 'element-plus';
/** 微信消息 - 图文 */
defineOptions({ name: 'WxNews' }); defineOptions({ name: 'WxNews' });
const props = withDefaults( const props = withDefaults(
@@ -61,6 +62,8 @@ defineExpose({
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan@hw看看有没适合 tindwind 的哈。 */
.news-home { .news-home {
width: 100%; width: 100%;
margin: auto; margin: auto;

View File

@@ -1,3 +1,5 @@
export { createEmptyReply, type Reply, ReplyType } from './types'; export { createEmptyReply, type Reply, ReplyType } from './types';
export { default } from './wx-reply.vue'; export { default } from './wx-reply.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -28,9 +28,11 @@ const emit = defineEmits<{
(e: 'update:modelValue', v: Reply): void; (e: 'update:modelValue', v: Reply): void;
}>(); }>();
// TODO @hw直接用 ElMessage
const message = ElMessage; const message = ElMessage;
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`; const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`;
// TODO @hw看看要不要和 antd 保持一致的风格;
const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` }; const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` };
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue, get: () => props.modelValue,
@@ -41,9 +43,9 @@ const showDialog = ref(false);
const fileList = ref([]); const fileList = ref([]);
const uploadData = reactive({ const uploadData = reactive({
accountId: reply.value.accountId, accountId: reply.value.accountId,
type: 'image',
title: '',
introduction: '', introduction: '',
title: '',
type: 'image',
}); });
/** 图片上传前校验 */ /** 图片上传前校验 */
@@ -157,5 +159,3 @@ function selectMaterial(item: any) {
</ElRow> </ElRow>
</div> </div>
</template> </template>
<style lang="scss" scoped></style>

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { UploadRawFile } from 'element-plus'; import type { UploadRawFile } from 'element-plus';
// TODO @hw类似 tab-image.vue 的建议
import type { Reply } from './types'; import type { Reply } from './types';
import { computed, reactive, ref } from 'vue'; import { computed, reactive, ref } from 'vue';
@@ -19,11 +20,8 @@ import {
} from 'element-plus'; } from 'element-plus';
import { UploadType, useBeforeUpload } from '#/utils/useUpload'; import { UploadType, useBeforeUpload } from '#/utils/useUpload';
// import { getAccessToken } from '@/utils/auth'
import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue'; import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue';
// 设置上传的请求头部
const props = defineProps<{ const props = defineProps<{
modelValue: Reply; modelValue: Reply;
}>(); }>();
@@ -45,9 +43,9 @@ const showDialog = ref(false);
const fileList = ref([]); const fileList = ref([]);
const uploadData = reactive({ const uploadData = reactive({
accountId: reply.value.accountId, accountId: reply.value.accountId,
type: 'thumb', // 音乐类型为thumb
title: '',
introduction: '', introduction: '',
title: '',
type: 'thumb', // 音乐类型为 thumb
}); });
/** 图片上传前校验 */ /** 图片上传前校验 */

View File

@@ -12,13 +12,17 @@ import News from '#/views/mp/components/wx-news/wx-news.vue';
import { NewsType } from '../wx-material-select/types'; import { NewsType } from '../wx-material-select/types';
defineOptions({ name: 'TabNews' });
const props = defineProps<{ const props = defineProps<{
modelValue: Reply; modelValue: Reply;
newsType: NewsType; newsType: NewsType;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:modelValue', v: Reply): void; (e: 'update:modelValue', v: Reply): void;
}>(); }>();
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue, get: () => props.modelValue,
set: (val) => emit('update:modelValue', val), set: (val) => emit('update:modelValue', val),
@@ -84,5 +88,3 @@ function onDelete() {
</ElRow> </ElRow>
</div> </div>
</template> </template>
<style lang="scss" scoped></style>

View File

@@ -22,6 +22,8 @@ import { UploadType, useBeforeUpload } from '#/utils/useUpload';
import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue'; import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue';
import VideoPlayer from '#/views/mp/components/wx-video-play/wx-video-play.vue'; import VideoPlayer from '#/views/mp/components/wx-video-play/wx-video-play.vue';
defineOptions({ name: 'TabVideo' });
const props = defineProps<{ const props = defineProps<{
modelValue: Reply; modelValue: Reply;
}>(); }>();
@@ -30,13 +32,16 @@ const emit = defineEmits<{
(e: 'update:modelValue', v: Reply): void; (e: 'update:modelValue', v: Reply): void;
}>(); }>();
// TODO @hw还是用 ElMessage
const message = ElMessage; const message = ElMessage;
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`; const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`;
// TODO @hw这里 antd 和 ele 有差异,要统一么?
const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` }; const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` };
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue, get: () => props.modelValue,
// TODO @hw这里 antd 和 ele 有差异,要统一么?
set: (val: Reply) => emit('update:modelValue', val), set: (val: Reply) => emit('update:modelValue', val),
}); });
@@ -44,9 +49,9 @@ const showDialog = ref(false);
const fileList = ref([]); const fileList = ref([]);
const uploadData = reactive({ const uploadData = reactive({
accountId: reply.value.accountId, accountId: reply.value.accountId,
type: 'video',
title: '',
introduction: '', introduction: '',
title: '',
type: 'video',
}); });
/** 视频上传前校验 */ /** 视频上传前校验 */
@@ -142,5 +147,3 @@ function selectMaterial(item: any) {
</ElRow> </ElRow>
</div> </div>
</template> </template>
<style lang="scss" scoped></style>

View File

@@ -21,7 +21,7 @@ import { UploadType, useBeforeUpload } from '#/utils/useUpload';
import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue'; import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue';
import VoicePlayer from '#/views/mp/components/wx-voice-play/wx-voice-play.vue'; import VoicePlayer from '#/views/mp/components/wx-voice-play/wx-voice-play.vue';
// 设置上传的请求头部 defineOptions({ name: 'TabVoice' });
const props = defineProps<{ const props = defineProps<{
modelValue: Reply; modelValue: Reply;
@@ -31,12 +31,15 @@ const emit = defineEmits<{
(e: 'update:modelValue', v: Reply): void; (e: 'update:modelValue', v: Reply): void;
}>(); }>();
// TODO @hw用 ElMessage
const message = ElMessage; const message = ElMessage;
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`; const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`;
// TODO @hwantd 和 ele 写法的统一;
const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` }; const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` };
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue, get: () => props.modelValue,
// TODO @hw这里要和 antd 统一么?还是 ele 和它统一
set: (val: Reply) => emit('update:modelValue', val), set: (val: Reply) => emit('update:modelValue', val),
}); });
@@ -44,9 +47,9 @@ const showDialog = ref(false);
const fileList = ref([]); const fileList = ref([]);
const uploadData = reactive({ const uploadData = reactive({
accountId: reply.value.accountId, accountId: reply.value.accountId,
type: 'voice',
title: '',
introduction: '', introduction: '',
title: '',
type: 'voice',
}); });
/** 语音上传前校验 */ /** 语音上传前校验 */
@@ -156,5 +159,3 @@ function selectMaterial(item: Reply) {
</ElRow> </ElRow>
</div> </div>
</template> </template>
<style lang="scss" scoped></style>

View File

@@ -2,6 +2,7 @@ import type { Ref } from 'vue';
import { unref } from 'vue'; import { unref } from 'vue';
// TODO @hw和 antd 风格,保持一致;
enum ReplyType { enum ReplyType {
Image = 'image', Image = 'image',
Music = 'music', Music = 'music',
@@ -30,7 +31,7 @@ interface _Reply {
type Reply = _Reply; // Partial<_Reply> type Reply = _Reply; // Partial<_Reply>
/** 利用旧的reply[accountId, type]初始化新的Reply */ /** 利用旧的 reply[accountId, type] 初始化新的 Reply */
const createEmptyReply = (old: Ref<Reply> | Reply): Reply => { const createEmptyReply = (old: Ref<Reply> | Reply): Reply => {
return { return {
accountId: unref(old).accountId, accountId: unref(old).accountId,

View File

@@ -1,12 +1,3 @@
<!--
- Copyright (C) 2018-2019
- All rights reserved, Designed By www.joolun.com
芋道源码
移除多余的 rep 为前缀的变量 message 消息更简单
代码优化补充注释提升阅读性
优化消息的临时缓存策略发送消息时只清理被发送消息的 tab不会强制切回到 text 输入
支持发送视频消息时支持新建视频
-->
<script lang="ts" setup> <script lang="ts" setup>
import type { Reply } from './types'; import type { Reply } from './types';
@@ -25,7 +16,8 @@ import TabVideo from './tab-video.vue';
import TabVoice from './tab-voice.vue'; import TabVoice from './tab-voice.vue';
import { createEmptyReply, ReplyType } from './types'; import { createEmptyReply, ReplyType } from './types';
defineOptions({ name: 'ReplySelect' }); /** 消息回复选择 */
defineOptions({ name: 'WxReplySelect' });
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@@ -36,14 +28,15 @@ const props = withDefaults(
newsType: () => NewsType.Published, newsType: () => NewsType.Published,
}, },
); );
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:modelValue', v: Reply): void; (e: 'update:modelValue', v: Reply): void;
}>(); }>();
// 提供一个默认的 Reply 对象,避免 undefined 导致的错误
const defaultReply: Reply = { const defaultReply: Reply = {
accountId: -1, accountId: -1,
type: ReplyType.Text, type: ReplyType.Text,
}; }; // 提供一个默认的 Reply 对象,避免 undefined 导致的错误
const reply = computed<Reply>({ const reply = computed<Reply>({
get: () => props.modelValue || defaultReply, get: () => props.modelValue || defaultReply,
@@ -113,5 +106,3 @@ defineExpose({
</ElTabPane> </ElTabPane>
</ElTabs> </ElTabs>
</template> </template>
<style lang="scss" scoped></style>

View File

@@ -1 +1,3 @@
export { default } from './wx-video-play.vue'; export { default } from './wx-video-play.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,15 +1,3 @@
<!--
- Copyright (C) 2018-2019
- All rights reserved, Designed By www.joolun.com
微信消息 - 视频
芋道源码
bug 修复
1joolun 的做法使用 mediaId 从微信公众号下载对应的 mp4 素材从而播放内容
存在的问题mediaId 有效期是 3 超过时间后无法播放
2重构后的做法后端接收到微信公众号的视频消息后将视频消息的 media_id 的文件内容保存到文件服务器中这样前端可以直接使用 URL 播放
体验优化弹窗关闭后自动暂停视频的播放
-->
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
@@ -20,8 +8,10 @@ import { ElDialog } from 'element-plus';
import 'video.js/dist/video-js.css'; import 'video.js/dist/video-js.css';
defineOptions({ name: 'VideoPlayer' }); /** 微信消息 - 视频 */
defineOptions({ name: 'WxVideoPlayer' });
// TODO @hwantd 或者 eleprops 保持一致;
const props = defineProps({ const props = defineProps({
url: { url: {
type: String, type: String,
@@ -31,10 +21,6 @@ const props = defineProps({
const dialogVideo = ref(false); const dialogVideo = ref(false);
// const handleEvent = (log) => {
// console.log('Basic player event', log)
// }
const playVideo = () => { const playVideo = () => {
dialogVideo.value = true; dialogVideo.value = true;
}; };
@@ -61,6 +47,7 @@ const playVideo = () => {
:width="800" :width="800"
:playback-rates="[0.7, 1.0, 1.5, 2.0]" :playback-rates="[0.7, 1.0, 1.5, 2.0]"
/> />
<!-- TODO @hw删除掉 -->
<!-- 事件暫時沒用 <!-- 事件暫時沒用
@mounted="handleMounted"--> @mounted="handleMounted"-->
<!-- @ready="handleEvent($event)"--> <!-- @ready="handleEvent($event)"-->

View File

@@ -1 +1,3 @@
export { default } from './wx-voice-play.vue'; export { default } from './wx-voice-play.vue';
// TODO @hw每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?

View File

@@ -1,14 +1,3 @@
<!--
- Copyright (C) 2018-2019
- All rights reserved, Designed By www.joolun.com
微信消息 - 语音
芋道源码
bug 修复
1joolun 的做法使用 mediaId 从微信公众号下载对应的 mp4 素材从而播放内容
存在的问题mediaId 有效期是 3 超过时间后无法播放
2重构后的做法后端接收到微信公众号的视频消息后将视频消息的 media_id 的文件内容保存到文件服务器中这样前端可以直接使用 URL 播放
代码优化 props 中的 reply 调成为 data 中对应的属性并补充相关注释
-->
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref } from 'vue';
@@ -17,8 +6,10 @@ import { IconifyIcon } from '@vben/icons';
// 因为微信语音是 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';
/** 微信消息 - 语音 */
defineOptions({ name: 'VoicePlayer' }); defineOptions({ name: 'VoicePlayer' });
// TODO @hwantd 和 ele 代码风格一致;
const props = defineProps({ const props = defineProps({
url: { url: {
type: String, // 语音地址例如说https://www.iocoder.cn/xxx.amr type: String, // 语音地址例如说https://www.iocoder.cn/xxx.amr
@@ -92,6 +83,7 @@ const amrStop = () => {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/** TODO @dylan看看有没适合 tindwind 的哈。 */
.wx-voice-div { .wx-voice-div {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -1,3 +1,4 @@
// TODO @hw合并到 api 里,参考 antd 的做法;
interface NewsItem { interface NewsItem {
title: string; title: string;
thumbMediaId: string; thumbMediaId: string;

View File

@@ -20,6 +20,7 @@ import MenuEditor from '#/views/mp/menu/modules/menu-editor.vue';
import MenuPreviewer from '#/views/mp/menu/modules/menu-previewer.vue'; import MenuPreviewer from '#/views/mp/menu/modules/menu-previewer.vue';
// Assets for backgrounds // Assets for backgrounds
// TODO @hw是不是资源的地址统一下antd 和 ele目录不同。建议按照 ele 的方法先;
import iphoneBackImg from './assets/iphone_backImg.png'; import iphoneBackImg from './assets/iphone_backImg.png';
import menuFootImg from './assets/menu_foot.png'; import menuFootImg from './assets/menu_foot.png';
import menuHeadImg from './assets/menu_head.png'; import menuHeadImg from './assets/menu_head.png';

View File

@@ -1,3 +1,4 @@
// TODO @hw合并到 types
export default [ export default [
{ {
value: 'view', value: 'view',

930
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff