CzRger před 1 rokem
rodič
revize
97a970910e

+ 1 - 1
src/components/cus/CusFormColumn.vue

@@ -278,7 +278,7 @@ export default defineComponent({
           message: `内容过长,字数需小于等于${props.maxLength}`
         })
       }
-      const doStr = ['input'].includes(props.link) ? '输入' : '选择'
+      const doStr = ['input', 'number'].includes(props.link) ? '输入' : '选择'
       if (props.required !== false && !props.rules.some((v: any) => v.type === 'default')) {
         if (['portOfRegistry', 'residentMooringPoint'].includes(props.link)) {
           r.unshift({

+ 105 - 0
src/views/system/dict-manage/detail.vue

@@ -0,0 +1,105 @@
+<template>
+  <CusDialog
+      title="字典"
+      :show="show"
+      @close="$emit('update:show', false)"
+      @submit="onSubmit"
+      height="300px"
+      :closeConfirm="!isViewCpt"
+  >
+    <div class="__normal-form">
+      <CusForm labelWidth="130px" ref="ref_form" :formView="isViewCpt">
+        <CusFormColumn
+            :span="24"
+            required
+            label="字典显示名称:"
+            v-model:param="cusDetail.p1"/>
+        <CusFormColumn
+            :span="24"
+            required
+            label="字典值内容:"
+            v-model:param="cusDetail.p1"/>
+        <CusFormColumn
+            :span="24"
+            required
+            label="排序:"
+            link="number"
+            :min="0"
+            v-model:param="cusDetail.p1"/>
+      </CusForm>
+    </div>
+  </CusDialog>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick
+} from 'vue'
+import {useStore} from 'vuex'
+import {useRouter, useRoute} from 'vue-router'
+
+export default defineComponent({
+  name: '',
+  components: {},
+  props: {
+    show: {},
+    transfer: <any>{}
+  },
+  setup(props, {emit}) {
+    const store = useStore();
+    const router = useRouter();
+    const route = useRoute();
+    const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
+    const state = reactive({
+      cusDetail: {
+        p1: null,
+        p2: null,
+        p3: null,
+        fileList: [
+          { "url": "http://8.140.240.182:18085/profile/upload/2023/10/23/6b7bf3b4-592a-4e2f-ba92-11923671ce3b.doc", "name": "迁移案例.doc"},],
+        }
+    })
+    watch(() => props.show, (n) => {
+      if (n) {
+        state.cusDetail = {
+          p1: null,
+          p2: null,
+          p3: null,
+          fileList: [],
+        }
+        if (props.transfer.method !== 'add') {
+          state.cusDetail.p1 = props.transfer.detail.p1
+          state.cusDetail.fileList = props.transfer.detail.fileList
+        }
+        nextTick(() => {
+          ref_form.value.reset()
+        })
+      }
+    })
+    const ref_form = ref()
+    const isViewCpt = computed(() => {
+      return props.transfer.method === 'view'
+    })
+    const onSubmit = () => {
+    }
+    return {
+      ...toRefs(state),
+      onSubmit,
+      isViewCpt,
+      ref_form
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+</style>

binární
src/views/system/dict-manage/dict_bg-active.png


binární
src/views/system/dict-manage/dict_bg.png


+ 291 - 3
src/views/system/dict-manage/index.vue

@@ -1,4 +1,84 @@
 <template>
+  <div class="__normal-page">
+    <div class="__normal-tree">
+      <div class="tree-filter">
+        <CusFormColumn
+            :span="24"
+            v-model:param="treeFilter">
+          <template #suffix>
+            <SvgIcon name="search"/>
+          </template>
+        </CusFormColumn>
+      </div>
+      <div class="tree-content">
+        <template v-for="p in dictTree">
+          <div class="tree-parent __hover" :class="{active: p.expend}" @click="p.expend = !p.expend">{{p.name}}</div>
+          <template v-if="p.expend">
+            <template v-for="s in p.children.filter(v => v.name.includes(treeFilter))">
+              <div class="tree-son __hover" :class="{active: queryForm.dictId === s.value}" @click="queryForm.dictId = s.value">{{s.name}}</div>
+            </template>
+          </template>
+        </template>
+      </div>
+    </div>
+    <div class="__normal-content">
+      <CusContent
+          v-model:tableHead="tableHead"
+          @handleReset="handleReset"
+          @handleSearch="onSearch"
+      >
+        <template #fieldOut>
+          <CusForm labelWidth="120px" @handleEnter="onSearch">
+            <CusFormColumn
+                :span="8"
+                label="字典显示名称:"
+                v-model:param="queryForm.shipId"/>
+            <CusFormColumn
+                :span="8"
+                label="字典值内容:"
+                v-model:param="queryForm.shipId"/>
+            <CusSearchButtons
+                @handleReset="handleReset"
+                @handleSearch="onSearch"
+            />
+          </CusForm>
+        </template>
+        <template #buttons>
+          <div class="__cus-button_submit __hover" @click="onAdd">
+            <SvgIcon name="add" size="16"/>新增
+          </div>
+        </template>
+        <template #table>
+          <CusTable
+              v-loading="loading"
+              ref="ref_cusTable"
+              :tableData="queryResult.tableData"
+              :tableHead="tableHead"
+              :total="queryResult.total"
+              :page="queryPage.pageNum"
+              :pageSize="queryPage.pageSize"
+              @handlePage="handlePage"
+              @handleSort="handleSort"
+          >
+            <template #do-column-value="{ scope }">
+              <div class="__cus-table_do">
+                <div class="__cus-table_do-green __hover" @click="onView(scope.row)">
+                  <SvgIcon name="view" size="16"/>查看
+                </div>
+                <div class="__cus-table_do-blue __hover" @click="onEdit(scope.row)">
+                  <SvgIcon name="edit" size="16"/>编辑
+                </div>
+                <div class="__cus-table_do-red __hover">
+                  <SvgIcon name="del" size="16"/>删除
+                </div>
+              </div>
+            </template>
+          </CusTable>
+        </template>
+      </CusContent>
+    </div>
+    <DetailCom v-model:show="showDetail" :transfer="transfer"/>
+  </div>
 </template>
 
 <script lang="ts">
@@ -16,22 +96,230 @@ import {
 } from 'vue'
 import {useStore} from 'vuex'
 import {useRouter, useRoute} from 'vue-router'
+import DetailCom from './detail.vue'
 
 export default defineComponent({
   name: '',
-  components: {},
+  components: {
+    DetailCom
+  },
   setup(props, {emit}) {
     const store = useStore();
     const router = useRouter();
     const route = useRoute();
     const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
-    const state = reactive({})
+    const state = reactive({
+      //  加载中
+      loading: false,
+      //  查询分页参数
+      queryPage: {
+        pageNum: 1,
+        pageSize: 10
+      },
+      //  查询结果
+      queryResult: {
+        total: 0,
+        tableData: []
+      },
+      //  查询表单参数
+      queryForm: <any>{},
+      //  查询表单参数备份
+      back_queryForm: {},
+      //  查询表格排序
+      querySort: {},
+      //  表格表头
+      tableHead: [
+        {value: "p1", label: "字典显示名称", show: true},
+        {value: "p1", label: "字典值内容", show: true},
+        {value: "p1", label: "排序", show: true},
+        {value: "p1", label: "更新时间", show: true},
+        {value: "do", label: "操作", show: true, width: 260},
+      ],
+      showDetail: false,
+      transfer: {},
+      treeFilter: '',
+      dictTree: [
+        {
+          name: '席位管理',
+          expend: true,
+          children: [
+            {name: '值班厅领导', value: 1},
+            {name: '总值班', value: 2},
+            {name: '带班领导', value: 3},
+            {name: '值班长', value: 4},
+            {name: '值班员', value: 5},
+          ]
+        },
+        {
+          name: 'xxx管理',
+          expend: false,
+          children: [
+          ]
+        },
+      ]
+    });
+    const ref_cusTable = ref()
+    //  获取字典
+    const initDictionary = () => {
+    }
+    //  查询分页参数改变处理方法
+    const handlePage = ({page, pageSize}: any) => {
+      state.queryPage.pageNum = page
+      state.queryPage.pageSize = pageSize
+      handleSearch(page, pageSize)
+    }
+    //  查询排序参数改变处理方法
+    const handleSort = ({key, value}: any) => {
+      state.querySort = key ? {key: value} : {}
+      handleSearch()
+    }
+    //  重置查询表单方法
+    const handleReset = () => {
+      state.queryForm = {}
+      state.back_queryForm = state.queryForm
+      handleSearch()
+    }
+    //  查询方法
+    const handleSearch = (page = 1, pageSize = 10) => {
+      //  添加分页参数
+      const queryParams: any = {
+        pageNum: page,
+        pageSize: pageSize,
+        sort: {},
+        text: ''
+      }
+      //  添加排序参数
+      for (const [k, v] of Object.entries(state.querySort)) {
+        that.$util.isValue(v) ? (queryParams.sort[k] = v) : null;
+      }
+      //  添加表单参数
+      for (const [k, v] of Object.entries(state.back_queryForm)) {
+        that.$util.isValue(v) ? (queryParams[k] = v) : null;
+      }
+      //  添加复合查询参数
+      state.loading = true
+
+      // mock
+      const arr: any = []
+      for (let i = 0; i < 77; i++) {
+        arr.push({
+          p1: '阿三顶顶顶顶顶顶顶顶顶顶顶顶顶' + i,
+          fileList: [
+            { "url": "http://8.140.240.182:18085/profile/upload/2023/10/23/6b7bf3b4-592a-4e2f-ba92-11923671ce3b.doc", "name": "迁移案例.doc"},
+          ],
+        })
+      }
+      state.queryResult.tableData = arr
+      state.queryResult.total = arr.length
+      state.loading = false
+      // that.$api.patrolBoatList(that.$util.formatGetParam(queryParams)).then((res: { code: number; rows: never[]; total: number; }) => {
+      //   if (res.code === 200) {
+      //     state.queryResult.tableData = res.rows
+      //     state.queryResult.total = res.total
+      //   }
+      //   setTimeout(() => {
+      //     state.loading = false
+      //   }, 1000)
+      // }).catch(() => {
+      //   setTimeout(() => {
+      //     state.loading = false
+      //   }, 1000)
+      // })
+    }
+    //  点击查询按钮后
+    const onSearch = () => {
+      ref_cusTable.value.resetFilter()
+      state.back_queryForm = state.queryForm
+      state.queryPage.pageNum = 1
+      handleSearch()
+    }
+    const onAdd = () => {
+      state.transfer = {
+        method: 'add',
+      }
+      state.showDetail = true
+    }
+    const onEdit = (val) => {
+      state.transfer = {
+        method: 'edit',
+        detail: val
+      }
+      state.showDetail = true
+    }
+    const onView = (val) => {
+      state.transfer = {
+        method: 'view',
+        detail: val
+      }
+      state.showDetail = true
+    }
+    onMounted(() => {
+      state.back_queryForm = JSON.parse(JSON.stringify(state.queryForm))
+      initDictionary()
+      handleSearch()
+    })
     return {
-      ...toRefs(state)
+      ref_cusTable,
+      ...toRefs(state),
+      handleSearch,
+      handlePage,
+      handleSort,
+      handleReset,
+      onSearch,
+      onAdd,
+      onEdit,
+      onView,
     }
   },
 })
 </script>
 
 <style scoped lang="scss">
+.__normal-tree {
+  width: 224px;
+  margin-right: 24px;
+  padding-top: 40px;
+  display: flex;
+  flex-direction: column;
+  box-sizing: border-box;
+  .tree-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    .tree-parent {
+      background-image: url("./dict_bg.png");
+      width: 188px;
+      height: 34px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 18px;
+      font-family: PingFang SC-Medium, PingFang SC;
+      font-weight: 500;
+      color: rgba(46,184,255,0.6);
+      margin-bottom: 10px;
+      &.active {
+        background-image: url("./dict_bg-active.png");
+        width: 196px;
+        height: 54px;
+        color: #3EFFBB;
+        text-shadow: 0px 0px 4px rgba(62,255,187,0.1);
+      }
+    }
+    .tree-son {
+      font-size: 18px;
+      font-family: PingFang SC-Medium, PingFang SC;
+      font-weight: 500;
+      color: rgba(255,255,255,0.6);
+      text-shadow: 0px 0px 4px rgba(62,255,187,0.1);
+      margin-bottom: 10px;
+      align-self: flex-start;
+      padding-left: 76px;
+      &.active {
+        color: #3EFFBB;
+      }
+    }
+  }
+}
 </style>