@@ -1,7 +1,7 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-29 11:14:13 | * @Date: 2021-11-29 11:14:13 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-09-08 14:24:09 | |||||
* @LastEditTime: 2023-01-05 14:55:26 | |||||
* @FilePath: \TelpoUserManageAdmin\README.md | * @FilePath: \TelpoUserManageAdmin\README.md | ||||
* @description: | * @description: | ||||
--> | --> | ||||
@@ -66,3 +66,66 @@ fix | |||||
`2022.8.8` | `2022.8.8` | ||||
feat | feat | ||||
- 增加 收单系统,众筹拼单系统,消息管理和系统管理路由配置 | - 增加 收单系统,众筹拼单系统,消息管理和系统管理路由配置 | ||||
## v1.0.1 | |||||
`2022.9.8` | |||||
feat | |||||
- 增加 流量统计功能 | |||||
## v1.0.2 | |||||
`2022.9.9` | |||||
feat | |||||
- 增加 群发列表功能 | |||||
## v1.0.3 | |||||
`2022.9.14` | |||||
feat | |||||
- 添加文章 | |||||
- 富文本编辑器更换为 wangeditor/editor-for-vue | |||||
## v1.0.4 | |||||
`2022.9.17` | |||||
feat | |||||
- 添加文章 | |||||
- 增加 富文本一些基本配置 | |||||
- 添加群发 | |||||
- 增加 接口对接 | |||||
- 群发列表 | |||||
- 增加 接口对接 | |||||
## v1.0.5 | |||||
`2022.9.19` | |||||
fix | |||||
- 添加群发 | |||||
- 群发列表 | |||||
- 修改 接口数据结构 | |||||
## v1.0.6 | |||||
`2022.9.20` | |||||
fix | |||||
- 添加群发 | |||||
- 群发列表 | |||||
- 修复 分页异常的问题 | |||||
- 修复 预览异常的问题 | |||||
## v1.0.7 | |||||
`2022.9.21` | |||||
feat | |||||
- 添加群发 | |||||
- 增加 动态创建消息模板 | |||||
- 群发列表 | |||||
- 修复 分页异常的问题 | |||||
## v1.0.8 | |||||
`2023.1.5` | |||||
feat | |||||
- 添加群发 | |||||
- 取消 模板列表为空时显示默认模板id | |||||
- 增加 正式环境的接口地址配置 |
@@ -16,6 +16,8 @@ | |||||
"test:ci": "npm run lint && npm run test:unit" | "test:ci": "npm run lint && npm run test:unit" | ||||
}, | }, | ||||
"dependencies": { | "dependencies": { | ||||
"@wangeditor/editor": "^5.1.15", | |||||
"@wangeditor/editor-for-vue": "^1.0.1", | |||||
"axios": "0.18.1", | "axios": "0.18.1", | ||||
"core-js": "3.6.5", | "core-js": "3.6.5", | ||||
"element-ui": "2.13.2", | "element-ui": "2.13.2", | ||||
@@ -23,7 +25,7 @@ | |||||
"normalize.css": "7.0.0", | "normalize.css": "7.0.0", | ||||
"nprogress": "0.2.0", | "nprogress": "0.2.0", | ||||
"path-to-regexp": "2.4.0", | "path-to-regexp": "2.4.0", | ||||
"vue": "2.6.10", | |||||
"vue": "2.6.14", | |||||
"vue-router": "3.0.6", | "vue-router": "3.0.6", | ||||
"vuex": "3.1.0", | "vuex": "3.1.0", | ||||
"xlsx": "0.14.1" | "xlsx": "0.14.1" | ||||
@@ -52,7 +54,7 @@ | |||||
"serve-static": "1.13.2", | "serve-static": "1.13.2", | ||||
"svg-sprite-loader": "4.1.3", | "svg-sprite-loader": "4.1.3", | ||||
"svgo": "1.2.2", | "svgo": "1.2.2", | ||||
"vue-template-compiler": "2.6.10" | |||||
"vue-template-compiler": "2.6.14" | |||||
}, | }, | ||||
"browserslist": [ | "browserslist": [ | ||||
"> 1%", | "> 1%", | ||||
@@ -0,0 +1,81 @@ | |||||
/* | |||||
* @Date: 2022-09-15 16:40:39 | |||||
* @LastEditors: JinxChen | |||||
* @LastEditTime: 2022-09-20 11:25:01 | |||||
* @FilePath: \TelpoUserManageAdmin\src\api\wechat-fans.js | |||||
* @description: | |||||
*/ | |||||
import requestWxFans from '@/utils/request-wx-fans'; | |||||
export const APIWechatFans = { | |||||
SelfGroups, //获取自定义分组 | |||||
getGroupSender, //获取群发列表 | |||||
addGroupSender, //添加模板消息群发 | |||||
getArticlesGroup, //获取文章列表 | |||||
getGroupSenderDetails, //获取单个群发记录 | |||||
deleteGroupSender, //删除单个群发记录 | |||||
getTemplateMsgList, //获取模板消息列表 | |||||
getTemplateById, //根据模板id获取对应的模板消息 | |||||
}; | |||||
export default APIWechatFans; | |||||
function SelfGroups(data) { | |||||
return requestWxFans({ | |||||
url: '/SelfGroups', | |||||
method: 'get', | |||||
params: data, | |||||
}); | |||||
} | |||||
function getGroupSender(data) { | |||||
return requestWxFans({ | |||||
url: '/GroupSender', | |||||
method: 'get', | |||||
params: data, | |||||
}); | |||||
} | |||||
function getArticlesGroup(data) { | |||||
return requestWxFans({ | |||||
url: '/Articles', | |||||
method: 'get', | |||||
params: data, | |||||
}); | |||||
} | |||||
function addGroupSender(params) { | |||||
return requestWxFans({ | |||||
url: '/GroupSender', | |||||
method: 'post', | |||||
data: params, | |||||
}); | |||||
} | |||||
function getGroupSenderDetails(subject_id, data) { | |||||
return requestWxFans({ | |||||
url: `/GroupSender/${subject_id}/details`, | |||||
method: 'get', | |||||
params: data, | |||||
}); | |||||
} | |||||
function deleteGroupSender(id) { | |||||
return requestWxFans({ | |||||
url: `/GroupSender/${id}`, | |||||
method: 'delete', | |||||
}); | |||||
} | |||||
function getTemplateMsgList(){ | |||||
return requestWxFans({ | |||||
url: `/GroupSender/TemplateMsgTemplates`, | |||||
method: 'get', | |||||
}); | |||||
} | |||||
function getTemplateById(id){ | |||||
return requestWxFans({ | |||||
url: `/GroupSender/TemplateMsgTemplates/${id}`, | |||||
method: 'get', | |||||
}); | |||||
} |
@@ -1,14 +1,14 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-30 17:19:51 | * @Date: 2021-11-30 17:19:51 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-08-16 16:13:27 | |||||
* @LastEditTime: 2022-09-21 14:31:06 | |||||
* @FilePath: \TelpoUserManageAdmin\src\components\TTable\TTable.vue | * @FilePath: \TelpoUserManageAdmin\src\components\TTable\TTable.vue | ||||
* @description: 封装通用的table组件 | * @description: 封装通用的table组件 | ||||
--> | --> | ||||
<template> | <template> | ||||
<div class="app-container"> | <div class="app-container"> | ||||
<!-- 表格 --> | <!-- 表格 --> | ||||
<el-table :data="tableData" border fit highlight-current-row @sort-change="sortChange" :height="400" > | |||||
<el-table :data="tableData" border fit highlight-current-row @sort-change="sortChange" :empty-text="emptyText" :height="400" > | |||||
<template v-for="column in columns"> | <template v-for="column in columns"> | ||||
<!-- 标题 --> | <!-- 标题 --> | ||||
<el-table-column | <el-table-column | ||||
@@ -16,9 +16,16 @@ | |||||
:prop="column.prop" | :prop="column.prop" | ||||
:label="column.title" | :label="column.title" | ||||
:fixed="column.fixed" | :fixed="column.fixed" | ||||
v-if="!column.action" | |||||
v-if="!column.action && !column.isCustom" | |||||
height="400" | height="400" | ||||
/> | /> | ||||
<el-table-column :label="column.title" :show-overflow-tooltip="true" :key="column.prop" v-else-if="column.isCustom" fixed="right" min-width="100"> | |||||
<template slot-scope="scope"> | |||||
<div> | |||||
<p @click="handleClick(scope.row, column.fnName)" class="details-underline">{{scope.row.template_content}}</p> | |||||
</div> | |||||
</template> | |||||
</el-table-column> | |||||
<!-- 操作列 --> | <!-- 操作列 --> | ||||
<el-table-column :label="column.title" :key="column.prop" v-else fixed="right" min-width="100"> | <el-table-column :label="column.title" :key="column.prop" v-else fixed="right" min-width="100"> | ||||
<template slot-scope="scope"> | <template slot-scope="scope"> | ||||
@@ -61,6 +68,9 @@ export default { | |||||
type: Array, | type: Array, | ||||
default: () => [] | default: () => [] | ||||
}, | }, | ||||
emptyText: { | |||||
type: String, | |||||
}, | |||||
btnType: { | btnType: { | ||||
type: String | type: String | ||||
} | } | ||||
@@ -94,4 +104,10 @@ export default { | |||||
.el-table { | .el-table { | ||||
font-size: 14px; | font-size: 14px; | ||||
} | } | ||||
.details-underline { | |||||
text-decoration: underline; | |||||
&:hover { | |||||
cursor: pointer; | |||||
} | |||||
} | |||||
</style> | </style> |
@@ -31,7 +31,7 @@ export default { | |||||
}, | }, | ||||
data() { | data() { | ||||
return { | return { | ||||
title: '用户运营管理系统', | |||||
title: '用户运营管理平台', | |||||
logo: require('@/assets/telpo.png') | logo: require('@/assets/telpo.png') | ||||
} | } | ||||
} | } | ||||
@@ -1,8 +1,8 @@ | |||||
/* | /* | ||||
* @Date: 2021-11-30 15:35:16 | * @Date: 2021-11-30 15:35:16 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-08-06 10:25:02 | |||||
* @FilePath: \telpoAdminTemplate\src\main.js | |||||
* @LastEditTime: 2022-09-17 15:12:15 | |||||
* @FilePath: \TelpoUserManageAdmin\src\main.js | |||||
* @description: | * @description: | ||||
*/ | */ | ||||
import Vue from 'vue' | import Vue from 'vue' | ||||
@@ -10,7 +10,7 @@ import Vue from 'vue' | |||||
import 'normalize.css/normalize.css' // A modern alternative to CSS resets | import 'normalize.css/normalize.css' // A modern alternative to CSS resets | ||||
import ElementUI from 'element-ui' | import ElementUI from 'element-ui' | ||||
import 'element-ui/lib/theme-chalk/index.css' | |||||
import 'element-ui/lib/theme-chalk/index.css'; | |||||
/* import locale from 'element-ui/lib/locale/lang/en' */ // lang i18n | /* import locale from 'element-ui/lib/locale/lang/en' */ // lang i18n | ||||
import '@/styles/index.scss' // global css | import '@/styles/index.scss' // global css | ||||
@@ -72,6 +72,7 @@ export const constantRoutes = [{ | |||||
component: Layout, | component: Layout, | ||||
redirect: '/collection-order-list', | redirect: '/collection-order-list', | ||||
name: 'collection-order-system', | name: 'collection-order-system', | ||||
hidden: true, | |||||
meta: { | meta: { | ||||
title: '收单系统', | title: '收单系统', | ||||
icon: 'el-icon-s-help' | icon: 'el-icon-s-help' | ||||
@@ -89,6 +90,29 @@ export const constantRoutes = [{ | |||||
] | ] | ||||
}, | }, | ||||
// 流量统计 todo | |||||
{ | |||||
path: '/traffic-statistics', | |||||
component: Layout, | |||||
redirect: '/ssjl-statistics', | |||||
name: 'traffic-statistics', | |||||
hidden: false, | |||||
meta: { | |||||
title: '流量统计', | |||||
icon: 'el-icon-data-line' | |||||
}, | |||||
children: [ | |||||
{ | |||||
path: '/ssjl-statistics', | |||||
name: 'ssjl-statistics', | |||||
component: () => import('@/views/traffic-statistics/main/ssjl-statistics/index'), | |||||
meta: { | |||||
title: '家长端流量统计', //收单列表 | |||||
icon: 'el-icon-office-building' | |||||
} | |||||
}, | |||||
] | |||||
}, | |||||
// 众筹拼单系统 | // 众筹拼单系统 | ||||
{ | { | ||||
path: 'crowd-funding-otrder-system', | path: 'crowd-funding-otrder-system', | ||||
@@ -168,7 +192,7 @@ export const constantRoutes = [{ | |||||
redirect: '/wechat-fans', | redirect: '/wechat-fans', | ||||
name: 'message-manage', | name: 'message-manage', | ||||
meta: { | meta: { | ||||
title: '消息管理', | |||||
title: '消息发送系统', | |||||
icon: 'el-icon-message-solid' | icon: 'el-icon-message-solid' | ||||
}, | }, | ||||
children: [ | children: [ | ||||
@@ -179,7 +203,8 @@ export const constantRoutes = [{ | |||||
meta: { | meta: { | ||||
title: '公众号粉丝', | title: '公众号粉丝', | ||||
icon: 'el-icon-user-solid' | icon: 'el-icon-user-solid' | ||||
} | |||||
}, | |||||
hidden: true | |||||
}, | }, | ||||
{ | { | ||||
@@ -189,7 +214,8 @@ export const constantRoutes = [{ | |||||
meta: { | meta: { | ||||
title: '添加文章', | title: '添加文章', | ||||
icon: 'el-icon-edit' | icon: 'el-icon-edit' | ||||
} | |||||
}, | |||||
hidden: true | |||||
}, | }, | ||||
{ | { | ||||
@@ -211,6 +237,16 @@ export const constantRoutes = [{ | |||||
icon: 'el-icon-document' | icon: 'el-icon-document' | ||||
} | } | ||||
}, | }, | ||||
{ | |||||
path: '/send-details', | |||||
name: 'send-details', | |||||
component: () => import('@/views/message-manage/main/send-details/index'), | |||||
meta: { | |||||
title: '发送明细', | |||||
icon: 'el-icon-document' | |||||
}, | |||||
hidden: true | |||||
}, | |||||
{ | { | ||||
path: '/unsubscribe-list', | path: '/unsubscribe-list', | ||||
@@ -219,7 +255,8 @@ export const constantRoutes = [{ | |||||
meta: { | meta: { | ||||
title: '退订列表', | title: '退订列表', | ||||
icon: 'el-icon-notebook-2' | icon: 'el-icon-notebook-2' | ||||
} | |||||
}, | |||||
hidden: true | |||||
}, | }, | ||||
] | ] | ||||
@@ -7,7 +7,7 @@ | |||||
*/ | */ | ||||
module.exports = { | module.exports = { | ||||
title: '用户运营管理系统', | |||||
title: '用户运营管理平台', | |||||
/** | /** | ||||
* @type {boolean} true | false | * @type {boolean} true | false | ||||
@@ -64,14 +64,15 @@ div:focus { | |||||
// main-container global css | // main-container global css | ||||
.home-container { | .home-container { | ||||
height: 600px; | height: 600px; | ||||
width: 100%; | |||||
position: relative; | position: relative; | ||||
margin: 60px 20px 0 20px; | margin: 60px 20px 0 20px; | ||||
padding: 10px 0; | |||||
padding: 10px 10px; | |||||
border: 1px solid #d8dce5; | border: 1px solid #d8dce5; | ||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04); | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04); | ||||
.top-container { | .top-container { | ||||
display: inline-block; | display: inline-block; | ||||
padding: 0 20px 0 20px; | |||||
padding: 0 20px 0 0; | |||||
span { | span { | ||||
font-size: 14px; | font-size: 14px; | ||||
} | } | ||||
@@ -7,7 +7,7 @@ | |||||
*/ | */ | ||||
import defaultSettings from '@/settings' | import defaultSettings from '@/settings' | ||||
const title = defaultSettings.title || '用户运营管理系统' | |||||
const title = defaultSettings.title || '用户运营管理平台' | |||||
export default function getPageTitle(pageTitle) { | export default function getPageTitle(pageTitle) { | ||||
if (pageTitle) { | if (pageTitle) { | ||||
@@ -1,8 +1,8 @@ | |||||
/* | /* | ||||
* @Date: 2021-11-30 15:09:25 | * @Date: 2021-11-30 15:09:25 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-08-08 11:10:59 | |||||
* @LastEditTime: 2022-12-12 11:35:33 | |||||
* @FilePath: \TelpoUserManageAdmin\src\utils\model.js | * @FilePath: \TelpoUserManageAdmin\src\utils\model.js | ||||
* @description: 版本号 | * @description: 版本号 | ||||
*/ | */ | ||||
export const VersionModel = '1.0.0'; | |||||
export const VersionModel = '1.0.8'; |
@@ -0,0 +1,84 @@ | |||||
/* | |||||
* @Date: 2021-12-08 15:59:46 | |||||
* @LastEditors: JinxChen | |||||
* @LastEditTime: 2023-01-05 14:53:02 | |||||
* @FilePath: \TelpoUserManageAdmin\src\utils\request-wx-fans.js | |||||
* @description: | |||||
*/ | |||||
import axios from 'axios' | |||||
import { | |||||
Message | |||||
} from 'element-ui' | |||||
import store from '@/store' | |||||
/* import { getToken } from '@/utils/auth' */ | |||||
// create an axios instance | |||||
// 区分正式和测试环境,注意 :http://localhost:9528/ 是你本地项目的启动地址 | |||||
const currentUrl = window.location.href.split('#'); // 当前url,因项目部署方式不同,用当前url区分正式环境和测试环境 | |||||
const testUrlList = [ | |||||
'http://ping.ssjlai.com', | |||||
'http://localhost:9528' | |||||
]; | |||||
const proUrl = 'http://47.116.67.214:8766/api'; //正式环境接口地址 | |||||
const isTest = testUrlList.some(item => { return currentUrl[0].indexOf(item) > -1; }); | |||||
const service = axios.create({ | |||||
baseURL: process.env === 'test' || process.env === 'development' ? 'http://ping.ssjlai.com:8008/api/' : isTest ? 'http://ping.ssjlai.com:8008/api/': proUrl, | |||||
}); | |||||
// request interceptor | |||||
service.interceptors.request.use( | |||||
config => { | |||||
// do something before request is sent | |||||
/* if (store.getters.token) { | |||||
config.headers['AuthToken'] = store.getters.token; | |||||
} */ | |||||
return config; | |||||
}, | |||||
error => { | |||||
// do something with request error | |||||
console.log(error) // for debug | |||||
return Promise.reject(error) | |||||
} | |||||
) | |||||
// response interceptor | |||||
service.interceptors.response.use( | |||||
response => { | |||||
const res = response.data; | |||||
return res; | |||||
// todo 拦截暂时去掉 | |||||
/* if (res.code === 106) { | |||||
setTimeout(() => { | |||||
store.dispatch('user/resetToken').then(() => { | |||||
Message({ | |||||
message: '登录过期,请您重新登录!', | |||||
type: 'error', | |||||
duration: 1500 | |||||
}) | |||||
location.reload() | |||||
}) | |||||
}, 1000) | |||||
} else if (res.code === 200000) { | |||||
return res | |||||
} else { | |||||
Message({ | |||||
message: res.message || '出错了,请联系管理员!', | |||||
type: 'error', | |||||
duration: 3 * 1000 | |||||
}) | |||||
return Promise.reject(new Error(res.message)) | |||||
} | |||||
}, | |||||
error => { | |||||
console.log('err:', error) | |||||
Message({ | |||||
message: error.message, | |||||
type: 'error', | |||||
duration: 3 * 1000 | |||||
}) | |||||
return Promise.reject(error) | |||||
} */} | |||||
); | |||||
export default service; |
@@ -7,7 +7,7 @@ | |||||
--> | --> | ||||
<template> | <template> | ||||
<div class="dashboard-container"> | <div class="dashboard-container"> | ||||
<div class="dashboard-text">欢迎来到用户运营管理系统</div> | |||||
<div class="dashboard-text">欢迎来到用户运营管理平台</div> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
@@ -1,7 +1,7 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2022-08-08 10:09:45 | * @Date: 2022-08-08 10:09:45 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-08-09 16:44:50 | |||||
* @LastEditTime: 2022-09-16 16:39:27 | |||||
* @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\add-articles\index.vue | * @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\add-articles\index.vue | ||||
* @description: 添加文章 | * @description: 添加文章 | ||||
--> | --> | ||||
@@ -55,8 +55,29 @@ | |||||
<!-- 富文本编辑器 --> | <!-- 富文本编辑器 --> | ||||
<el-form-item label="文章内容:"> | <el-form-item label="文章内容:"> | ||||
<tinymce v-model="form.articleContent" :height="5" menubar="false" /> | |||||
<!-- <tinymce v-model="form.articleContent" :height="5" menubar="false" /> --> | |||||
<!-- <p>文章内容:{{form.articleContent}}</p> --> | <!-- <p>文章内容:{{form.articleContent}}</p> --> | ||||
<div style="border: 1px solid #ccc;"> | |||||
<Toolbar | |||||
style="border-bottom: 1px solid #ccc" | |||||
:editor="editor" | |||||
:defaultConfig="toolbarConfig" | |||||
:mode="mode" | |||||
/> | |||||
<Editor | |||||
style="height: 350px; overflow-y: hidden;" | |||||
v-model="form.articleContent" | |||||
:defaultConfig="editorConfig" | |||||
:mode="mode" | |||||
@onCreated="onCreated" | |||||
@onChange="onChange" | |||||
@onDestroyed="onDestroyed" | |||||
@onMaxLength="onMaxLength" | |||||
@onFocus="onFocus" | |||||
@onBlur="onBlur" | |||||
@customPaste="customPaste" | |||||
/> | |||||
</div> | |||||
</el-form-item> | </el-form-item> | ||||
<!-- 保存 --> | <!-- 保存 --> | ||||
@@ -70,10 +91,11 @@ | |||||
<script> | <script> | ||||
import TopMenu from "@/components/TopMenu/index"; | import TopMenu from "@/components/TopMenu/index"; | ||||
import Tinymce from '@/components/Tinymce' | |||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'; | |||||
/* import Tinymce from '@/components/Tinymce' */ | |||||
export default { | export default { | ||||
name: 'wechat-fans', | name: 'wechat-fans', | ||||
components: { TopMenu, Tinymce }, | |||||
components: { TopMenu, /* Tinymce */ Editor, Toolbar }, | |||||
data(){ | data(){ | ||||
return { | return { | ||||
buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | ||||
@@ -95,6 +117,18 @@ export default { | |||||
], | ], | ||||
// 图片列表 | // 图片列表 | ||||
fileList: [], | fileList: [], | ||||
editor: null, | |||||
toolbarConfig: { }, | |||||
mode: 'default', // or 'simple' | |||||
// 菜单配置 | |||||
editorConfig: { | |||||
MENU_CONF: { | |||||
uploadImage: { | |||||
server: '', //上传图片地址 todo 待后端提供 | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
}, | }, | ||||
@@ -103,7 +137,36 @@ export default { | |||||
this.clearFiles(); | this.clearFiles(); | ||||
console.log("本地的上传图片列表", this.fileList); | console.log("本地的上传图片列表", this.fileList); | ||||
}, | }, | ||||
beforeDestroy() { | |||||
const editor = this.editor | |||||
if (editor == null) return | |||||
editor.destroy() // 组件销毁时,及时销毁编辑器 | |||||
}, | |||||
methods: { | methods: { | ||||
onCreated(editor) { | |||||
this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错 | |||||
}, | |||||
onChange(editor) { console.log('onChange', editor.children) }, | |||||
onDestroyed(editor) { console.log('onDestroyed', editor) }, | |||||
onMaxLength(editor) { console.log('onMaxLength', editor) }, | |||||
onFocus(editor) { console.log('onFocus', editor) }, | |||||
onBlur(editor) { console.log('onBlur', editor) }, | |||||
customPaste(editor, event, callback) { | |||||
console.log('ClipboardEvent 粘贴事件对象', event) | |||||
// const html = event.clipboardData.getData('text/html') // 获取粘贴的 html | |||||
// const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本 | |||||
// const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴) | |||||
// 自定义插入内容 | |||||
editor.insertText('') | |||||
// 返回 false ,阻止默认粘贴行为 | |||||
event.preventDefault() | |||||
callback(false) // 返回值(注意,vue 事件的返回值,不能用 return) | |||||
// 返回 true ,继续默认的粘贴行为 | |||||
// callback(true) | |||||
}, | |||||
// 清空本地上传的图片列表 | // 清空本地上传的图片列表 | ||||
clearFiles() {}, | clearFiles() {}, | ||||
// 删除上传的图片 | // 删除上传的图片 | ||||
@@ -151,6 +214,7 @@ export default { | |||||
} | } | ||||
</script> | </script> | ||||
<style src="@wangeditor/editor/dist/css/style.css"></style> | |||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
.home-container { | .home-container { | ||||
position: relative; | position: relative; | ||||
@@ -1,7 +1,7 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2022-08-08 10:09:47 | * @Date: 2022-08-08 10:09:47 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-08-10 09:43:22 | |||||
* @LastEditTime: 2023-01-05 14:49:38 | |||||
* @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\add-mass\index.vue | * @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\add-mass\index.vue | ||||
* @description: 添加群发 | * @description: 添加群发 | ||||
--> | --> | ||||
@@ -10,54 +10,56 @@ | |||||
<div class="home-container"> | <div class="home-container"> | ||||
<div class="form-container"> | <div class="form-container"> | ||||
<!-- 表单 --> | <!-- 表单 --> | ||||
<el-form ref="form" :model="form" label-width="80px"> | |||||
<el-form-item label="消息主题:" size="small"> | |||||
<el-input v-model="form.msgTheme" class="input-width-400" clearable ></el-input> | |||||
<el-form ref="form" :model="form" label-width="100px" :rules="rules"> | |||||
<el-form-item label="消息主题:" size="small" prop="subject"> | |||||
<el-input v-model="form.subject" class="input-width-400" clearable ></el-input> | |||||
</el-form-item> | </el-form-item> | ||||
<el-form-item label="内容模板:" size="small"> | |||||
<p>{{firstData}}</p> | |||||
<el-input v-model="form.contentTitle" class="input-width-600" clearable ></el-input> | |||||
<p>学习账号{{keyword1Data}}</p> | |||||
<el-input v-model="form.studyAccount" class="input-width-400" clearable ></el-input> | |||||
<p>更新内容{{keyword2Data}}</p> | |||||
<el-input v-model="form.updateCon" class="input-width-600" clearable ></el-input> | |||||
<p>{{remarkData}}</p> | |||||
<el-input v-model="form.contentDetails" class="input-width-600" clearable ></el-input> | |||||
</el-form-item> | |||||
<el-form-item label="内容链接:" size="small" class="inline-form-item"> | |||||
<el-input v-model="form.contentUrl" placeholder="请选择文章或者输入外部URL" class="input-width-400"></el-input> | |||||
<el-select v-model="article" placeholder="选择文章" clearable filterable @change="onSelectArt"> | |||||
<el-option :label="item.label" :value="item.label" v-for="(item, index) in articleList" :key="index"/> | |||||
<el-form-item label="选择模板:" size="small" prop="tempId"> | |||||
<!-- 动态生成模板 --> | |||||
<el-select v-model="form.tempId" placeholder="选择模板" clearable filterable @change="onSelectTemp"> | |||||
<el-option :label="item.label" :value="item.value" v-for="(item, index) in templateMsgList" :key="index"/> | |||||
</el-select> | </el-select> | ||||
</el-form-item> | </el-form-item> | ||||
<el-form-item label="群发对象:" size="small"> | |||||
<el-select v-model="form.group" placeholder="选择分组" clearable filterable @change="onSelectMass"> | |||||
<el-option :label="item.label" :value="item.label" v-for="(item, index) in groupList" :key="index"/> | |||||
<el-form-item label="模板内容:" size="small" required> | |||||
<el-form-item v-for="(item, index) in templateMsgCon" :key="index"> | |||||
<el-form-item> | |||||
<p>{{item.name}}</p> | |||||
<el-input v-model="templateInput[item.key]" class="input-width-600" clearable type="textarea" autosize></el-input> | |||||
</el-form-item> | |||||
</el-form-item> | |||||
</el-form-item> | |||||
<el-form-item label="内容链接:" size="small" class="inline-form-item" required> | |||||
<el-form-item prop="articleContent" > | |||||
<el-input v-model="form.articleContent" placeholder="请输入正确的外部URL" class="input-width-400" clearable @clear="onClearUrl"></el-input> | |||||
<!-- <el-select v-model="article" placeholder="选择文章" clearable filterable @change="onSelectArt" @clear="onClearSelect"> | |||||
<el-option :label="item.label" :value="item.value" v-for="(item, index) in articleList" :key="index"/> | |||||
</el-select> --> | |||||
</el-form-item> | |||||
</el-form-item> | |||||
<el-form-item label="群发对象:" size="small" prop="selfGroupId"> | |||||
<el-select v-model="form.selfGroupId" placeholder="选择分组" clearable filterable @change="onSelectMass"> | |||||
<el-option :label="item.label" :value="item.value" v-for="(item, index) in groupList" :key="index"/> | |||||
</el-select> | </el-select> | ||||
<el-button type="primary" @click="onCheckList">查看名单</el-button> | |||||
<el-button type="primary" @click="onCheckList" disabled>查看名单</el-button> | |||||
</el-form-item> | </el-form-item> | ||||
<div class="footer-container"> | |||||
<el-button type="primary" v-for="(item, index) in footBtnList" :key="index" @click="item.click">{{item.name}}</el-button> | |||||
</div> | |||||
</el-form> | </el-form> | ||||
</div> | </div> | ||||
<!-- 底部操作按钮 --> | <!-- 底部操作按钮 --> | ||||
<div class="footer-container"> | |||||
<el-button type="primary" v-for="(item, index) in footBtnList" :key="index" @click="item.click">{{item.name}}</el-button> | |||||
</div> | |||||
<!-- 预览dialog --> | <!-- 预览dialog --> | ||||
<el-dialog title="预览信息" :visible.sync="previewShow"> | <el-dialog title="预览信息" :visible.sync="previewShow"> | ||||
<div class="preview-container"> | <div class="preview-container"> | ||||
<div class="top"> | <div class="top"> | ||||
<p>{{form.contentTitle}}</p> | |||||
<p>学习账号:{{form.studyAccount}}</p> | |||||
<p>更新内容:{{form.updateCon}}</p> | |||||
<p>更新时间:{{updateTime}}</p> | |||||
<p>{{form.contentDetails}}</p> | |||||
<p>{{templateInput.first}}</p> | |||||
<p v-for="(item, index) in previewData" :key="index"> | |||||
{{item.name}}:{{item.value}} | |||||
</p> | |||||
<p>{{templateInput.remark}}</p> | |||||
</div> | </div> | ||||
<div class="fot"> | |||||
<div class="fot" @click="onOpenUrl"> | |||||
<p>详情</p> | <p>详情</p> | ||||
<p>></p> | <p>></p> | ||||
</div> | </div> | ||||
@@ -70,42 +72,47 @@ | |||||
</template> | </template> | ||||
<script> | <script> | ||||
//import TopMenu from "@/components/TopMenu/index"; | |||||
import { initTime } from '@/utils/index.js'; | import { initTime } from '@/utils/index.js'; | ||||
/* import './index.scss' */ | |||||
import { APIWechatFans } from '@/api/wechat-fans.js'; | |||||
export default { | export default { | ||||
name: 'add-mass', | name: 'add-mass', | ||||
components: { }, | components: { }, | ||||
data(){ | data(){ | ||||
const checkUrl = (rule, value, callback) => { | |||||
let urlrReg = /^((https?|ftp):\/\/)?([\da-z.-]+)\.([a-z.]{2,6})(\/\w\.-]*)*\/?/; | |||||
if(urlrReg.test(value)) { | |||||
callback(); | |||||
} else if (this.form.articleId !== '') { | |||||
callback(); | |||||
} else { | |||||
callback(`请输入正确的网址`); | |||||
} | |||||
}; | |||||
return { | return { | ||||
buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | ||||
firstData: '{{first.DATA}}:', | firstData: '{{first.DATA}}:', | ||||
keyword1Data: '{{keyword1DATA}}:', | keyword1Data: '{{keyword1DATA}}:', | ||||
keyword2Data: '{{keyword2DATA}}:', | keyword2Data: '{{keyword2DATA}}:', | ||||
keyword3Data: '{{keyword3DATA}}:', | |||||
remarkData: '{{remarkDATA}}:', | remarkData: '{{remarkDATA}}:', | ||||
form: { | form: { | ||||
msgTheme: '' || '财商学习通知', | |||||
contentTitle: '' || '家长您好,您孩子所需的财商学习内容有更新', //内容模板标题 | |||||
studyAccount: '' || 'csds', //学习账号 | |||||
updateCon: '' || '财商36问', //更新内容 | |||||
contentDetails: '' || '请点击内容查看详情', //内容详情 | |||||
contentUrl: '', //内容连接 | |||||
group: '', //分组 | |||||
subject: '' /* || '财商学习通知' */, //发送主题 | |||||
templateId: 1, //模板id | |||||
articleContent: '', //文章内容 | |||||
articleId: '', //文章id | |||||
selfGroupId: '', //分组id | |||||
first: '' /* || '家长您好,您孩子所需的财商学习内容有更新' */, //内容模板标题 | |||||
keyword1: '' /* || 'csds' */, //学习账号 | |||||
keyword2: '' /* || '财商36问' */, //更新内容 | |||||
keyword3: '', | |||||
remark: '' /* || '请点击内容查看详情' */, //内容详情 | |||||
tempId: '' /* || '-kOhlwJPhO7v3WW3rAdmNs76lR7ZpQEJtbVSY8Y35Eg' */, //模板id | |||||
}, | }, | ||||
article: '', //选择文章 | article: '', //选择文章 | ||||
articleList: [ | |||||
{ label: '文章1', value: '文章1' }, | |||||
{ label: '文章2', value: '文章2' }, | |||||
{ label: '文章3', value: '文章3' }, | |||||
{ label: '文章4', value: '文章4' }, | |||||
], | |||||
// 文章列表 | |||||
articleList: [], | |||||
// 用户分组 | // 用户分组 | ||||
groupList: [ | |||||
{ label: '分组1', value: '分组2' }, | |||||
{ label: '分组2', value: '分组2' }, | |||||
{ label: '分组3', value: '分组3' }, | |||||
{ label: '分组4', value: '分组4' }, | |||||
], | |||||
groupList: [], | |||||
// 底部操作按钮 | // 底部操作按钮 | ||||
footBtnList: [ | footBtnList: [ | ||||
{ name: '立即发送', click: () => { this.onSend()}}, | { name: '立即发送', click: () => { this.onSend()}}, | ||||
@@ -115,27 +122,264 @@ export default { | |||||
], | ], | ||||
// 预览dialog | // 预览dialog | ||||
previewShow: false, | previewShow: false, | ||||
// 要预览的页面字段 | |||||
previewData: [], | |||||
// form验证 | |||||
rules: { | |||||
subject: [ | |||||
{ required: true, message: '请输入消息主题', trigger: 'blur' }, | |||||
], | |||||
tempId: [ | |||||
{ required: true, message: '请选择模板消息', trigger: 'blur' }, | |||||
], | |||||
/* first: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], | |||||
keyword1: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], | |||||
keyword2: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], | |||||
keyword3: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], | |||||
keyword4: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], | |||||
keyword5: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], | |||||
remark: [ | |||||
{ required: true, message: '请填写消息模板内容', trigger: 'blur' }, | |||||
], */ | |||||
articleContent: [ | |||||
{ required: true, validator: checkUrl, message: '请输入正确的外部URL', trigger: 'blur' }, | |||||
], | |||||
selfGroupId: [ | |||||
{ required: true, message: '请选择群发分组', trigger: 'blur' }, | |||||
], | |||||
}, | |||||
// 模板消息列表 | |||||
templateMsgList: [], | |||||
// 模板内容 | |||||
templateMsgCon: [ | |||||
{ | |||||
key: 'first', | |||||
name: '{{first.DATA}}', | |||||
}, | |||||
{ | |||||
key: 'keyword1', | |||||
name: '消息类别:{{keyword1.DATA}}', | |||||
}, | |||||
{ | |||||
key: 'keyword2', | |||||
name: '通知用户:{{keyword2.DATA}}', | |||||
}, | |||||
{ | |||||
key: 'keyword3', | |||||
name: '通知内容:{{keyword3.DATA}}', | |||||
}, | |||||
{ | |||||
key: 'remark', | |||||
name: '{{remark.DATA}}' | |||||
} | |||||
], | |||||
// 动态生成的input | |||||
templateInput: {}, | |||||
tempData: [] || [ | |||||
{first: 'first', remark: 'remark'} | |||||
] | |||||
} | } | ||||
}, | }, | ||||
computed: { | computed: { | ||||
// 初始弹窗更新时间 | // 初始弹窗更新时间 | ||||
updateTime() { | |||||
return initTime(new Date(), 'ymdh'); //更新时间 | |||||
} | |||||
initUpdateTime() { | |||||
return initTime(new Date(), 'ymdhm'); //更新时间 | |||||
}, | |||||
}, | |||||
activated() { | |||||
this.getSelfGroups(); | |||||
this.getArticlesGroup(); | |||||
this.getTemplateMsgList(); | |||||
}, | |||||
mounted() { | |||||
}, | |||||
created() { | |||||
this.getSelfGroups(); | |||||
this.getTemplateMsgList(); | |||||
this.getArticlesGroup(); | |||||
}, | }, | ||||
mounted() {}, | |||||
created() {}, | |||||
methods: { | methods: { | ||||
// 获取自定义分组 | |||||
getSelfGroups() { | |||||
let reqBody = { | |||||
page_index: 1, | |||||
page_size: 10 | |||||
} | |||||
APIWechatFans.SelfGroups(reqBody) | |||||
.then(res => { | |||||
let data = res.data; | |||||
this.groupList = data.rows.map(item => { | |||||
return { | |||||
label: item.name, | |||||
value: item.id | |||||
} | |||||
}) | |||||
console.log("data", data); | |||||
}) | |||||
}, | |||||
// 获取文章列表 | |||||
getArticlesGroup() { | |||||
let reqBody = { | |||||
page_index: 1, | |||||
page_size: 100000 | |||||
} | |||||
APIWechatFans.getArticlesGroup(reqBody) | |||||
.then(res => { | |||||
let data = res.data; | |||||
console.log("文章data", data); | |||||
this.articleList = data.rows.map(item => { | |||||
return { | |||||
label: item.title, | |||||
value: item.id | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
// 查看白名单 | // 查看白名单 | ||||
onCheckList() {}, | onCheckList() {}, | ||||
// objectToArray | |||||
objectToArray(obj) { | |||||
let arr = []; | |||||
for(let i in obj) { | |||||
// arr.push (obj[i] ) //返回属性值 | |||||
arr.push(obj[i]) //返回键名 | |||||
}; | |||||
return arr; | |||||
}, | |||||
// 立即发送 | // 立即发送 | ||||
onSend() {}, | |||||
onSend() { | |||||
this.tempData.push(this.templateInput); | |||||
console.log("tempData", JSON.stringify(this.templateInput)); | |||||
// 拼接所需字段 | |||||
let reqBody = { | |||||
send_now: true, //true 是立即发送, false是保存 | |||||
subject: this.form.subject, | |||||
template_id: this.form.tempId, | |||||
self_group_id: this.form.selfGroupId, | |||||
article_id: this.form.articleId || 0, | |||||
mptemplate_content: JSON.stringify(this.templateInput), | |||||
url: this.form.articleContent | |||||
}; | |||||
this.$refs['form'].validate((valid) => { | |||||
if(valid) { | |||||
const isCanSave = this.checkTemplateInput(); | |||||
if(!isCanSave) { | |||||
this.$message({ | |||||
type: "error", | |||||
message: "请完善模板内容" | |||||
}); | |||||
return | |||||
} | |||||
this.addGroupSender(reqBody, '群发'); | |||||
} else { | |||||
this.$message({ | |||||
type: "error", | |||||
message: "请完善群发消息" | |||||
}); | |||||
} | |||||
}); | |||||
}, | |||||
// 验证动态模板 | |||||
checkTemplateInput() { | |||||
console.log("templateInput", this.templateInput); | |||||
// 获取模板输入框的实际数量 | |||||
let tempInputLen = this.templateMsgCon.length; | |||||
console.log("tempInputLen", tempInputLen); | |||||
// 计算模板输入的数量 | |||||
let tempLen = (Object.keys(this.templateInput).length); | |||||
if( tempLen !== tempInputLen) { | |||||
return false | |||||
} else { | |||||
return true | |||||
} | |||||
}, | |||||
// 保存 | // 保存 | ||||
onSave() { | onSave() { | ||||
// 定义接口所需字段 | |||||
let reqBody = { | |||||
send_now: false, //true 是立即发送, false是保存 | |||||
subject: this.form.subject, //消息主题 | |||||
template_id: this.form.tempId, // 模板id | |||||
self_group_id: this.form.selfGroupId, //发送分组id | |||||
article_id: this.form.articleId || 0, //文章id | |||||
mptemplate_content: JSON.stringify(this.templateInput), //模板消息内容 | |||||
url: this.form.articleContent, //文章链接 | |||||
}; | |||||
this.$refs['form'].validate((valid) => { | |||||
if(valid) { | |||||
const isCanSave = this.checkTemplateInput(); | |||||
if(!isCanSave) { | |||||
this.$message({ | |||||
type: "error", | |||||
message: "请完善模板内容" | |||||
}); | |||||
return | |||||
} | |||||
this.addGroupSender(reqBody, '保存'); | |||||
} else { | |||||
this.$message({ | |||||
type: "error", | |||||
message: "请完善群发消息" | |||||
}); | |||||
} | |||||
}); | |||||
}, | |||||
// 添加群发 | |||||
addGroupSender(reqBody, action) { | |||||
const loading = this.$loading({ | |||||
text: `${action}中` | |||||
}); | |||||
APIWechatFans.addGroupSender(reqBody) | |||||
.then(res => { | |||||
console.log("res", res); | |||||
if(res.code === 20000) { | |||||
this.$message({ | |||||
type: "success", | |||||
message: `${action}成功!` | |||||
}); | |||||
} else { | |||||
this.$message({ | |||||
type: "error", | |||||
message: `${action}失败!${res.message}` | |||||
}); | |||||
} | |||||
}).catch(error => { | |||||
this.$message({ | |||||
type: "error", | |||||
message: '出错了!请联系管理员。' | |||||
}); | |||||
}).finally(() => { | |||||
loading.close(); | |||||
}) | |||||
}, | }, | ||||
// 预览 | // 预览 | ||||
onPreview() { | onPreview() { | ||||
const isCanSave = this.checkTemplateInput(); | |||||
if(!isCanSave) { | |||||
this.$message({ | |||||
type: "error", | |||||
message: "请先完善模板内容" | |||||
}); | |||||
return | |||||
} | |||||
this.previewShow = true; | this.previewShow = true; | ||||
this.tempData.push(this.templateInput); | |||||
let previewArr = this.objectToArray(this.tempData[0]).slice(1, this.objectToArray(this.tempData[0]).length - 1); | |||||
this.previewData.forEach((value, index) => { | |||||
value['value'] = previewArr[index]; | |||||
}); | |||||
}, | }, | ||||
// 预览确认 | // 预览确认 | ||||
onConfirm() { | onConfirm() { | ||||
@@ -144,16 +388,76 @@ export default { | |||||
// 选择文章 | // 选择文章 | ||||
onSelectArt(value) { | onSelectArt(value) { | ||||
if(value) { | if(value) { | ||||
this.form.contentUrl = value; | |||||
console.log("this.form.contentUrl", this.form.contentUrl); | |||||
this.form.articleId = value; | |||||
this.form.articleContent = this.articleList.filter(item => { | |||||
return item.value === value; | |||||
}).map(item => { | |||||
return item.label; | |||||
}).toString(); | |||||
} | } | ||||
}, | }, | ||||
// 选择群发对象分组 | // 选择群发对象分组 | ||||
onSelectMass(value) { | onSelectMass(value) { | ||||
if(value) { | if(value) { | ||||
this.form.group = value; | |||||
console.log("this.form.group", this.form.group); | |||||
this.form.selfGroupId = value; | |||||
console.log("选择的对象分组", value); | |||||
} | } | ||||
}, | |||||
// 获取消息模板列表 | |||||
getTemplateMsgList() { | |||||
APIWechatFans.getTemplateMsgList() | |||||
.then(res => { | |||||
let telpData = res.data; | |||||
this.templateMsgList = telpData.map(item => { | |||||
return { | |||||
label: item.title, | |||||
value: item.template_id | |||||
} | |||||
}); | |||||
// 默认显示第一个模板id | |||||
this.getTemplateMsgListById(this.templateMsgList[0].value); | |||||
}) | |||||
}, | |||||
// 根据模板id获取对应模板消息 | |||||
getTemplateMsgListById(id) { | |||||
APIWechatFans.getTemplateById(id) | |||||
.then(res => { | |||||
console.log("res", res); | |||||
let data = res.data; | |||||
let splitData = data.content.split('\\n'); | |||||
this.templateMsgCon = splitData.map(item => { | |||||
return { | |||||
name: item, | |||||
key: item.substring( item.indexOf("{{") + 2, item.indexOf(".DATA")) | |||||
} | |||||
}); | |||||
this.previewData = splitData.splice(1, splitData.length - 2 ).map(item => { | |||||
return { | |||||
name: item.substring( 0, item.indexOf(":")), | |||||
key: item.substring( item.indexOf("{{") + 2, item.indexOf(".DATA")) | |||||
} | |||||
}); | |||||
}) | |||||
}, | |||||
// 选择模板消息 | |||||
onSelectTemp(value) { | |||||
console.log("选择了模板消息", value); | |||||
this.form.tempId = value; | |||||
this.templateInput = {}; | |||||
this.getTemplateMsgListById(value); | |||||
}, | |||||
// 清空url填写 | |||||
onClearUrl() { | |||||
this.form.articleContent = ''; | |||||
if( this.form.articleId ) { | |||||
this.form.articleId = ''; | |||||
} | |||||
}, | |||||
onClearSelect() { | |||||
this.form.articleContent = ''; | |||||
}, | |||||
onOpenUrl() { | |||||
window.open(this.form.articleContent); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -161,18 +465,21 @@ export default { | |||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
.home-container { | .home-container { | ||||
height: 600px; | |||||
padding: 0 20px; | padding: 0 20px; | ||||
//overflow-y: scroll; | //overflow-y: scroll; | ||||
overflow-x: hidden; | overflow-x: hidden; | ||||
border: none; | border: none; | ||||
box-shadow: none; | box-shadow: none; | ||||
overflow-y: scroll; | |||||
.form-container { | .form-container { | ||||
height: 500px; | |||||
height: 600px; | |||||
padding: 5px 0; | |||||
border: 1px solid #d8dce5; | border: 1px solid #d8dce5; | ||||
padding: 20px; | |||||
display: flex; | display: flex; | ||||
justify-content: center; | justify-content: center; | ||||
align-items: center; | |||||
//align-items: center; | |||||
overflow: scroll; | |||||
p { | p { | ||||
margin: 5px 0; | margin: 5px 0; | ||||
} | } | ||||
@@ -187,7 +494,7 @@ export default { | |||||
} | } | ||||
} | } | ||||
.footer-container { | .footer-container { | ||||
height: 100px; | |||||
height: 60px; | |||||
display: flex; | display: flex; | ||||
justify-content: center; | justify-content: center; | ||||
align-items: center; | align-items: center; | ||||
@@ -211,6 +518,7 @@ export default { | |||||
flex-direction: column; | flex-direction: column; | ||||
padding: 0 40px; | padding: 0 40px; | ||||
border-bottom: 1px solid #d8dce5 ; | border-bottom: 1px solid #d8dce5 ; | ||||
overflow-y: scroll; | |||||
} | } | ||||
.fot { | .fot { | ||||
width: 100%; | width: 100%; | ||||
@@ -218,6 +526,9 @@ export default { | |||||
display: flex; | display: flex; | ||||
justify-content: space-between; | justify-content: space-between; | ||||
align-items: center; | align-items: center; | ||||
&:hover { | |||||
cursor: pointer; | |||||
} | |||||
} | } | ||||
} | } | ||||
.preview-btn { | .preview-btn { | ||||
@@ -1,38 +1,254 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2022-08-08 10:09:50 | * @Date: 2022-08-08 10:09:50 | ||||
* @LastEditors: JinxChen | * @LastEditors: JinxChen | ||||
* @LastEditTime: 2022-08-08 16:08:15 | |||||
* @LastEditTime: 2022-09-21 14:34:33 | |||||
* @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\mass-list\index.vue | * @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\mass-list\index.vue | ||||
* @description: 群发列表 | * @description: 群发列表 | ||||
--> | --> | ||||
<template> | <template> | ||||
<div class="app-container"> | |||||
<!-- 顶部内容 --> | |||||
<div class="top-container"> | |||||
<TopMenu :buttonList="buttonList"/> | |||||
</div> | |||||
<div class="home-container"> | |||||
<!-- 顶部内容 --> | |||||
<div class="top-container"> | |||||
<!-- 搜索 --> | |||||
<el-input | |||||
:placeholder="placeholder" | |||||
v-model="searchParams.subject" | |||||
class="search-input" | |||||
clearable | |||||
@clear="onClear" | |||||
/> | |||||
<el-button icon="el-icon-search" @click="onSearch" type="primary" class="search-btn">搜索</el-button> | |||||
</div> | |||||
<TTable :tableData="dataList" :columns="columns" @details="onDetails" @delete="onDelete" @update="onUpdate" @openUrl="openUrl"></TTable> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="total > 0" | |||||
ref="pages" | |||||
:total="total" | |||||
:page.sync="searchParams.page" | |||||
:limit.sync="searchParams.limit" | |||||
@pagination="pageChange" | |||||
/> | |||||
<el-dialog | |||||
title="发送明细" | |||||
:visible.sync="isDetailsShow" | |||||
center | |||||
top="5vh" | |||||
@close="onCloseDetail" | |||||
> | |||||
<TTable :tableData="detailsDataList" :columns="detailsColumns" :emptyText="errorMessage"></TTable> | |||||
<!-- <p v-else-if="detailsDataList.length <= 0">{{errorMessage}}</p> --> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="detailsTotal > 0" | |||||
ref="pages" | |||||
:total="detailsTotal" | |||||
:page.sync="detailsParams.page" | |||||
:limit.sync="detailsParams.limit" | |||||
@pagination="pageDetailsChange" | |||||
/> | |||||
</el-dialog> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import TopMenu from "@/components/TopMenu/index"; | |||||
import TTable from "@/components/TTable/TTable"; | |||||
import Pagination from "@/components/Pagination"; | |||||
import { APIWechatFans } from '@/api/wechat-fans.js'; | |||||
export default { | export default { | ||||
name: 'mass-list', | |||||
components: { TopMenu }, | |||||
data(){ | |||||
return { | |||||
buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | |||||
} | |||||
}, | |||||
mounted() {}, | |||||
created() {}, | |||||
methods: { | |||||
name: "mass-list", | |||||
components: { TTable, Pagination }, | |||||
data() { | |||||
return { | |||||
buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | |||||
searchParams: { | |||||
subject: "", | |||||
page: 1, | |||||
limit: 10 | |||||
}, | |||||
placeholder: "可输入消息主题", | |||||
dataList: [], | |||||
// 群发详细数组 | |||||
detailsDataList: [], | |||||
detailsColumns: [ | |||||
{ prop: "nickname", title: "发送对象", fixed: "left" }, | |||||
{ prop: "status", title: "发送状态" }, | |||||
{ prop: "send_time", title: "发送时间" }, | |||||
], | |||||
columns: [ | |||||
{ prop: "subject", title: "消息主题", fixed: "left" }, | |||||
{ prop: "template_content", isCustom: true, title: "内容摘要", fnName: 'openUrl' }, | |||||
{ prop: "self_group_name", title: "发送分组" }, | |||||
{ prop: "create_time", title: "创建时间" }, | |||||
{ | |||||
action: true, | |||||
title: "操作", | |||||
fixed: "right", | |||||
actions: [ | |||||
/* { | |||||
fnName: "update", | |||||
title: "修改", | |||||
type: "primary", | |||||
icon: "el-icon-edit", | |||||
size: "small" | |||||
}, */ | |||||
{ | |||||
fnName: "delete", | |||||
title: "删除", | |||||
type: "danger", | |||||
icon: "el-icon-delete", | |||||
size: "small" | |||||
}, | |||||
{ | |||||
fnName: "details", | |||||
title: "发送明细", | |||||
type: "success", | |||||
icon: "el-icon-tickets", | |||||
size: "small" | |||||
} | |||||
/* { fnName: "delete", title: "删除", type: "danger" , icon: 'el-icon-delete', size: 'small'}, */ | |||||
] | |||||
} | |||||
], | |||||
total: 0, | |||||
isDetailsShow: false, | |||||
detailsTotal: 0, | |||||
detailsParams: { | |||||
page: 1, | |||||
limit: 10 | |||||
}, | |||||
errorMessage: '', //详情错误信息 | |||||
// 群发明细ID | |||||
massDetailsId: '' | |||||
} | |||||
} | |||||
}; | |||||
}, | |||||
mounted() { | |||||
}, | |||||
activated() { | |||||
this.getGroupSender(); | |||||
}, | |||||
created() { | |||||
this.getGroupSender(); | |||||
}, | |||||
methods: { | |||||
//获取群发列表 | |||||
getGroupSender() { | |||||
let reqBody = { | |||||
subject: this.searchParams.subject, | |||||
page_index: this.searchParams.page, | |||||
page_size: this.searchParams.limit | |||||
}; | |||||
APIWechatFans.getGroupSender(reqBody) | |||||
.then(res => { | |||||
console.log("res::", res); | |||||
this.dataList = res.data.rows.map(item => { | |||||
item.template_content = item.template_content ? JSON.parse(item.template_content).remark : ''; | |||||
return item | |||||
}); | |||||
this.total = res.data.totals; | |||||
}) | |||||
}, | |||||
// 搜索 | |||||
onSearch() { | |||||
this.getGroupSender(); | |||||
}, | |||||
// 清空输入框 | |||||
onClear() { | |||||
this.searchParams.subject = ''; | |||||
this.getGroupSender(); | |||||
}, | |||||
onUpdate() { | |||||
}, | |||||
onDelete(value) { | |||||
let that = this; | |||||
this.$confirm("是否删除?", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning" | |||||
}).then(() => { | |||||
APIWechatFans.deleteGroupSender(value.id) | |||||
.then(res => { | |||||
if(res.code === 20000) { | |||||
this.$message({ | |||||
type: "success", | |||||
message: "删除成功" | |||||
}); | |||||
this.getGroupSender(); | |||||
} else { | |||||
this.$message({ | |||||
type: "error", | |||||
message: `删除失败!${error.message}` | |||||
}); | |||||
} | |||||
}) | |||||
}) | |||||
}, | |||||
// 群发明细 | |||||
onDetails(value) { | |||||
console.log("value", value); | |||||
//this.$router.push({name: 'send-details'}); | |||||
this.isDetailsShow = true; | |||||
this.massDetailsId = value.id; | |||||
this.getGroupSenderDetails(value.id); | |||||
}, | |||||
// 获取单个群发明细 | |||||
getGroupSenderDetails(id) { | |||||
let reqBody = { | |||||
page_index: 1, | |||||
page_size: 10, | |||||
}; | |||||
APIWechatFans.getGroupSenderDetails(id,reqBody) | |||||
.then(res => { | |||||
console.log("res", res); | |||||
if(res.data !== null) { | |||||
this.detailsDataList = res.data.rows.map(item => { | |||||
item.status = item.status === 1 ? '发送成功' : '发送失败'; | |||||
return item | |||||
}); | |||||
this.detailsTotal = res.data.totals; | |||||
} else { | |||||
this.errorMessage = res.message; | |||||
} | |||||
}) | |||||
console.log("reqBody", reqBody); | |||||
}, | |||||
// 关闭群发明细 | |||||
onCloseDetail() { | |||||
this.getGroupSender(); | |||||
}, | |||||
// 分页发生变化 | |||||
pageChange() { | |||||
if (this.searchParams.subject !== "") { | |||||
this.searchParams.subject = ""; | |||||
this.getGroupSender(); | |||||
} else { | |||||
this.getGroupSender(); | |||||
} | |||||
}, | |||||
// 群发明细发生变化 | |||||
pageDetailsChange() { | |||||
this.getGroupSenderDetails(this.massDetailsId); | |||||
}, | |||||
// 打开链接 | |||||
openUrl(value) { | |||||
window.open(value.url); | |||||
console.log("value", value.url); | |||||
} | |||||
} | |||||
}; | |||||
</script> | </script> | ||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
.search-input { | |||||
width: 350px; | |||||
margin-left: 20px; | |||||
} | |||||
.search-btn { | |||||
margin-left: 20px; | |||||
width: 100px; | |||||
} | |||||
</style> | </style> |
@@ -0,0 +1,77 @@ | |||||
<!-- | |||||
* @Date: 2022-08-08 10:09:50 | |||||
* @LastEditors: JinxChen | |||||
* @LastEditTime: 2022-09-09 14:54:02 | |||||
* @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\send-details\index.vue | |||||
* @description: 发送明细 | |||||
--> | |||||
<template> | |||||
<div class="home-container"> | |||||
<!-- 顶部内容 --> | |||||
<!-- <div class="top-container"> | |||||
<el-input | |||||
:placeholder="placeholder" | |||||
v-model="searchParams.inputValue" | |||||
class="search-input" | |||||
/> | |||||
<el-button icon="el-icon-search" @click="onSearch" type="primary" class="search-btn">搜索</el-button> | |||||
</div> --> | |||||
<TTable :tableData="dataList" :columns="columns"></TTable> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="total > 0" | |||||
ref="pages" | |||||
:total="total" | |||||
:page.sync="searchParams.page" | |||||
:limit.sync="searchParams.limit" | |||||
/> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import TTable from "@/components/TTable/TTable"; | |||||
import Pagination from "@/components/Pagination"; | |||||
export default { | |||||
name: "send-details", | |||||
components: { TTable, Pagination }, | |||||
data() { | |||||
return { | |||||
buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}} | |||||
searchParams: { | |||||
inputValue: "", | |||||
page: 1, | |||||
limit: 10 | |||||
}, | |||||
placeholder: "可输入消息主题", | |||||
dataList: [ | |||||
{ sendUser: '张三', sendStatus: '成功', sendTime: '2022.09.09 17:35' }, | |||||
{ sendUser: '李四', sendStatus: '成功', sendTime: '2022.09.09 17:35' }, | |||||
{ sendUser: '王五', sendStatus: '失败', sendTime: '2022.09.09 17:35' }, | |||||
], | |||||
columns: [ | |||||
{ prop: "sendUser", title: "发送对象", fixed: "left" }, | |||||
{ prop: "sendStatus", title: "发送状态" }, | |||||
{ prop: "sendTime", title: "发送时间" }, | |||||
], | |||||
total: 1 | |||||
}; | |||||
}, | |||||
mounted() {}, | |||||
created() {}, | |||||
methods: { | |||||
onSearch() {} | |||||
} | |||||
}; | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.search-input { | |||||
width: 350px; | |||||
margin-left: 20px; | |||||
} | |||||
.search-btn { | |||||
margin-left: 20px; | |||||
width: 100px; | |||||
} | |||||
</style> |
@@ -0,0 +1,31 @@ | |||||
<!-- | |||||
* @Date: 2022-08-08 10:14:16 | |||||
* @LastEditors: JinxChen | |||||
* @LastEditTime: 2022-09-08 15:54:08 | |||||
* @FilePath: \TelpoUserManageAdmin\src\views\traffic-statistics\main\index.vue | |||||
* @description: 家长端流量统计 | |||||
--> | |||||
<template> | |||||
<div style="padding:30px;"> | |||||
<el-alert :closable="false" title="menu 1"> | |||||
<router-view /> | |||||
</el-alert> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
export default { | |||||
name:'', | |||||
data(){ | |||||
return { | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped> | |||||
</style> |
@@ -0,0 +1,43 @@ | |||||
<!-- | |||||
* @Date: 2022-09-08 15:55:10 | |||||
* @LastEditors: JinxChen | |||||
* @LastEditTime: 2022-09-08 16:11:22 | |||||
* @FilePath: \TelpoUserManageAdmin\src\views\traffic-statistics\main\ssjl-statistics\index.vue | |||||
* @description: | |||||
--> | |||||
<template> | |||||
<div class="app-container"> | |||||
<div class="home-container"> | |||||
<p>账号: <el-input v-model="account" ></el-input></p> | |||||
<p>密码: <el-input v-model="password" ></el-input></p> | |||||
<el-button type="success" icon="el-icon-paperclip" @click="onJumpBaidu">点击跳转百度统计平台</el-button> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
export default { | |||||
name: 'ssjl-statistics', | |||||
data(){ | |||||
return { | |||||
hrefUrl: 'https://tongji.baidu.com/web5/welcome/login', | |||||
account: 'ssjlai', | |||||
password: 'Ssjlai_123456' | |||||
} | |||||
}, | |||||
methods: { | |||||
onJumpBaidu() { | |||||
window.open(this.hrefUrl); | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.home-container { | |||||
.el-input { | |||||
width: 200px; | |||||
} | |||||
} | |||||
</style> |
@@ -6,7 +6,7 @@ function resolve(dir) { | |||||
return path.join(__dirname, dir) | return path.join(__dirname, dir) | ||||
} | } | ||||
const name = defaultSettings.title || '用户运营管理系统' // page title | |||||
const name = defaultSettings.title || '用户运营管理平台' // page title | |||||
// If your port is set to 80, | // If your port is set to 80, | ||||
// use administrator privileges to execute the command line. | // use administrator privileges to execute the command line. | ||||