|
|
@@ -117,6 +117,64 @@
|
|
|
v-hasPermi="['course:courseWatchLog:export']"
|
|
|
>导出</el-button>
|
|
|
</el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ v-hasPermi="['app:user:bindTag']"
|
|
|
+ @click="openBindTagPage(false, 0)"
|
|
|
+ >批量添加标签
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="info"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ v-hasPermi="['app:user:unbindTag']"
|
|
|
+ @click="openUnbindTagPage(false, 1)"
|
|
|
+ >批量移除标签
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ v-hasPermi="['app:user:batchBindTag']"
|
|
|
+ @click="openBindTagPage(true, 0)"
|
|
|
+ >批量添加标签(筛选条件)
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="info"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ v-hasPermi="['app:user:batchUnbindTag']"
|
|
|
+ @click="openUnbindTagPage(true, 1)"
|
|
|
+ >批量移除标签(筛选条件)
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="success"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ @click="openRemarkPage(false)"
|
|
|
+ >批量修改备注
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="success"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ @click="openRemarkPage(true)"
|
|
|
+ >批量修改备注(筛选条件)
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
</el-row>
|
|
|
|
|
|
@@ -169,13 +227,82 @@
|
|
|
@pagination="getList"
|
|
|
/>
|
|
|
|
|
|
+ <el-dialog :title="tagConfig.title" :visible.sync="tagConfig.visible" width="800px" append-to-body>
|
|
|
+ <div>搜索标签:
|
|
|
+ <el-input v-model="tagConfig.queryParams.groupName" placeholder="请输入标签名称" clearable size="small"
|
|
|
+ style="width: 200px;margin-right: 10px"/>
|
|
|
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags">搜索</el-button>
|
|
|
+ <el-button type="primary" icon="el-icon-refresh" size="mini" @click="cancelSearchTags">重置</el-button>
|
|
|
+ </div>
|
|
|
+ <div class="dialog-body">
|
|
|
+ <div v-for="groupItem in tagConfig.tagGroupList" :key="groupItem.id">
|
|
|
+ <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
|
|
|
+ <span class="name-background">{{ groupItem.name }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="tag-container">
|
|
|
+ <a
|
|
|
+ v-for="tagItem in groupItem.tags"
|
|
|
+ :key="tagItem.id"
|
|
|
+ class="tag-box"
|
|
|
+ @click="tagSelection(tagItem)"
|
|
|
+ :class="{ 'tag-selected': tagItem.isSelected }"
|
|
|
+ >
|
|
|
+ {{ tagItem.name }}
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <pagination
|
|
|
+ v-show="tagConfig.total > 0"
|
|
|
+ :total="tagConfig.total"
|
|
|
+ :page.sync="tagConfig.queryParams.pageNum"
|
|
|
+ :limit.sync="tagConfig.queryParams.pageSize"
|
|
|
+ @pagination="getTagGroupList"
|
|
|
+ />
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="bindOrUnbindTagSubmit">确 定</el-button>
|
|
|
+ <el-button @click="bindTagCancel">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog :title="remarkConfig.title" :visible.sync="remarkConfig.visible" width="600px" append-to-body>
|
|
|
+ <el-form label-width="90px">
|
|
|
+ <el-form-item label="备注类型">
|
|
|
+ <el-radio-group v-model="remarkConfig.remarkType">
|
|
|
+ <el-radio :label="1">用户名称添加在新备注前</el-radio>
|
|
|
+ <el-radio :label="2">用户名称添加在新备注后</el-radio>
|
|
|
+ <el-radio :label="3">不添加用户名称</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注内容">
|
|
|
+ <el-input
|
|
|
+ v-model="remarkConfig.remark"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ placeholder="请输入备注信息"
|
|
|
+ maxlength="30"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" :loading="remarkConfig.loading" @click="submitRemark">确 定</el-button>
|
|
|
+ <el-button @click="cancelRemark">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { listAppCourseWatchLog, exportAppCourseWatchLog,getCustomerListLikeName } from "@/api/course/courseWatchLog";
|
|
|
+import { listAppCourseWatchLog, exportAppCourseWatchLog, getCustomerListLikeName, batchUpdateFriendRemark } from "@/api/course/courseWatchLog";
|
|
|
import { courseList,videoList } from '../../../api/course/courseRedPacketLog'
|
|
|
import {getTask} from "@/api/common";
|
|
|
+import { listTagGroupForUserBindTag } from "@/api/app/tag/tagGroup";
|
|
|
+import {
|
|
|
+ bindTagV2,
|
|
|
+ unbindTagV2,
|
|
|
+} from "@/api/app/tag/bindTag";
|
|
|
export default {
|
|
|
name: "CourseWatchLog",
|
|
|
data() {
|
|
|
@@ -190,7 +317,7 @@ export default {
|
|
|
loading: true,
|
|
|
// 导出遮罩层
|
|
|
exportLoading: false,
|
|
|
- // 选中数组
|
|
|
+ // 选中数组(会员userId)
|
|
|
ids: [],
|
|
|
// 非单个禁用
|
|
|
single: true,
|
|
|
@@ -240,6 +367,7 @@ export default {
|
|
|
scheduleEndTime: null,
|
|
|
isVip: null,
|
|
|
watchType:null,
|
|
|
+ appCustomerId: null,
|
|
|
},
|
|
|
// 表单参数
|
|
|
form: {},
|
|
|
@@ -256,6 +384,28 @@ export default {
|
|
|
},
|
|
|
companyUserOptionsLoading: false,
|
|
|
companyUserOptions: [],
|
|
|
+ tagConfig: {
|
|
|
+ visible: false,
|
|
|
+ enableFilter: false,
|
|
|
+ title: null,
|
|
|
+ opType: 0,//0-添加,1-移除
|
|
|
+ queryParams: {
|
|
|
+ groupName: null,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ },
|
|
|
+ total: 0,
|
|
|
+ tagGroupList: [],
|
|
|
+ selected: [],
|
|
|
+ },
|
|
|
+ remarkConfig: {
|
|
|
+ visible: false,
|
|
|
+ enableFilter: false,
|
|
|
+ title: '批量修改备注',
|
|
|
+ remarkType: 1,
|
|
|
+ remark: '',
|
|
|
+ loading: false,
|
|
|
+ },
|
|
|
};
|
|
|
},
|
|
|
created() {
|
|
|
@@ -366,12 +516,227 @@ export default {
|
|
|
this.updateTime=null;
|
|
|
this.handleQuery();
|
|
|
},
|
|
|
- // 多选框选中数据
|
|
|
+ // 多选框选中数据(按会员userId去重,用于批量打标签)
|
|
|
handleSelectionChange(selection) {
|
|
|
- this.ids = selection.map(item => item.logId)
|
|
|
+ this.ids = [...new Set(selection.map(item => item.userId).filter(id => id != null))]
|
|
|
this.single = selection.length!==1
|
|
|
this.multiple = !selection.length
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 用户绑定标签页面
|
|
|
+ */
|
|
|
+ openBindTagPage(enableFilter = false, opType = 0) {
|
|
|
+ this.tagConfig.enableFilter = enableFilter;
|
|
|
+ this.tagConfig.opType = opType;
|
|
|
+ if (!enableFilter && (this.ids === null || this.ids.length === 0)) {
|
|
|
+ this.$message.closeAll();
|
|
|
+ return this.$message('请选择需要添加标签的用户');
|
|
|
+ }
|
|
|
+ this.getTagGroupList();
|
|
|
+ this.tagConfig.title = '批量添加标签' + (enableFilter ? '(筛选条件)' : '');
|
|
|
+ this.tagConfig.visible = true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 用户解绑标签页面
|
|
|
+ */
|
|
|
+ openUnbindTagPage(enableFilter = false, opType = 1) {
|
|
|
+ this.tagConfig.enableFilter = enableFilter;
|
|
|
+ this.tagConfig.opType = opType;
|
|
|
+ if (!enableFilter && (this.ids === null || this.ids.length === 0)) {
|
|
|
+ this.$message.closeAll();
|
|
|
+ return this.$message('请选择需要移除标签的用户');
|
|
|
+ }
|
|
|
+ this.getTagGroupList();
|
|
|
+ this.tagConfig.title = '批量移除标签' + (enableFilter ? '(筛选条件)' : '');
|
|
|
+ this.tagConfig.visible = true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 绑定/解绑 标签页面搜索
|
|
|
+ */
|
|
|
+ handleSearchTags() {
|
|
|
+ this.tagConfig.queryParams.pageNum = 1;
|
|
|
+ this.getTagGroupList();
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 绑定/解绑 标签页面重置
|
|
|
+ */
|
|
|
+ cancelSearchTags() {
|
|
|
+ this.tagConfig.queryParams = {
|
|
|
+ groupName: null,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ }
|
|
|
+ this.getTagGroupList();
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 切换选中状态
|
|
|
+ * @param row
|
|
|
+ */
|
|
|
+ tagSelection(row) {
|
|
|
+ row.isSelected = !row.isSelected;
|
|
|
+ if (row.isSelected) {
|
|
|
+ this.tagConfig.selected.push({ tagId: row.id, tagName: row.name });
|
|
|
+ } else {
|
|
|
+ this.tagConfig.selected = this.tagConfig.selected.filter(item => item.tagId !== row.id);
|
|
|
+ }
|
|
|
+ this.$forceUpdate();
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 重置 绑定/解绑 标签参数
|
|
|
+ */
|
|
|
+ resetBindTag() {
|
|
|
+ this.tagConfig = {
|
|
|
+ visible: false,
|
|
|
+ enableFilter: false,
|
|
|
+ title: null,
|
|
|
+ opType: 0,
|
|
|
+ queryParams: {
|
|
|
+ groupName: null,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ },
|
|
|
+ total: 0,
|
|
|
+ tagGroupList: [],
|
|
|
+ selected: [],
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 绑定/解绑 标签-提交
|
|
|
+ */
|
|
|
+ bindOrUnbindTagSubmit() {
|
|
|
+ let opType = this.tagConfig.opType;
|
|
|
+ let tmpParam = {};
|
|
|
+ if (!this.tagConfig.selected || this.tagConfig.selected.length === 0) {
|
|
|
+ return this.$message('请选择标签');
|
|
|
+ }
|
|
|
+ tmpParam['enableFilter'] = this.tagConfig.enableFilter;
|
|
|
+ tmpParam['tagId'] = this.tagConfig.selected.map(item => item.tagId);
|
|
|
+ tmpParam['userId'] = this.ids;
|
|
|
+ const queryParams = JSON.parse(JSON.stringify(this.queryParams));
|
|
|
+ delete queryParams['startIndex'];
|
|
|
+ delete queryParams['pageLimit'];
|
|
|
+ tmpParam['fsUserParam'] = queryParams;
|
|
|
+ //绑定标签
|
|
|
+ if (opType === 0) {
|
|
|
+ bindTagV2(tmpParam)
|
|
|
+ .then(res => {
|
|
|
+ this.tagConfig.visible = false;
|
|
|
+ this.resetBindTag();
|
|
|
+ this.msgSuccess("正在添加中!");
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getList();
|
|
|
+ }, 500);
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ this.msgError("添加标签失败!");
|
|
|
+ })
|
|
|
+ }
|
|
|
+ //解绑标签
|
|
|
+ else {
|
|
|
+ unbindTagV2(tmpParam)
|
|
|
+ .then(res => {
|
|
|
+ this.tagConfig.visible = false;
|
|
|
+ this.msgSuccess("正在移除中!");
|
|
|
+ this.resetBindTag();
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getList();
|
|
|
+ }, 500);
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ this.msgError("移除标签失败!");
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 绑定/解绑 标签-取消
|
|
|
+ */
|
|
|
+ bindTagCancel() {
|
|
|
+ this.resetBindTag();
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 查询标签列表
|
|
|
+ */
|
|
|
+ getTagGroupList() {
|
|
|
+ listTagGroupForUserBindTag(this.tagConfig.queryParams).then(response => {
|
|
|
+ this.tagConfig.tagGroupList = response.rows;
|
|
|
+ this.tagConfig.total = response.total;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 打开批量修改备注弹窗
|
|
|
+ * @param enableFilter 是否按筛选条件
|
|
|
+ */
|
|
|
+ openRemarkPage(enableFilter = false) {
|
|
|
+ if (!enableFilter && (!this.ids || this.ids.length === 0)) {
|
|
|
+ this.$message.closeAll();
|
|
|
+ return this.$message('请选择需要修改备注的用户');
|
|
|
+ }
|
|
|
+ if (enableFilter && (!this.total || this.total <= 0)) {
|
|
|
+ this.$message.closeAll();
|
|
|
+ return this.$message('当前筛选条件下没有数据');
|
|
|
+ }
|
|
|
+ this.remarkConfig.enableFilter = enableFilter;
|
|
|
+ this.remarkConfig.remarkType = 1;
|
|
|
+ this.remarkConfig.remark = '';
|
|
|
+ this.remarkConfig.loading = false;
|
|
|
+ this.remarkConfig.title = '批量修改备注' + (enableFilter ? '(筛选条件)' : '');
|
|
|
+ this.remarkConfig.visible = true;
|
|
|
+ },
|
|
|
+ cancelRemark() {
|
|
|
+ this.remarkConfig.visible = false;
|
|
|
+ this.remarkConfig.enableFilter = false;
|
|
|
+ this.remarkConfig.remarkType = 1;
|
|
|
+ this.remarkConfig.remark = '';
|
|
|
+ this.remarkConfig.loading = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 提交批量修改备注
|
|
|
+ */
|
|
|
+ async submitRemark() {
|
|
|
+ const remark = (this.remarkConfig.remark || '').trim();
|
|
|
+ if (!remark) {
|
|
|
+ return this.$message.error('请输入备注内容');
|
|
|
+ }
|
|
|
+ if (remark.length > 30) {
|
|
|
+ return this.$message.error('备注内容不能超过30个字符');
|
|
|
+ }
|
|
|
+ this.remarkConfig.loading = true;
|
|
|
+ try {
|
|
|
+ let userIds = [];
|
|
|
+ if (this.remarkConfig.enableFilter) {
|
|
|
+ // 按筛选条件拉取全部匹配记录的 userId
|
|
|
+ const queryParams = JSON.parse(JSON.stringify(this.queryParams));
|
|
|
+ queryParams.pageNum = 1;
|
|
|
+ queryParams.pageSize = this.total > 0 ? this.total : 10000;
|
|
|
+ if (queryParams.logType == "10") {
|
|
|
+ queryParams.logType = null;
|
|
|
+ }
|
|
|
+ const response = await listAppCourseWatchLog(queryParams);
|
|
|
+ const rows = response.rows || [];
|
|
|
+ userIds = [...new Set(rows.map(item => item.userId).filter(id => id != null))];
|
|
|
+ } else {
|
|
|
+ userIds = this.ids;
|
|
|
+ }
|
|
|
+ if (!userIds || userIds.length === 0) {
|
|
|
+ this.remarkConfig.loading = false;
|
|
|
+ return this.$message.error('没有可修改备注的用户');
|
|
|
+ }
|
|
|
+ await batchUpdateFriendRemark({
|
|
|
+ remarkType: this.remarkConfig.remarkType,
|
|
|
+ remark,
|
|
|
+ userId: userIds,
|
|
|
+ });
|
|
|
+ this.msgSuccess('正在修改备注中!');
|
|
|
+ this.cancelRemark();
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getList();
|
|
|
+ }, 500);
|
|
|
+ } catch (e) {
|
|
|
+ this.msgError('修改备注失败!');
|
|
|
+ } finally {
|
|
|
+ this.remarkConfig.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
/** 新增按钮操作 */
|
|
|
handleAdd() {
|
|
|
this.reset();
|
|
|
@@ -464,3 +829,36 @@ export default {
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.dialog-body {
|
|
|
+ height: 400px;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.tag-container {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.name-background {
|
|
|
+ display: inline-block;
|
|
|
+ background-color: #abece6;
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.tag-box {
|
|
|
+ padding: 8px 12px;
|
|
|
+ border: 1px solid #989797;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+.tag-selected {
|
|
|
+ background-color: #00bc98;
|
|
|
+ color: #fff;
|
|
|
+ border-color: #00bc98;
|
|
|
+}
|
|
|
+</style>
|