Browse Source

系统设置帮助中心配置

yujinwen 3 months ago
parent
commit
79c630e7f1

+ 7 - 0
pnpm-lock.yaml

@@ -19,6 +19,9 @@ dependencies:
   highcharts:
     specifier: ^11.4.1
     version: 11.4.3
+  js-md5:
+    specifier: ^0.8.3
+    version: 0.8.3
   lodash:
     specifier: ^4.17.21
     version: 4.17.21
@@ -2437,6 +2440,10 @@ packages:
     resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
     dev: true
 
+  /js-md5@0.8.3:
+    resolution: {integrity: sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==}
+    dev: false
+
   /js-tokens@4.0.0:
     resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
     dev: true

+ 4 - 0
src/api/system/helpCenter.js

@@ -21,6 +21,10 @@ export default{
   classifyDelete:params=>{
     return get('/help_doc/classify/delete',params)
   },
+  // 分类权限
+  classifyAuth:params=>{
+    return post('/help_doc/classify/visible/edit',params)
+  },
 
   // 获取文章列表
   getDocmentList:params=>{

+ 8 - 0
src/router/modules/system.js

@@ -69,6 +69,14 @@ export default[
           title:'查看文章'
         },
       },
+      {
+        path:'helpCenter/classify',
+        name:'SystemHelpCenterClassify',
+        component:()=>import('@/views/system/helpCenter/classify/Index.vue'),
+        meta:{
+          title:'分类管理'
+        },
+      },
     ]
   }
 ]

+ 1 - 1
src/views/system/helpCenter/Index.vue

