Bläddra i källkod

Merge branch 'develop' into test

test
JinxChen 2 år sedan
förälder
incheckning
c098abedb9
6 ändrade filer med 265 tillägg och 78 borttagningar
  1. +11
    -2
      README.md
  2. +16
    -1
      src/api/wechat-fans.js
  3. +15
    -2
      src/components/TTable/TTable.vue
  4. +2
    -2
      src/utils/model.js
  5. +200
    -57
      src/views/message-manage/main/add-mass/index.vue
  6. +21
    -14
      src/views/message-manage/main/mass-list/index.vue

+ 11
- 2
README.md Visa fil

@@ -1,7 +1,7 @@
<!--
* @Date: 2021-11-29 11:14:13
* @LastEditors: JinxChen
* @LastEditTime: 2022-09-20 09:21:28
* @LastEditTime: 2022-09-21 14:40:58
* @FilePath: \TelpoUserManageAdmin\README.md
* @description:
-->
@@ -112,4 +112,13 @@ fix
- 添加群发
- 群发列表
- 修复 分页异常的问题
- 修复 预览异常的问题
- 修复 预览异常的问题


## v1.0.7
`2022.9.21`
feat
- 添加群发
- 增加 动态创建消息模板
- 群发列表
- 修复 分页异常的问题

+ 16
- 1
src/api/wechat-fans.js Visa fil

@@ -1,7 +1,7 @@
/*
* @Date: 2022-09-15 16:40:39
* @LastEditors: JinxChen
* @LastEditTime: 2022-09-19 16:50:23
* @LastEditTime: 2022-09-20 11:25:01
* @FilePath: \TelpoUserManageAdmin\src\api\wechat-fans.js
* @description:
*/
@@ -13,6 +13,8 @@ export const APIWechatFans = {
getArticlesGroup, //获取文章列表
getGroupSenderDetails, //获取单个群发记录
deleteGroupSender, //删除单个群发记录
getTemplateMsgList, //获取模板消息列表
getTemplateById, //根据模板id获取对应的模板消息
};
export default APIWechatFans;

@@ -64,3 +66,16 @@ function deleteGroupSender(id) {
method: 'delete',
});
}
function getTemplateMsgList(){
return requestWxFans({
url: `/GroupSender/TemplateMsgTemplates`,
method: 'get',
});
}

function getTemplateById(id){
return requestWxFans({
url: `/GroupSender/TemplateMsgTemplates/${id}`,
method: 'get',
});
}

+ 15
- 2
src/components/TTable/TTable.vue Visa fil

