feat:【antd】【mp】mp 的代码评审(components)
This commit is contained in:
@@ -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 WxMaterialSelect } from './wx-material-select/wx-material-select.vue';
|
||||
export { default as WxMsg } from './wx-msg/msg.vue';
|
||||
|
||||
@@ -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 暴露就好了?
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
export * from './types';
|
||||
export { default as WxLocation } from './wx-location.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// TODO @hw:ele 没这个文件,是不是也要搞个?
|
||||
export interface WxLocationProps {
|
||||
label: string;
|
||||
locationX: number;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Col, Row } from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'WxLocation' });
|
||||
|
||||
// TODO @dylan:apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue 参考这个,从后端拿 key 哈
|
||||
// TODO @dylan:@hw:apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue 参考这个,从后端拿 key 哈
|
||||
const props = withDefaults(defineProps<WxLocationProps>(), {
|
||||
qqMapKey: 'TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E', // QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
|
||||
});
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { default as WxMaterialSelect } from './wx-material-select.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -15,6 +15,7 @@ import { getFreePublishPage } from '#/api/mp/freePublish';
|
||||
import { getMaterialPage } from '#/api/mp/material';
|
||||
import { WxNews, WxVideoPlayer, WxVoicePlayer } from '#/views/mp/components';
|
||||
|
||||
/** 微信素材选择 */
|
||||
defineOptions({ name: 'WxMaterialSelect' });
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -42,7 +43,7 @@ const queryParams = reactive({
|
||||
}); // 查询参数
|
||||
|
||||
const voiceGridColumns: VxeTableGridOptions<any>['columns'] = [
|
||||
// TODO @dylan:any 有 linter 告警;看看别的模块哈
|
||||
// TODO @hw:@dylan:any 有 linter 告警;看看别的模块哈
|
||||
{
|
||||
field: 'mediaId',
|
||||
title: '编号',
|
||||
@@ -77,7 +78,7 @@ const voiceGridColumns: VxeTableGridOptions<any>['columns'] = [
|
||||
];
|
||||
|
||||
const videoGridColumns: VxeTableGridOptions<any>['columns'] = [
|
||||
// TODO @dylan:any 有 linter 告警;看看别的模块哈
|
||||
// TODO @hw:@dylan:any 有 linter 告警;看看别的模块哈
|
||||
{
|
||||
field: 'mediaId',
|
||||
title: '编号',
|
||||
@@ -381,7 +382,7 @@ watch(
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/** TODO @dylan:看看有没适合 tindwind 的哈。 */
|
||||
/** TODO @dylan:@hw:看看有没适合 tindwind 的哈。 */
|
||||
@media (width >= 992px) and (width <= 1300px) {
|
||||
.waterfall {
|
||||
column-count: 3;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from './types';
|
||||
|
||||
export { default as WxMsg } from './wx-msg.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -17,7 +17,7 @@ const props = defineProps<{
|
||||
const SendFrom = {
|
||||
MpBot: 2,
|
||||
User: 1,
|
||||
} as const;
|
||||
} as const; // 发送来源
|
||||
|
||||
function getAvatar(sendFrom: number) {
|
||||
return sendFrom === SendFrom.User
|
||||
@@ -63,7 +63,7 @@ function getNickname(sendFrom: number) {
|
||||
<style lang="scss" scoped>
|
||||
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
|
||||
|
||||
/** TODO @dylan:看看有没适合 tindwind 的哈。 */
|
||||
/** TODO @dylan:@hw 看看有没适合 tindwind 的哈。 */
|
||||
|
||||
@import url('./comment.scss');
|
||||
@import url('./card.scss');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// TODO @hw:用 MpUserApi 里的 user 可以么?
|
||||
|
||||
export interface User {
|
||||
accountId: number;
|
||||
avatar: string;
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { default as WxMusic } from './wx-music.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { WxMusicProps } from './types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
/** 微信消息 - 音乐 */
|
||||
defineOptions({ name: 'WxMusic' });
|
||||
|
||||
const props = withDefaults(defineProps<WxMusicProps>(), {
|
||||
@@ -21,8 +22,8 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 微信消息 - 音乐 -->
|
||||
<div>
|
||||
<!-- TODO @hw:是不是用 antd link 更好? -->
|
||||
<a :href="href" target="_blank" class="text-success no-underline">
|
||||
<div class="music-card">
|
||||
<div class="music-avatar">
|
||||
@@ -38,7 +39,7 @@ defineExpose({
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/** TODO @dylan:看看有没适合 tindwind 的哈。 */
|
||||
/** TODO @dylan:@hw:看看有没适合 tindwind 的哈。 */
|
||||
|
||||
.music-card {
|
||||
display: flex;
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { default as WxNews } from './wx-news.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { Image } from 'ant-design-vue';
|
||||
|
||||
/** 微信消息 - 图文 */
|
||||
defineOptions({ name: 'WxNews' });
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -18,7 +19,6 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 微信消息 - 图文 -->
|
||||
<div class="news-home">
|
||||
<div v-for="(article, index) in articles" :key="index" class="news-div">
|
||||
<!-- 头条 -->
|
||||
@@ -52,7 +52,7 @@ defineExpose({
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/** TODO @dylan:看看有没适合 tindwind 的哈。 */
|
||||
/** TODO @dylan:@hw:看看有没适合 tindwind 的哈。 */
|
||||
|
||||
.news-home {
|
||||
width: 100%;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from './types';
|
||||
|
||||
export { default as WxReply } from './wx-reply.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -26,7 +26,6 @@ const emit = defineEmits<{
|
||||
const accessStore = useAccessStore();
|
||||
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-temporary`;
|
||||
const HEADERS = { Authorization: `Bearer ${accessStore.accessToken}` };
|
||||
|
||||
const reply = computed<Reply>({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
@@ -41,6 +40,7 @@ const uploadData = reactive({
|
||||
type: 'image',
|
||||
});
|
||||
|
||||
/** 图片上传前校验 */
|
||||
function beforeImageUpload(rawFile: UploadRawFile) {
|
||||
return useBeforeUpload(UploadType.Image, 2)(rawFile);
|
||||
}
|
||||
@@ -65,6 +65,7 @@ async function customRequest(options: any) {
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// TODO @hw:if return 风格,简化掉。if (result.code !=== 0) { ... }
|
||||
if (result.code === 0) {
|
||||
// 清空上传时的各种数据
|
||||
fileList.value = [];
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
import { WxMaterialSelect } from '#/views/mp/components';
|
||||
import { UploadType, useBeforeUpload } from '#/views/mp/hooks/useUpload';
|
||||
|
||||
// TODO @hw:类似 tab-image.vue 的建议
|
||||
|
||||
defineOptions({ name: 'TabMusic' });
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -46,9 +48,10 @@ const uploadData = reactive({
|
||||
accountId: reply.value.accountId,
|
||||
introduction: '',
|
||||
title: '',
|
||||
type: 'thumb', // 音乐类型为thumb
|
||||
type: 'thumb', // 音乐类型为 thumb
|
||||
});
|
||||
|
||||
/** 图片上传前校验 */
|
||||
function beforeImageUpload(rawFile: UploadRawFile) {
|
||||
return useBeforeUpload(UploadType.Image, 2)(rawFile);
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ const reply = computed<Reply>({
|
||||
|
||||
const showDialog = ref(false);
|
||||
|
||||
/** 选择素材 */
|
||||
function selectMaterial(item: any) {
|
||||
showDialog.value = false;
|
||||
reply.value.articles = item.content.newsItem;
|
||||
}
|
||||
|
||||
/** 删除图文 */
|
||||
function onDelete() {
|
||||
reply.value.articles = [];
|
||||
}
|
||||
@@ -72,7 +74,6 @@ function onDelete() {
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
<Modal
|
||||
v-model:open="showDialog"
|
||||
title="选择图文"
|
||||
@@ -92,7 +93,7 @@ function onDelete() {
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/** TODO @dylan:看看有没适合 tindwind 的哈。 */
|
||||
/** TODO @dylan:@hw:看看有没适合 tindwind 的哈。 */
|
||||
.select-item {
|
||||
width: 280px;
|
||||
padding: 10px;
|
||||
|
||||
@@ -49,6 +49,7 @@ const uploadData = reactive({
|
||||
type: 'video',
|
||||
});
|
||||
|
||||
/** 视频上传前校验 */
|
||||
function beforeVideoUpload(rawFile: UploadRawFile) {
|
||||
return useBeforeUpload(UploadType.Video, 10)(rawFile);
|
||||
}
|
||||
@@ -73,6 +74,7 @@ async function customRequest(options: any) {
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// TODO @hw:也采用类似 ele 的 if return(res.code !== 0) return 写法;
|
||||
if (result.code === 0) {
|
||||
// 清空上传时的各种数据
|
||||
fileList.value = [];
|
||||
|
||||
@@ -41,6 +41,7 @@ const uploadData = reactive({
|
||||
type: 'voice',
|
||||
});
|
||||
|
||||
/** 语音上传前校验 */
|
||||
function beforeVoiceUpload(rawFile: UploadRawFile) {
|
||||
return useBeforeUpload(UploadType.Voice, 10)(rawFile);
|
||||
}
|
||||
@@ -65,6 +66,7 @@ async function customRequest(options: any) {
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// TODO @hw:if result.code !== 0 return,代码简洁一点。
|
||||
if (result.code === 0) {
|
||||
// 清空上传时的各种数据
|
||||
fileList.value = [];
|
||||
@@ -85,12 +87,14 @@ async function customRequest(options: any) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除语音 */
|
||||
function onDelete() {
|
||||
reply.value.mediaId = null;
|
||||
reply.value.url = null;
|
||||
reply.value.name = null;
|
||||
}
|
||||
|
||||
/** 选择素材 */
|
||||
function selectMaterial(item: Reply) {
|
||||
showDialog.value = false;
|
||||
reply.value.mediaId = item.mediaId;
|
||||
@@ -165,7 +169,7 @@ function selectMaterial(item: Reply) {
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/** TODO @dylan:看看有没适合 tindwind 的哈。 */
|
||||
/** TODO @dylan:@hw:看看有没适合 tindwind 的哈。 */
|
||||
.select-item {
|
||||
padding: 10px;
|
||||
margin: 0 auto 10px;
|
||||
|
||||
@@ -21,7 +21,7 @@ export interface Reply {
|
||||
url?: null | string;
|
||||
}
|
||||
|
||||
/** 利用旧的reply[accountId, type]初始化新的Reply */
|
||||
/** 利用旧的 reply[accountId, type] 初始化新的 Reply */
|
||||
export function createEmptyReply(old: Ref<Reply> | Reply): Reply {
|
||||
return {
|
||||
accountId: unref(old).accountId,
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
<!--
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
芋道源码:
|
||||
① 移除多余的 rep 为前缀的变量,让 message 消息更简单
|
||||
② 代码优化,补充注释,提升阅读性
|
||||
③ 优化消息的临时缓存策略,发送消息时,只清理被发送消息的 tab,不会强制切回到 text 输入
|
||||
④ 支持发送【视频】消息时,支持新建视频
|
||||
-->
|
||||
<script lang="ts" setup>
|
||||
import type { Reply } from './types';
|
||||
|
||||
@@ -25,6 +16,7 @@ import TabVideo from './tab-video.vue';
|
||||
import TabVoice from './tab-voice.vue';
|
||||
import { createEmptyReply } from './types';
|
||||
|
||||
/** 消息回复选择 */
|
||||
defineOptions({ name: 'WxReplySelect' });
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -34,16 +26,16 @@ const emit = defineEmits<{
|
||||
(e: 'update:modelValue', v: Reply): void;
|
||||
}>();
|
||||
|
||||
// TODO @hw:antd 和 ele 风格不同,需要统一;
|
||||
interface Props {
|
||||
modelValue: Reply | undefined;
|
||||
newsType?: NewsType;
|
||||
}
|
||||
|
||||
// 提供一个默认的 Reply 对象,避免 undefined 导致的错误
|
||||
const defaultReply: Reply = {
|
||||
accountId: -1,
|
||||
type: ReplyType.Text,
|
||||
};
|
||||
}; // 提供一个默认的 Reply 对象,避免 undefined 导致的错误
|
||||
|
||||
const reply = computed<Reply>({
|
||||
get: () => props.modelValue || defaultReply,
|
||||
@@ -53,6 +45,7 @@ const reply = computed<Reply>({
|
||||
const tabCache = new Map<ReplyType, Reply>(); // 作为多个标签保存各自 Reply 的缓存
|
||||
const currentTab = ref<ReplyType>(props.modelValue?.type || ReplyType.Text); // 采用独立的 ref 来保存当前 tab,避免在 watch 标签变化,对 reply 进行赋值会产生了循环调用
|
||||
|
||||
// TODO @hw:antd 和 ele 风格不同,需要统一;
|
||||
// 监听 modelValue 变化,同步更新 currentTab 和缓存
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
@@ -71,6 +64,7 @@ watch(
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
// TODO @hw:antd 和 ele 风格不同,需要统一;
|
||||
watch(
|
||||
currentTab,
|
||||
(newTab, oldTab) => {
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { default as WxVideoPlayer } from './wx-video-play.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Modal } from 'ant-design-vue';
|
||||
|
||||
import 'video.js/dist/video-js.css';
|
||||
|
||||
/** 微信消息 - 视频 */
|
||||
defineOptions({ name: 'WxVideoPlayer' });
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -22,7 +23,6 @@ function playVideo() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 微信消息 - 视频播放 -->
|
||||
<div class="cursor-pointer" @click="playVideo()">
|
||||
<!-- 提示 -->
|
||||
<div class="flex items-center">
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { default as WxVoicePlayer } from './wx-voice-play.vue';
|
||||
|
||||
// TODO @hw:每个组件下的 index.ts 要不都删除,统一在 mp/components/index.ts 暴露就好了?
|
||||
|
||||
@@ -6,6 +6,7 @@ import { IconifyIcon } from '@vben/icons';
|
||||
import { Tag } from 'ant-design-vue';
|
||||
import BenzAMRRecorder from 'benz-amr-recorder'; // 因为微信语音是 amr 格式,所以需要用到 amr 解码器:https://www.npmjs.com/package/benz-amr-recorder
|
||||
|
||||
/** 微信消息 - 语音 */
|
||||
defineOptions({ name: 'WxVoicePlayer' });
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -62,10 +63,10 @@ function amrStop() {
|
||||
playing.value = false;
|
||||
amr.value.stop();
|
||||
}
|
||||
// TODO 芋艿:下面样式有点问题
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 微信消息 - 语音播放 -->
|
||||
<div class="wx-voice-div cursor-pointer" @click="playVoice">
|
||||
<div class="flex items-center">
|
||||
<IconifyIcon
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Button } from 'ant-design-vue';
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { WxVideoPlayer } from '#/views/mp/components';
|
||||
|
||||
// TODO @dylan:vue 组件名小写 + 中划线
|
||||
// TODO @dylan:@hw:vue 组件名小写 + 中划线
|
||||
|
||||
const props = defineProps<{
|
||||
list: any[];
|
||||
|
||||
Reference in New Issue
Block a user