@@ -90,7 +90,7 @@ async function handleDocPublishChange(row){
   <div class="bg-white help-center-page">
     <div class="flex top-wrap">
       <t-button theme="primary" @click="$router.push('/system/helpCenter/addDoc')">添加文章</t-button>
-      <t-button theme="primary">分类管理</t-button>
+      <t-button theme="primary" @click="$router.push('/system/helpCenter/classify')">分类管理</t-button>
       <t-cascader 
         v-model="classifyValue" 
         :options="classifyOpts"

+ 187 - 0
src/views/system/helpCenter/classify/Index.vue

@@ -0,0 +1,187 @@
+
+<script setup>
+import { SearchIcon } from 'tdesign-icons-vue-next';
+import {apiSystemHelpCenter} from '@/api/system'
+import { useTemplateRef } from 'vue';
+import EditClassify from './components/EditClassify.vue'
+import AuthSet from './components/AuthSet.vue'
+
+const tableCol=[
+  { align: 'center', colKey: 'fisrt', title: '一级分类' },
+  { align: 'center', colKey: 'second', title: '二级分类' },
+  { align: 'center', colKey: 'third', title: '三级分类' },
+  {
+    align: 'center',
+    colKey: 'opt',
+    title: '操作',
+  },
+]
+const keyword=ref('')
+const classifyData=ref([])
+const TwoLevelNodes=ref([])
+const tableIns=useTemplateRef('tableIns')
+const defaultExpandedTreeNodes=ref([])
+async function getClassifyData(){
+  classifyData.value=[]
+  defaultExpandedTreeNodes.value=[]
+  const res=await apiSystemHelpCenter.classifyList({
+    KeyWord:keyword.value
+  })
+  if(res.Ret!==200) return
+  classifyData.value=res.Data.AllNodes||[]
+  TwoLevelNodes.value=res.Data.TwoLevelNodes||[]
+
+  classifyData.value.forEach(item => {
+    defaultExpandedTreeNodes.value.push(item.ClassifyId)
+  });
+}
+getClassifyData()
+
+async function handleSort({newData,current,target,targetIndex}){
+  console.log(newData,current,target,targetIndex);
+  const params={
+    ClassifyId:current.ClassifyId,
+    ParentClassifyId:target.ParentId,
+    PrevClassifyId:0,
+    NextClassifyId:0,
+  }
+  if(current.Level===1){
+    let arr=newData.filter(i=>i.Level===1)
+    const index=arr.findIndex(i=>i.ClassifyId===current.ClassifyId)
+    params.NextClassifyId=index<arr.length-1?arr[index+1].ClassifyId:0
+    params.PrevClassifyId=index===0?0:arr[index-1].ClassifyId
+  }else if(current.Level===2){
+    let arr=newData.filter(i=>i.Level===2)
+    const index=arr.findIndex(i=>i.ClassifyId===current.ClassifyId)
+    const preObj=index>0?arr[index-1]:null
+    const nextObj=index<arr.length-1?arr[index+1]:null
+    if(preObj&&preObj.ParentId===params.ParentClassifyId){
+      params.PrevClassifyId=preObj.ClassifyId
+    }
+    if(nextObj&&nextObj.ParentId===params.ParentClassifyId){
+      params.NextClassifyId=nextObj.ClassifyId
+    }
+  }else if(current.Level===3){
+    let arr=newData.filter(i=>i.Level===3)
+    const index=arr.findIndex(i=>i.ClassifyId===current.ClassifyId)
+    const preObj=index>0?arr[index-1]:null
+    const nextObj=index<arr.length-1?arr[index+1]:null
+    if(preObj&&preObj.ParentId===params.ParentClassifyId){
+      params.PrevClassifyId=preObj.ClassifyId
+    }
+    if(nextObj&&nextObj.ParentId===params.ParentClassifyId){
+      params.NextClassifyId=nextObj.ClassifyId
+    }
+  }
+  const res=await apiSystemHelpCenter.classifyMove(params)
+  getClassifyData()
+  if(res.Ret===200){
+    MessagePlugin.success('移动分类成功');
+  }
+}
+function handleAbnormalDragSort(e){
+  if (e.code === 1001) {
+    MessagePlugin.warning('不同层级的元素,不允许调整顺序');
+  }
+}
+
+async function handleDel(item){
+  await $confirmDialog({
+    body:'是否确认删除?'
+  })
+  const res=await apiSystemHelpCenter.classifyDelete({
+    ClassifyId:item.ClassifyId
+  })
+  if(res.Ret!==200) return
+  MessagePlugin.success('删除分类成功')
+  getClassifyData()
+}
+
+const editClassifyData=ref(null)
+const showEditClassify=ref(false)
+function handleShowClassify(item){
+  editClassifyData.value=item
+  showEditClassify.value=true
+}
+
+const showAuthSetClassify=ref(false)
+function handleShowAuthSetClassify(item){
+  editClassifyData.value=item
+  showAuthSetClassify.value=true
+}
+
+</script>
+
+<template>
+  <div class="bg-white classify-page">
+    <div class="flex top-box">
+      <t-button theme="primary" @click="handleShowClassify(null)">添加分类</t-button>
+      <t-input
+        style="width: 310px;"
+        placeholder="分类名称"
+        v-model="keyword"
+        clearable
+        @change="getClassifyData"
+      >
+        <template #prefixIcon><SearchIcon /></template>
+      </t-input>
+    </div>
+    <t-enhanced-table
+      ref="tableIns"
+      :defaultExpandedTreeNodes="defaultExpandedTreeNodes"
+      v-model:expandedTreeNodes="defaultExpandedTreeNodes"
+      row-key="ClassifyId"
+      drag-sort="row"
+      :data="classifyData"
+      :columns="tableCol"
+      :tree="{
+        childrenKey:'Children',
+        treeNodeColumnIndex: 0,
+      }"
+      bordered
+      show-header
+      @drag-sort="handleSort"
+      @abnormal-drag-sort="handleAbnormalDragSort"
+    >
+      <template #fisrt="{ row }">
+        <span v-if="row.Level===1">{{row.ClassifyName}}</span>
+      </template>
+      <template #second="{ row }">
+        <span v-if="row.Level===2">{{row.ClassifyName}}</span>
+      </template>
+      <template #third="{ row }">
+        <span v-if="row.Level===3">{{row.ClassifyName}}</span>
+      </template>
+      <template #opt="{ row }">
+        <t-button size="small" variant="text" theme="primary" @click="handleShowAuthSetClassify(row)">权限配置</t-button>
+        <t-button size="small" variant="text" theme="primary" @click="handleShowClassify(row)">编辑</t-button>
+        <t-button size="small" variant="text" theme="danger" @click="handleDel(row)">删除</t-button>
+      </template>
+    </t-enhanced-table>
+  </div>
+  <!-- 新增编辑分类 -->
+  <EditClassify 
+    v-model:show="showEditClassify"
+    :options="TwoLevelNodes"
+    :data="editClassifyData"
+    @change="getClassifyData"
+  />
+  <!-- 设置权限 -->
+  <AuthSet 
+    v-model:show="showAuthSetClassify"
+    :data="editClassifyData"
+    @change="getClassifyData"
+  />
+</template>
+
+<style lang="scss" scoped>
+.classify-page{
+  padding: 30px;
+  border: 1px solid var(--border-color);
+  min-height: calc(100vh - 160px);
+  .top-box{
+    justify-content: space-between;
+    margin-bottom: 20px;
+  }
+}
+</style>

+ 86 - 0
src/views/system/helpCenter/classify/components/AuthSet.vue

