guhongwei 2 년 전
부모
커밋
d74c6bff21
6개의 변경된 파일256개의 추가작업 그리고 25개의 파일을 삭제
  1. 1 1
      .env.development
  2. 1 0
      .env.production
  3. 3 1
      src/main.ts
  4. 214 0
      src/views/c-table.vue
  5. 32 23
      src/views/homeIndex.vue
  6. 5 0
      vite.config.ts

+ 1 - 1
.env.development

@@ -2,4 +2,4 @@ VITE_APP_HOST="http://basic.waityou24.cn"
 BASE_URL='web'
 VITE_OUT_DIR="build"
 VITE_BASE_URL=""
-g
+VITE_APP_PAGE_SIZE="10"

+ 1 - 0
.env.production

@@ -2,3 +2,4 @@ VITE_APP_HOST="http://basic.waityou24.cn"
 BASE_URL='web'
 VITE_OUT_DIR="build"
 VITE_BASE_URL=""
+VITE_APP_PAGE_SIZE="10"

+ 3 - 1
src/main.ts

@@ -9,6 +9,7 @@ import 'animate.css'
 // element
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'
+import locale from 'element-plus/lib/locale/lang/zh-cn'
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 
 // moment
@@ -21,7 +22,7 @@ import frameComponents from '@/components/index'
 const app = createApp(App)
 app.use(createPinia())
 app.use(router)
-app.use(ElementPlus, {})
+app.use(ElementPlus, { locale })
 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
   app.component(key, component)
 }
@@ -30,5 +31,6 @@ app.config.globalProperties.$moment = moment
 for (const componentItme in frameComponents) {
   app.component(componentItme, frameComponents[componentItme])
 }
+app.config.globalProperties.$limit = parseInt(import.meta.env.VITE_APP_PAGE_SIZE) || 10
 
 app.mount('#app')

+ 214 - 0
src/views/c-table.vue

