|
|
@@ -68,587 +68,10 @@
|
|
|
</basic-container>
|
|
|
</template>
|
|
|
|
|
|
-<script>
|
|
|
-import { getList, update, add, getAnnouncement, getCategoryList } from "@/api/announcement";
|
|
|
-import { mapGetters } from "vuex";
|
|
|
+<script src="./index.js">
|
|
|
|
|
|
-/**
|
|
|
- * 公告数据类型定义
|
|
|
- * @typedef {Object} NoticeItem
|
|
|
- * @property {string} id - 公告ID
|
|
|
- * @property {string} title - 公告标题
|
|
|
- * @property {string} content - 公告内容
|
|
|
- * @property {string} categoryId - 分类ID
|
|
|
- * @property {string} categoryName - 分类名称
|
|
|
- * @property {number} orgId - 组织ID
|
|
|
- * @property {string} orgCode - 组织编码
|
|
|
- * @property {string} orgName - 组织名称
|
|
|
- * @property {string} visibleRoles - 可见角色
|
|
|
- * @property {Object|null} brandScope - 品牌范围
|
|
|
- * @property {Object|null} customerBlacklist - 客户黑名单
|
|
|
- * @property {string} remark - 备注
|
|
|
- * @property {string} createTime - 创建时间
|
|
|
- * @property {string} updateTime - 更新时间
|
|
|
- * @property {number} status - 状态
|
|
|
- * @property {number} isDeleted - 是否删除
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * 分类选项类型定义
|
|
|
- * @typedef {Object} CategoryOption
|
|
|
- * @property {string} id - 分类ID
|
|
|
- * @property {string} name - 分类名称
|
|
|
- * @property {string} value - 选项值
|
|
|
- * @property {string} label - 选项标签
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * 分页信息类型定义
|
|
|
- * @typedef {Object} PageInfo
|
|
|
- * @property {number} pageSize - 每页大小
|
|
|
- * @property {number} currentPage - 当前页码
|
|
|
- * @property {number} total - 总记录数
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * 查询参数类型定义
|
|
|
- * @typedef {Object} QueryParams
|
|
|
- * @property {string} [title] - 公告标题
|
|
|
- * @property {string} [categoryId] - 分类ID
|
|
|
- * @property {string} [content] - 公告内容
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * 公告管理组件
|
|
|
- * @component NoticeIndex
|
|
|
- */
|
|
|
-export default {
|
|
|
- name: 'NoticeIndex',
|
|
|
- data() {
|
|
|
- return {
|
|
|
- /** @type {NoticeItem} 表单数据 */
|
|
|
- form: {},
|
|
|
- /** @type {QueryParams} 查询参数 */
|
|
|
- query: {},
|
|
|
- /** @type {boolean} 加载状态 */
|
|
|
- loading: true,
|
|
|
- /** @type {boolean} 详情对话框显示状态 */
|
|
|
- detailVisible: false,
|
|
|
- /** @type {NoticeItem} 当前查看的详情数据 */
|
|
|
- currentDetail: {},
|
|
|
- /** @type {PageInfo} 分页信息 */
|
|
|
- page: {
|
|
|
- pageSize: 10,
|
|
|
- currentPage: 1,
|
|
|
- total: 0
|
|
|
- },
|
|
|
- /** @type {NoticeItem[]} 选中的数据列表 */
|
|
|
- selectionList: [],
|
|
|
- /** @type {CategoryOption[]} 分类选项列表 */
|
|
|
- categoryOptions: [],
|
|
|
- /** @type {Object} 表格配置选项 */
|
|
|
- option: {
|
|
|
- height: 'auto',
|
|
|
- calcHeight: 30,
|
|
|
- dialogWidth: 1000,
|
|
|
- labelWidth: 120,
|
|
|
- tip: false,
|
|
|
- searchShow: true,
|
|
|
- searchMenuSpan: 6,
|
|
|
- border: true,
|
|
|
- index: true,
|
|
|
- viewBtn: true,
|
|
|
- selection: true,
|
|
|
- excelBtn: false,
|
|
|
- columnBtn: false,
|
|
|
- delBtn: false, // 根据需求移除删除功能
|
|
|
- dialogClickModal: false,
|
|
|
- column: [
|
|
|
- {
|
|
|
- label: "公告标题",
|
|
|
- prop: "title",
|
|
|
- span: 12,
|
|
|
- search: true,
|
|
|
- overHidden: true,
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请输入公告标题",
|
|
|
- trigger: "blur"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "分类",
|
|
|
- prop: "categoryId",
|
|
|
- type: "select",
|
|
|
- dicData: [],
|
|
|
- props: {
|
|
|
- label: "name",
|
|
|
- value: "id"
|
|
|
- },
|
|
|
- slot: true,
|
|
|
- search: true,
|
|
|
- span: 12,
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请选择分类",
|
|
|
- trigger: "change"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "组织名称",
|
|
|
- prop: "orgName",
|
|
|
- span: 12,
|
|
|
- overHidden: true,
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请输入组织名称",
|
|
|
- trigger: "blur"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "组织ID",
|
|
|
- prop: "orgId",
|
|
|
- span: 12,
|
|
|
- type: "number",
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请输入组织名称",
|
|
|
- trigger: "blur"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "组织编码",
|
|
|
- prop: "orgCode",
|
|
|
- span: 12,
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请输入组织编码",
|
|
|
- trigger: "blur"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "可见角色",
|
|
|
- prop: "visibleRoles",
|
|
|
- type: "select",
|
|
|
- dicData: [
|
|
|
- { label: "管理员", value: "1" },
|
|
|
- { label: "普通用户", value: "2" },
|
|
|
- { label: "访客", value: "3" },
|
|
|
- { label: "VIP用户", value: "4" }
|
|
|
- ],
|
|
|
- slot: true,
|
|
|
- span: 12,
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请选择可见角色",
|
|
|
- trigger: "change"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "状态",
|
|
|
- prop: "status",
|
|
|
- type: "select",
|
|
|
- dicData: [
|
|
|
- { label: "正常", value: 1 },
|
|
|
- { label: "禁用", value: 0 }
|
|
|
- ],
|
|
|
- slot: true,
|
|
|
- addDisplay: false,
|
|
|
- editDisplay: false,
|
|
|
- width: 80
|
|
|
- },
|
|
|
- {
|
|
|
- label: "创建时间",
|
|
|
- prop: "createTime",
|
|
|
- type: "datetime",
|
|
|
- format: "yyyy-MM-dd HH:mm:ss",
|
|
|
- valueFormat: "yyyy-MM-dd HH:mm:ss",
|
|
|
- addDisplay: false,
|
|
|
- editDisplay: false,
|
|
|
- overHidden: true,
|
|
|
- width: 150
|
|
|
- },
|
|
|
- {
|
|
|
- label: "分类名称",
|
|
|
- prop: "categoryName",
|
|
|
- hide: true,
|
|
|
- addDisplay: false,
|
|
|
- editDisplay: false
|
|
|
- },
|
|
|
- {
|
|
|
- label: "备注",
|
|
|
- prop: "remark",
|
|
|
- type: "textarea",
|
|
|
- span: 24,
|
|
|
- minRows: 3,
|
|
|
- hide: true
|
|
|
- },
|
|
|
- {
|
|
|
- label: "公告内容",
|
|
|
- prop: "content",
|
|
|
- component: 'AvueUeditor',
|
|
|
- options: {
|
|
|
- action: '/api/blade-resource/oss/endpoint/put-file',
|
|
|
- props: {
|
|
|
- res: "data",
|
|
|
- url: "link",
|
|
|
- }
|
|
|
- },
|
|
|
- showColumn: false,
|
|
|
- hide: true,
|
|
|
- minRows: 6,
|
|
|
- span: 24,
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- message: "请输入公告内容",
|
|
|
- trigger: "blur"
|
|
|
- }]
|
|
|
- },
|
|
|
- {
|
|
|
- label: "品牌范围",
|
|
|
- prop: "brandScope",
|
|
|
- type: "json",
|
|
|
- hide: true,
|
|
|
- span: 24
|
|
|
- },
|
|
|
- {
|
|
|
- label: "客户黑名单",
|
|
|
- prop: "customerBlacklist",
|
|
|
- type: "json",
|
|
|
- hide: true,
|
|
|
- span: 24
|
|
|
- }
|
|
|
- ]
|
|
|
- },
|
|
|
- /** @type {NoticeItem[]} 表格数据 */
|
|
|
- data: []
|
|
|
- };
|
|
|
- },
|
|
|
- computed: {
|
|
|
- ...mapGetters(["permission", "userInfo"]),
|
|
|
- /**
|
|
|
- * 权限列表
|
|
|
- * @returns {Object} 权限配置对象
|
|
|
- */
|
|
|
- permissionList() {
|
|
|
- return {
|
|
|
- // addBtn: this.vaildData(this.permission.announcement_add, false),
|
|
|
- // viewBtn: this.vaildData(this.permission.announcement_view, false),
|
|
|
- // delBtn: false,
|
|
|
- // editBtn: this.vaildData(this.permission.announcement_edit, false)
|
|
|
- addBtn: true,
|
|
|
- viewBtn: true,
|
|
|
- delBtn: false,
|
|
|
- editBtn: true,
|
|
|
- };
|
|
|
- },
|
|
|
- /**
|
|
|
- * 选中的ID字符串
|
|
|
- * @returns {string} 逗号分隔的ID字符串
|
|
|
- */
|
|
|
- ids() {
|
|
|
- const ids = [];
|
|
|
- this.selectionList.forEach(ele => {
|
|
|
- ids.push(ele.id);
|
|
|
- });
|
|
|
- return ids.join(",");
|
|
|
- }
|
|
|
- },
|
|
|
- created() {
|
|
|
- this.loadCategoryOptions();
|
|
|
- },
|
|
|
- methods: {
|
|
|
- /**
|
|
|
- * 加载分类选项
|
|
|
- * @async
|
|
|
- * @returns {Promise<void>}
|
|
|
- */
|
|
|
- async loadCategoryOptions() {
|
|
|
- try {
|
|
|
- const res = await getCategoryList();
|
|
|
- const categoryData = res.data.data || [];
|
|
|
-
|
|
|
- this.categoryOptions = categoryData
|
|
|
- .filter(item => item.status === 1 && item.isDeleted === 0)
|
|
|
- .map(item => ({
|
|
|
- id: item.id,
|
|
|
- name: item.name,
|
|
|
- value: item.id,
|
|
|
- label: item.name,
|
|
|
- orgId: item.orgId,
|
|
|
- orgName: item.orgName,
|
|
|
- sortOrder: item.sortOrder || 0
|
|
|
- }))
|
|
|
- .sort((a, b) => a.sortOrder - b.sortOrder);
|
|
|
-
|
|
|
- const categoryColumn = this.option.column.find(col => col.prop === 'categoryId');
|
|
|
- if (categoryColumn) {
|
|
|
- categoryColumn.dicData = this.categoryOptions;
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('加载分类选项失败:', error);
|
|
|
- // 使用默认分类
|
|
|
- this.categoryOptions = [
|
|
|
- { id: '1', name: '系统公告', value: '1', label: '系统公告' },
|
|
|
- { id: '2', name: '部门公告', value: '2', label: '部门公告' }
|
|
|
- ];
|
|
|
- const categoryColumn = this.option.column.find(col => col.prop === 'categoryId');
|
|
|
- if (categoryColumn) {
|
|
|
- categoryColumn.dicData = this.categoryOptions;
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- /**
|
|
|
- * 获取可见角色文本
|
|
|
- * @param {string} visibleRoles - 可见角色值
|
|
|
- * @returns {string} 角色文本
|
|
|
- */
|
|
|
- getVisibleRolesText(visibleRoles) {
|
|
|
- const roleMap = {
|
|
|
- '1': '管理员',
|
|
|
- '2': '普通用户',
|
|
|
- '3': '访客',
|
|
|
- '4': 'VIP用户'
|
|
|
- };
|
|
|
- return roleMap[visibleRoles] || '未知角色';
|
|
|
- },
|
|
|
- /**
|
|
|
- * 查看详情
|
|
|
- * @async
|
|
|
- * @returns {Promise<void>}
|
|
|
- */
|
|
|
- async handleDetail() {
|
|
|
- if (this.selectionList.length !== 1) {
|
|
|
- this.$message.warning("请选择一条数据查看详情");
|
|
|
- return;
|
|
|
- }
|
|
|
- try {
|
|
|
- const res = await getAnnouncement(this.selectionList[0].id);
|
|
|
- this.currentDetail = res.data.data;
|
|
|
- this.detailVisible = true;
|
|
|
- } catch (error) {
|
|
|
- console.error('获取详情失败:', error);
|
|
|
- this.$message.error('获取详情失败');
|
|
|
- }
|
|
|
- },
|
|
|
- /**
|
|
|
- * 保存行数据
|
|
|
- * @async
|
|
|
- * @param {NoticeItem} row - 行数据
|
|
|
- * @param {Function} done - 完成回调
|
|
|
- * @param {Function} loading - 加载回调
|
|
|
- * @returns {Promise<void>}
|
|
|
- */
|
|
|
- async rowSave(row, done, loading) {
|
|
|
- try {
|
|
|
- // 设置默认值
|
|
|
- const formData = {
|
|
|
- ...row,
|
|
|
- orgId: this.userInfo.orgId || 1,
|
|
|
- orgCode: this.userInfo.orgCode || 'ORG_0001',
|
|
|
- orgName: this.userInfo.orgName || '默认组织',
|
|
|
- brandScope: row.brandScope || {},
|
|
|
- customerBlacklist: row.customerBlacklist || {},
|
|
|
- remark: row.remark || ''
|
|
|
- };
|
|
|
-
|
|
|
- // 设置分类名称
|
|
|
- const selectedCategory = this.categoryOptions.find(cat => cat.id === row.categoryId);
|
|
|
- if (selectedCategory) {
|
|
|
- formData.categoryName = selectedCategory.name;
|
|
|
- }
|
|
|
-
|
|
|
- await add(formData);
|
|
|
- this.onLoad(this.page);
|
|
|
- this.$message({
|
|
|
- type: "success",
|
|
|
- message: "操作成功!"
|
|
|
- });
|
|
|
- done();
|
|
|
- } catch (error) {
|
|
|
- console.error('保存失败:', error);
|
|
|
- this.$message.error('保存失败');
|
|
|
- loading();
|
|
|
- }
|
|
|
- },
|
|
|
- /**
|
|
|
- * 更新行数据
|
|
|
- * @async
|
|
|
- * @param {NoticeItem} row - 行数据
|
|
|
- * @param {number} index - 行索引
|
|
|
- * @param {Function} done - 完成回调
|
|
|
- * @param {Function} loading - 加载回调
|
|
|
- * @returns {Promise<void>}
|
|
|
- */
|
|
|
- async rowUpdate(row, index, done, loading) {
|
|
|
- try {
|
|
|
- // 设置分类名称
|
|
|
- const selectedCategory = this.categoryOptions.find(cat => cat.id === row.categoryId);
|
|
|
- if (selectedCategory) {
|
|
|
- row.categoryName = selectedCategory.name;
|
|
|
- }
|
|
|
-
|
|
|
- // 确保必要字段存在
|
|
|
- const formData = {
|
|
|
- ...row,
|
|
|
- brandScope: row.brandScope || {},
|
|
|
- customerBlacklist: row.customerBlacklist || {},
|
|
|
- remark: row.remark || ''
|
|
|
- };
|
|
|
-
|
|
|
- await update(formData);
|
|
|
- this.onLoad(this.page);
|
|
|
- this.$message({
|
|
|
- type: "success",
|
|
|
- message: "操作成功!"
|
|
|
- });
|
|
|
- done();
|
|
|
- } catch (error) {
|
|
|
- console.error('更新失败:', error);
|
|
|
- this.$message.error('更新失败');
|
|
|
- loading();
|
|
|
- }
|
|
|
- },
|
|
|
- /**
|
|
|
- * 重置搜索
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- searchReset() {
|
|
|
- this.query = {};
|
|
|
- this.onLoad(this.page);
|
|
|
- },
|
|
|
- /**
|
|
|
- * 搜索变化
|
|
|
- * @param {QueryParams} params - 搜索参数
|
|
|
- * @param {Function} done - 完成回调
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- searchChange(params, done) {
|
|
|
- this.query = params;
|
|
|
- this.page.currentPage = 1;
|
|
|
- this.onLoad(this.page, params);
|
|
|
- done();
|
|
|
- },
|
|
|
- /**
|
|
|
- * 选择变化
|
|
|
- * @param {NoticeItem[]} list - 选中的数据列表
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- selectionChange(list) {
|
|
|
- this.selectionList = list;
|
|
|
- },
|
|
|
- /**
|
|
|
- * 清空选择
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- selectionClear() {
|
|
|
- this.selectionList = [];
|
|
|
- this.$refs.crud.toggleSelection();
|
|
|
- },
|
|
|
- /**
|
|
|
- * 打开前回调
|
|
|
- * @async
|
|
|
- * @param {Function} done - 完成回调
|
|
|
- * @param {string} type - 操作类型
|
|
|
- * @returns {Promise<void>}
|
|
|
- */
|
|
|
- async beforeOpen(done, type) {
|
|
|
- if (["edit", "view"].includes(type)) {
|
|
|
- try {
|
|
|
- const res = await getAnnouncement(this.form.id);
|
|
|
- this.form = res.data.data;
|
|
|
- } catch (error) {
|
|
|
- console.error('获取详情失败:', error);
|
|
|
- }
|
|
|
- } else if (type === "add") {
|
|
|
- // 新增时设置默认值
|
|
|
- this.form = {
|
|
|
- orgId: this.userInfo.orgId || 1,
|
|
|
- orgCode: this.userInfo.orgCode || 'ORG_0001',
|
|
|
- orgName: this.userInfo.orgName || '默认组织',
|
|
|
- visibleRoles: '2', // 默认普通用户
|
|
|
- brandScope: {},
|
|
|
- customerBlacklist: {},
|
|
|
- remark: ''
|
|
|
- };
|
|
|
- }
|
|
|
- done();
|
|
|
- },
|
|
|
- /**
|
|
|
- * 当前页变化
|
|
|
- * @param {number} currentPage - 当前页码
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- currentChange(currentPage) {
|
|
|
- this.page.currentPage = currentPage;
|
|
|
- },
|
|
|
- /**
|
|
|
- * 页大小变化
|
|
|
- * @param {number} pageSize - 页大小
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- sizeChange(pageSize) {
|
|
|
- this.page.pageSize = pageSize;
|
|
|
- },
|
|
|
- /**
|
|
|
- * 刷新变化
|
|
|
- * @returns {void}
|
|
|
- */
|
|
|
- refreshChange() {
|
|
|
- this.onLoad(this.page, this.query);
|
|
|
- },
|
|
|
- /**
|
|
|
- * 加载数据
|
|
|
- * @async
|
|
|
- * @param {PageInfo} page - 分页信息
|
|
|
- * @param {QueryParams} [params={}] - 查询参数
|
|
|
- * @returns {Promise<void>}
|
|
|
- */
|
|
|
- async onLoad(page, params = {}) {
|
|
|
- this.loading = true;
|
|
|
- try {
|
|
|
- const queryParams = {
|
|
|
- ...params,
|
|
|
- ...this.query
|
|
|
- };
|
|
|
-
|
|
|
- const res = await getList(page.currentPage, page.pageSize, queryParams);
|
|
|
- const data = res.data.data;
|
|
|
- this.page.total = data.total;
|
|
|
- this.data = data.records;
|
|
|
- this.loading = false;
|
|
|
- this.selectionClear();
|
|
|
- } catch (error) {
|
|
|
- console.error('加载数据失败:', error);
|
|
|
- this.$message.error('加载数据失败');
|
|
|
- this.loading = false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-};
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
-.detail-content {
|
|
|
- padding: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-.detail-info {
|
|
|
- margin: 20px 0;
|
|
|
- padding: 15px;
|
|
|
- background-color: #f5f5f5;
|
|
|
- border-radius: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-.detail-info p {
|
|
|
- margin: 8px 0;
|
|
|
-}
|
|
|
+<style lang="scss" scoped src="./index.scss">
|
|
|
|
|
|
-.detail-body {
|
|
|
- margin-top: 20px;
|
|
|
- padding: 15px;
|
|
|
- border: 1px solid #e4e7ed;
|
|
|
- border-radius: 4px;
|
|
|
- min-height: 200px;
|
|
|
-}
|
|
|
</style>
|