@@ -0,0 +1,86 @@
+<script setup>
+import { watch } from "vue";
+import {apiSystemHelpCenter} from '@/api/system'
+
+
+const show = defineModel('show', { type: Boolean, default: false })
+const emits=defineEmits(['change'])
+const props=defineProps({
+  data:{
+    type:[null,Object],
+    default:null
+  },
+})
+
+const formData=reactive({
+  id:'',
+})
+
+async function handleSave(){
+  const res=await apiSystemHelpCenter.classifyAuth({
+    HelpDocClassifyId:props.data.ClassifyId,
+    VisibleBusinessIds:formData.id?formData.id.join(','):'',
+  })
+  if(res.Ret!=200) return
+  show.value=false
+  MessagePlugin.success('保存成功')
+  emits('change')
+}
+
+
+watch(
+  ()=>show.value,
+  (n)=>{
+    if(n&&props.data){
+      const arr=props.data.VisibleBusinessIds?props.data.VisibleBusinessIds.split(','):[]
+      formData.id=arr.map(i=>Number(i))
+    }
+  }
+)
+
+</script>
+
+<template>
+  <t-dialog
+    v-model:visible="show"
+    header="设置权限"
+    draggable
+    attach="body"
+    top="50px"
+    width="600px"
+    :cancelBtn="null"
+    :confirmBtn="null"
+    class="edit-user-wrap"
+  >
+    <t-form
+      :data="formData"
+      labelAlign="left"
+    >
+      <t-form-item label="可见权限" name="parent">
+        <select-business 
+          v-model="formData.id"
+          multiple
+          placeholder="请选择商家"
+        />
+      </t-form-item>
+    </t-form>
+    <template #footer>
+      <div class="bottom-btn">
+        <t-button theme="default" @click="show=false">取消</t-button>
+        <t-button type="submit" @click="handleSave">确定</t-button>
+      </div>
+    </template>
+  </t-dialog>
+</template>
+
+<style lang="scss" scoped>
+.edit-user-wrap{
+  .bottom-btn{
+    margin-top: 60px;
+    text-align: center;
+    .t-button{
+      width: 120px;
+    }
+  }
+}
+</style>

+ 125 - 0
src/views/system/helpCenter/classify/components/EditClassify.vue

@@ -0,0 +1,125 @@
+<script setup>
+import { useTemplateRef, watch } from "vue";
+import {apiSystemHelpCenter} from '@/api/system'
+
+
+const show = defineModel('show', { type: Boolean, default: false })
+const emits=defineEmits(['change'])
+const props=defineProps({
+  data:{
+    type:[null,Object],
+    default:null
+  },
+  options:{
+    type:Array,
+    default:()=>[]
+  }
+})
+
+const FORM_RULES = { 
+  name: [{ required: true, message: '请输入分类名称' }],
+};
+
+const formIns=useTemplateRef('formIns')
+const formData=reactive({
+  name:'',
+  parent:'',
+})
+
+let parentLevel=1
+function handleSelectParentChange(value,context){
+  parentLevel=context.node.data.Level
+}
+
+async function handleSave(){
+  const validRes=await formIns.value.validate()
+  if(validRes!==true) return
+  const params={
+    ParentId:formData.parent||0,
+    HelpDocClassifyName:formData.name,
+    Level:parentLevel-1,
+  }
+  const res=props.data?await apiSystemHelpCenter.classifyEdit({
+    HelpDocClassifyId:props.data.ClassifyId,
+    HelpDocClassifyName:formData.name,
+  }):await apiSystemHelpCenter.classifyAdd(params)
+  if(res.Ret!=200) return
+  show.value=false
+  MessagePlugin.success(props.data?'保存成功':'新增成功')
+  emits('change')
+}
+
+
+watch(
+  ()=>show.value,
+  (n)=>{
+    if(!n){
+      formIns.value.reset()
+      return
+    }
+    if(n&&props.data){
+      formData.name=props.data.ClassifyName
+      formData.parent=props.data.ParentId||''
+    }
+  }
+)
+
+</script>
+
+<template>
+  <t-dialog
+    v-model:visible="show"
+    :header="props.data?'编辑分类':'添加分类'"
+    draggable
+    attach="body"
+    top="50px"
+    width="600px"
+    :cancelBtn="null"
+    :confirmBtn="null"
+    class="edit-user-wrap"
+  >
+    <t-form
+      ref="formIns"
+      :rules="FORM_RULES"
+      :data="formData"
+      labelAlign="top"
+    >
+      <t-form-item label="上级目录" name="parent">
+        <t-cascader 
+          v-model="formData.parent" 
+          :options="props.options" 
+          check-strictly
+          :keys="{
+            value:'ClassifyId',
+            label:'ClassifyName',
+            children:'Children'
+          }"
+          :disabled="props.data?true:false"
+          placeholder="请选择上级目录(不选默认添加的是一级分类)"
+          @change="handleSelectParentChange"
+        />
+      </t-form-item>
+      <t-form-item label="分类名称" name="name">
+        <t-input v-model="formData.name" placeholder="请输入分类名称"></t-input>
+      </t-form-item>
+    </t-form>
+    <template #footer>
+      <div class="bottom-btn">
+        <t-button theme="default" @click="show=false">取消</t-button>
+        <t-button type="submit" @click="handleSave">确定</t-button>
+      </div>
+    </template>
+  </t-dialog>
+</template>
+
+<style lang="scss" scoped>
+.edit-user-wrap{
+  .bottom-btn{
+    margin-top: 60px;
+    text-align: center;
+    .t-button{
+      width: 120px;
+    }
+  }
+}
+</style>