@@ -0,0 +1,214 @@
+<template>
+  <el-table :data="list" border stripe @selection-change="toSelect">
+    <el-table-column type="selection" width="55" v-if="select"> </el-table-column>
+    <template v-for="(item, index) in fields">
+      <template v-if="item.custom">
+        <el-table-column :key="index" :label="item.label" v-bind="item.options" align="center" :show-overflow-tooltip="item.showTip || true">
+          <template v-slot="{ row }">
+            <slot :name="item.model" v-bind="{ item, row }"></slot>
+          </template>
+        </el-table-column>
+      </template>
+      <template v-else>
+        <el-table-column
+          :key="index"
+          :label="item.label"
+          :prop="item.model"
+          :formatter="toFormatter"
+          v-bind="item.options"
+          :sortable="true"
+          align="center"
+          :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
+        ></el-table-column>
+      </template>
+    </template>
+    <template v-if="opera.length > 0">
+      <el-table-column label="操作" fixed="right" width="110" align="center">
+        <template v-slot="{ row, $index }">
+          <template v-for="(item, index) in opera">
+            <template v-if="display(item, row)">
+              <template v-if="vOpera">
+                <el-link
+                  :key="`${item.model}-column-${index}`"
+                  :type="item.type || 'primary'"
+                  size="small"
+                  :underline="false"
+                  class="link"
+                  v-opera="item.method"
+                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
+                >
+                  {{ item.label }}
+                </el-link>
+              </template>
+              <template v-else>
+                <el-link
+                  :key="`${item.model}-column-${index}`"
+                  :type="item.type || 'primary'"
+                  size="small"
+                  :underline="false"
+                  class="link"
+                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
+                >
+                  {{ item.label }}
+                </el-link>
+              </template>
+            </template>
+          </template>
+        </template>
+      </el-table-column>
+    </template>
+  </el-table>
+  <el-row justify="end" class="page" v-if="usePage">
+    <el-pagination
+      background
+      layout="sizes,total, prev, pager, next"
+      :page-sizes="[10, 20, 50, 100, 200]"
+      :total="total"
+      :page-size="limit"
+      v-model:current-page="currentPage"
+      @current-change="changePage"
+      @size-change="sizeChange"
+    >
+    </el-pagination>
+  </el-row>
+</template>
+
+<script setup lang="ts">
+// 基础
+import _ from 'lodash'
+import type { Ref } from 'vue'
+import { onMounted, toRefs, getCurrentInstance, ref } from 'vue'
+import { ElMessageBox } from 'element-plus'
+const { proxy } = getCurrentInstance() as any
+const emit = defineEmits(['toSelect', 'query'])
+
+// 参数
+interface fieldsItem {
+  // 是否自定义
+  custom: string
+  // 名称
+  label: string
+  // 绑定键值
+  model: string
+  // 其他
+  options: string
+  // 是否超出隐藏
+  showTip: boolean
+}
+interface operaItem {
+  // 名称
+  label: string
+  model: string
+  // 绑定键值
+  method: string
+  // 颜色
+  type: string
+  // 是否开启弹框
+  confirm: boolean
+  // 是否自定义文字说明
+  confirmWord: string
+  // 简短文字
+  methodZh: string
+}
+interface dataItem {
+  _id?: string
+}
+
+const props = defineProps({
+  // 列表配置
+  fields: { type: Array<fieldsItem>, required: true },
+  // 操作配置
+  opera: { type: Array<operaItem>, required: true },
+  // 列表数据
+  list: { type: Array<dataItem>, required: true },
+  // 是否开启多选
+  select: { type: Boolean, default: true },
+  // selected: { type: Array, default: () => [] },
+  vOpera: { type: Boolean, default: false },
+  // 分页
+  usePage: { type: Boolean, default: true },
+  total: { type: Number, default: 0 }
+})
+const { fields } = toRefs(props)
+const { opera } = toRefs(props)
+const { list } = toRefs(props)
+const { select } = toRefs(props)
+// const { selected } = toRefs(props);
+const { vOpera } = toRefs(props)
+const { usePage } = toRefs(props)
+const { total } = toRefs(props)
+
+let limit: number = proxy.$limit
+let currentPage: Ref<number> = ref(1)
+// 请求
+onMounted(async () => {})
+// 多选
+const toSelect = (val: Array<[]>) => {
+  emit(`toSelect`, val)
+}
+// 格式化内容
+const toFormatter = (row: any, column: { property: string }, cellValue: string) => {
+  let this_fields = fields.value.filter((fil) => fil.model === column.property)
+  if (this_fields.length > 0) {
+    let format: any = _.get(this_fields[0], `format`, false)
+    if (format) {
+      let res
+      if (_.isFunction(format)) {
+        res = format(cellValue)
+      } else {
+        res = toFormat({ model: this_fields[0].model, value: cellValue })
+      }
+      return res
+    } else {
+      return cellValue
+    }
+  }
+}
+const toFormat = (e: { model: string; value: string }) => {
+  console.log(e)
+}
+// 过滤
+const display = (item: operaItem, row: any) => {
+  let display: any = _.get(item, `display`, true)
+  if (display === true) return true
+  else {
+    let res = display(row)
+    return res
+  }
+}
+// 操作
+const handleOpera = (data: string, method: any, confirm = false, methodZh: string, label: string, index: string, confirmWord: string) => {
+  let self = true
+  if (_.isFunction(methodZh)) methodZh = methodZh(data)
+  else if (!_.isString(methodZh)) {
+    methodZh = label
+    self = false
+  }
+  if (confirm) {
+    let word = self ? methodZh : `您确认${methodZh}该数据?`
+    if (confirmWord) word = confirmWord
+    ElMessageBox.confirm(word, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
+      .then(() => {
+        emit(method, data, index)
+      })
+      .catch(() => {})
+  } else emit(method, data, index)
+}
+// 分页
+const changePage = (page: number = currentPage.value) => {
+  emit('query', { skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits: number) => {
+  limit = limits
+  currentPage.value = 1
+  emit('query', { skip: 0, limit: limit })
+}
+</script>
+<style scoped lang="less">
+.link {
+  padding: 0 5px 0 0;
+}
+.page {
+  margin: 10px 0 0 0;
+}
+</style>

+ 32 - 23
src/views/homeIndex.vue

@@ -2,42 +2,41 @@
   <el-row>
     <el-col :span="24" class="main animate__animated animate__backInRight">
       <el-col :span="24" class="one">
-        <el-table :data="list" border stripe style="width: 100%" @selection-change="toSelect">
-          <el-table-column type="selection" width="55" />
-          <el-table-column type="index" label="序号" align="center" width="80" />
-          <el-table-column prop="dict_label" label="字典标签" align="center" show-overflow-tooltip sortable />
-          <el-table-column prop="dict_value" label="字典键值" align="center" show-overflow-tooltip sortable />
-          <el-table-column prop="dict_sort" label="字典排序" align="center" show-overflow-tooltip sortable />
-          <el-table-column prop="status" label="状态" align="center" show-overflow-tooltip sortable />
-          <el-table-column fixed="right" label="操作" width="100" align="center">
-            <template #default>
-              <el-button link type="primary" size="small">修改</el-button>
-              <el-button link type="danger" size="small">删除</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-      </el-col>
-      <el-col :span="24" class="two">
-        <cButton></cButton>
+        <cTable :fields="fields" :opera="opera" :list="list" :total="total" @query="search" @toSelect="toSelect" @edit="toEdit" @del="toDel">
+          <template #status="{ row, item }">{{ row[item.model] }}</template>
+        </cTable>
       </el-col>
     </el-col>
   </el-row>
 </template>
 
 <script setup lang="ts">
+// 组件
+import cTable from './c-table.vue'
 // 基础
 import type { Ref } from 'vue'
 // reactive, ref, onMounted
-import { onMounted, ref } from 'vue'
+import { onMounted, ref, getCurrentInstance } from 'vue'
 // 接口
-import { DictDataStore } from '@common/src/stores/users/sysdictdata'
+import { YearreportStore } from '@common/src/stores/studio/studios/yearreport'
 import type { IQueryResult } from '@/util/types.util'
-const testAxios = DictDataStore()
+const testAxios = YearreportStore()
+const { proxy } = getCurrentInstance() as any
 // 分页数据
 const skip = 0
-const limit = 10
+let limit: number = proxy.$limit
 const list: Ref<any[]> = ref([])
 const total: Ref<number> = ref(0)
+const fields: Ref<any[]> = ref([
+  { label: '序号', options: { type: 'index', width: '80' } },
+  { label: '依托单位名称', model: 'company', isSearch: true },
+  { label: '姓名', model: 'name', isSearch: true },
+  { label: '状态', model: 'status', isSearch: true }
+])
+const opera: Ref<any[]> = ref([
+  { label: '修改', method: 'edit' },
+  { label: '删除', method: 'del', confirm: true, type: 'danger', display: (i) => i.status == '1' }
+])
 // 请求
 onMounted(async () => {
   await search({ skip, limit })
@@ -46,7 +45,6 @@ const search = async (e: { skip: number; limit: number }) => {
   const info = { skip: e.skip, limit: e.limit }
   const res: IQueryResult = await testAxios.query(info)
   if (res.errcode == '0') {
-    console.log(res.data)
     list.value = res.data as any[]
     total.value = res.total
   }
@@ -56,5 +54,16 @@ const toSelect = (val: Array<[]>) => {
   console.log('多选')
   console.log(val)
 }
+
+const toEdit = (data) => {
+  console.log(data._id)
+}
+const toDel = (data) => {
+  console.log(data._id)
+}
 </script>
-<style scoped lang="less"></style>
+<style scoped lang="less">
+.main {
+  padding: 4%;
+}
+</style>

+ 5 - 0
vite.config.ts

@@ -23,6 +23,11 @@ export default defineConfig(({ mode }) => {
           target: 'http://basic.waityou24.cn',
           changeOrigin: true,
           ws: false
+        },
+        '/studioadmin/api': {
+          target: 'http://192.168.1.113:16001',
+          changeOrigin: true,
+          ws: false
         }
       }
     },