@@ -1,7 +1,7 @@
<!--
* @Date: 2021-11-30 17:19:51
* @LastEditors: JinxChen
* @LastEditTime: 2022-09-17 14:42:20
* @LastEditTime: 2022-09-21 14:31:06
* @FilePath: \TelpoUserManageAdmin\src\components\TTable\TTable.vue
* @description: 封装通用的table组件
-->
@@ -16,9 +16,16 @@
:prop="column.prop"
:label="column.title"
:fixed="column.fixed"
v-if="!column.action"
v-if="!column.action && !column.isCustom"
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">
<template slot-scope="scope">
@@ -97,4 +104,10 @@ export default {
.el-table {
font-size: 14px;
}
.details-underline {
text-decoration: underline;
&:hover {
cursor: pointer;
}
}
</style>

+ 2
- 2
src/utils/model.js Visa fil

@@ -1,8 +1,8 @@
/*
* @Date: 2021-11-30 15:09:25
* @LastEditors: JinxChen
* @LastEditTime: 2022-09-20 09:20:40
* @LastEditTime: 2022-09-21 14:18:59
* @FilePath: \TelpoUserManageAdmin\src\utils\model.js
* @description: 版本号
*/
export const VersionModel = '1.0.6';
export const VersionModel = '1.0.7';

+ 200
- 57
src/views/message-manage/main/add-mass/index.vue Visa fil

@@ -1,7 +1,7 @@
<!--
* @Date: 2022-08-08 10:09:47
* @LastEditors: JinxChen
* @LastEditTime: 2022-09-20 09:20:19
* @LastEditTime: 2022-09-21 14:43:45
* @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\add-mass\index.vue
* @description: 添加群发
-->
@@ -14,41 +14,26 @@
<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 label="内容模板:" size="small" required>


<el-form-item prop="first">
<p>{{firstData}}</p>
<el-input v-model="form.first" class="input-width-600" clearable prop="first"></el-input>
</el-form-item>

<el-form-item prop="keyword1">
<p>消息类别{{keyword1Data}}</p>
<el-input v-model="form.keyword1" class="input-width-400" clearable prop="keyword1"></el-input>
</el-form-item>

<el-form-item prop="keyword2">
<p>通知用户{{keyword2Data}}</p>
<el-input v-model="form.keyword2" class="input-width-400" clearable prop="keyword1"></el-input>
</el-form-item>

<el-form-item prop="keyword3">
<p>通知内容{{keyword3Data}}</p>
<el-input v-model="form.keyword3" class="input-width-600" clearable prop="keyword1"></el-input>
</el-form-item>

<el-form-item prop="remark">
<p>{{remarkData}}</p>
<el-input v-model="form.remark" class="input-width-600" clearable prop="remark"></el-input>
<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-form-item>
<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" prop="articleContent" required>
<el-form-item prop="remark">
<el-input v-model="form.articleContent" placeholder="请选择文章或者输入外部URL" class="input-width-400"></el-input>
<el-select v-model="article" placeholder="选择文章" clearable filterable @change="onSelectArt">
<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-select> -->
</el-form-item>
</el-form-item>

@@ -68,14 +53,14 @@
<el-dialog title="预览信息" :visible.sync="previewShow">
<div class="preview-container">
<div class="top">
<p>{{form.first}}</p>
<p>消息类别:{{form.keyword1}}</p>
<p>通知用户:{{form.keyword2}}</p>
<p>通知内容:{{form.keyword3}}</p>
<p>更新时间:{{initUpdateTime}}</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 class="fot">
<p>{{form.remark}}</p>
<div class="fot" @click="onOpenUrl">
<p>详情</p>
<p>></p>
</div>
</div>
@@ -95,6 +80,16 @@ export default {
name: 'add-mass',
components: { },
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 {
buttonList: [], // 头部按钮,例子: {name: '添加', type: 'primary', icon: 'el-icon-circle-plus', click: () => { this.AddDialog();}}
firstData: '{{first.DATA}}:',
@@ -113,6 +108,7 @@ export default {
keyword2: '' /* || '财商36问' */, //更新内容
keyword3: '',
remark: '' /* || '请点击内容查看详情' */, //内容详情
tempId: '' || '-kOhlwJPhO7v3WW3rAdmNs76lR7ZpQEJtbVSY8Y35Eg', //模板id
},
article: '', //选择文章
// 文章列表
@@ -128,12 +124,17 @@ export default {
],
// 预览dialog
previewShow: false,
// 要预览的页面字段
previewData: [],
// form验证
rules: {
subject: [
{ required: true, message: '请输入消息主题', trigger: 'blur' },
],
first: [
tempId: [
{ required: true, message: '请选择模板消息', trigger: 'blur' },
],
/* first: [
{ required: true, message: '请填写消息模板内容', trigger: 'blur' },
],
keyword1: [
@@ -145,35 +146,70 @@ export default {
keyword3: [
{ required: true, message: '请填写消息模板内容', trigger: 'blur' },
],
remark: [
keyword4: [
{ required: true, message: '请填写消息模板内容', trigger: 'blur' },
],
messageSubject: [
keyword5: [
{ required: true, message: '请填写消息模板内容', trigger: 'blur' },
],
remark: [
{ required: true, message: '请填写消息模板内容', trigger: 'blur' },
], */
articleContent: [
{ required: true, message: '请选择文章获取填写外部URL', trigger: 'blur' },
{ 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: {
// 初始弹窗更新时间
initUpdateTime() {
return initTime(new Date(), 'ymdhm'); //更新时间
}
},
},
activated() {
this.getSelfGroups();
this.getArticlesGroup();
this.getTemplateMsgList();
},
mounted() {
},
created() {
this.getSelfGroups();
this.getTemplateMsgList();
this.getArticlesGroup();
},
methods: {
@@ -215,23 +251,39 @@ export default {
},
// 查看白名单
onCheckList() {},
// objectToArray
objectToArray(obj) {
let arr = [];
for(let i in obj) {
// arr.push (obj[i] ) //返回属性值
arr.push(obj[i]) //返回键名
};
return arr;
},
// 立即发送
onSend() {
this.tempData.push(this.templateInput);
console.log("tempData", JSON.stringify(this.templateInput));
// 拼接所需字段
let keywordStr = this.form.keyword1 + ',' + this.form.keyword2 + ',' + this.form.keyword3;
let reqBody = {
send_now: true, //true 是立即发送, false是保存
subject: this.form.subject,
template_id: '1',
template_id: this.form.tempId,
self_group_id: this.form.selfGroupId,
article_id: this.form.articleId || 0,
first: this.form.first,
remark: this.form.remark,
keyword: keywordStr,
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({
@@ -240,25 +292,43 @@ export default {
});
}
});
//this.addGroupSender(reqBody);
},
// 验证动态模板
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() {
// 拼接所需字段
let keywordStr = this.form.keyword1 + ',' + this.form.keyword2 + ',' + this.form.keyword3;
let reqBody = {
send_now: false, //true 是立即发送, false是保存
subject: this.form.subject,
template_id: '1',
template_id: this.form.tempId,
self_group_id: this.form.selfGroupId,
article_id: this.form.articleId || 0,
first: this.form.first,
remark: this.form.remark,
keyword: keywordStr,
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({
@@ -298,7 +368,20 @@ export default {
},
// 预览
onPreview() {
const isCanSave = this.checkTemplateInput();
if(!isCanSave) {
this.$message({
type: "error",
message: "请先完善模板内容"
});
return
}
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() {
@@ -321,6 +404,62 @@ export default {
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);
}
}
}
@@ -381,6 +520,7 @@ export default {
flex-direction: column;
padding: 0 40px;
border-bottom: 1px solid #d8dce5 ;
overflow-y: scroll;
}
.fot {
width: 100%;
@@ -388,6 +528,9 @@ export default {
display: flex;
justify-content: space-between;
align-items: center;
&:hover {
cursor: pointer;
}
}
}
.preview-btn {


+ 21
- 14
src/views/message-manage/main/mass-list/index.vue Visa fil

@@ -1,7 +1,7 @@
<!--
* @Date: 2022-08-08 10:09:50
* @LastEditors: JinxChen
* @LastEditTime: 2022-09-20 09:16:28
* @LastEditTime: 2022-09-21 14:34:33
* @FilePath: \TelpoUserManageAdmin\src\views\message-manage\main\mass-list\index.vue
* @description: 群发列表
-->
@@ -20,7 +20,7 @@
/>
<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"></TTable>
<TTable :tableData="dataList" :columns="columns" @details="onDetails" @delete="onDelete" @update="onUpdate" @openUrl="openUrl"></TTable>
<!-- 分页 -->
<pagination
v-show="total > 0"
@@ -68,9 +68,7 @@ export default {
limit: 10
},
placeholder: "可输入消息主题",
dataList: [

],
dataList: [],
// 群发详细数组
detailsDataList: [],
detailsColumns: [
@@ -80,7 +78,7 @@ export default {
],
columns: [
{ prop: "subject", title: "消息主题", fixed: "left" },
{ prop: "template_first", title: "内容摘要(链接详情)" },
{ prop: "template_content", isCustom: true, title: "内容摘要", fnName: 'openUrl' },
{ prop: "self_group_name", title: "发送分组" },
{ prop: "create_time", title: "创建时间" },
{
@@ -146,7 +144,10 @@ export default {
APIWechatFans.getGroupSender(reqBody)
.then(res => {
console.log("res::", res);
this.dataList = res.data.rows;
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;
})
},
@@ -176,13 +177,14 @@ export default {
type: "success",
message: "删除成功"
});
this.getGroupSender();
} else {
this.$message({
type: "error",
message: `删除失败!${error.message}`
});
}
})
}).catch(error => {
this.$message({
type: "error",
message: `删除失败!${error.message}`
});
})
},
// 群发明细
@@ -220,8 +222,8 @@ export default {
},
// 分页发生变化
pageChange() {
if (this.searchParams.keywords !== "") {
this.searchParams.keywords = "";
if (this.searchParams.subject !== "") {
this.searchParams.subject = "";
this.getGroupSender();
} else {
this.getGroupSender();
@@ -230,6 +232,11 @@ export default {
// 群发明细发生变化
pageDetailsChange() {
this.getGroupSenderDetails(this.massDetailsId);
},
// 打开链接
openUrl(value) {
window.open(value.url);
console.log("value", value.url);
}
}
};


Laddar…
Avbryt
Spara