Explorar o código

计算菜品总量,绑定用户与管理员

lrf hai 1 ano
pai
achega
ce505fa0ce

+ 2 - 1
.gitignore

@@ -14,7 +14,8 @@ dist
 dist-ssr
 coverage
 *.local
-
+stAdmin/
+stAdmin.zip
 /cypress/videos/
 /cypress/screenshots/
 

+ 6 - 1
src/stores/core/order.ts

@@ -33,11 +33,16 @@ export const OrderStore = defineStore('order', () => {
     const res = await axios.$delete(`${api.url}/${payload}`);
     return res;
   };
+  const computedMeal = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$get(`${api.url}/computedMeal/${payload}`);
+    return res;
+  };
   return {
     query,
     fetch,
     create,
     update,
-    del
+    del,
+    computedMeal
   };
 });

+ 78 - 26
src/views/core/order/index.vue

@@ -1,15 +1,25 @@
 <template>
   <el-row>
     <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
-      <el-col :span="24" class="one">
-        <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch">
-          <template #is_use>
-            <el-option v-for="i in statusList" :key="i._id" :label="i.label" :value="i.value"></el-option>
-          </template>
-        </cSearch>
+      <el-col :span="24" class="one" style="margin-bottom: 10px">
+        <el-date-picker
+          v-model="searchForm.date"
+          type="date"
+          placeholder="选择时间查询当天订单以及计算当天菜品总量"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+          style="width: 350px; height: 32px; margin-right: 20px"
+        >
+        </el-date-picker>
+        <el-button type="primary" size="mini" @click="toSearch">查询</el-button>
+        <el-button type="primary" size="mini" @click="toComputedSelectDay">计算当天菜品总量</el-button>
       </el-col>
       <el-col :span="24" class="thr">
-        <cTable :fields="fields" :opera="opera" :list="list" @query="search" :total="total" @view="toView"> </cTable>
+        <cTable :fields="fields" :opera="opera" :list="list" @query="search" :total="total" @view="toView">
+          <template #is_use="{ row }">
+            <span style="color: red">{{ checkUseStatus(row) }}</span>
+          </template>
+        </cTable>
       </el-col>
     </el-col>
   </el-row>
@@ -27,18 +37,23 @@
         </el-tab-pane>
       </el-tabs>
     </el-col>
+    <el-col :span="24" class="dialog_one" v-if="dialog.type == '2'"> 
+      <computed-table :data="computedMeal" :fields="allMeal"></computed-table>
+    </el-col>
   </cDialog>
 </template>
 
 <script setup lang="ts">
 // 组件
 import meal from './parts/meal.vue';
-import { ref, Ref, onMounted, inject } from 'vue';
+import computedTable from './parts/computedTable.vue';
+import moment from 'moment';
+import { ref, Ref, onMounted, inject, toRaw } from 'vue';
 // NeedChange
 import { OrderStore } from '@/stores/core/order';
 import { DictDataStore } from '@/stores/system/dictData';
 import type { IQueryResult } from '@/util/types.util';
-import { get } from 'lodash';
+import { get, cloneDeep } from 'lodash';
 import baseStore from '@/stores/counter';
 const user = ref(baseStore.state.user);
 onMounted(async () => {
@@ -76,49 +91,85 @@ let list: Ref<any> = ref([]);
 let total: Ref<number> = ref(0);
 let skip = 0;
 let limit = inject('$limit') as number;
-let searchForm: Ref<any> = ref({});
+let searchForm: Ref<any> = ref({ date: moment().format('YYYY-MM-DD') });
 
 const search = async (e: { skip: number; limit: number }) => {
-  const info = { skip: e.skip, limit: e.limit, ...searchForm.value };
+  const sfd = cloneDeep(searchForm.value);
+  const info = { skip: e.skip, limit: e.limit, ...sfd };
   const res: IQueryResult = await store.query(info);
   if (res.errcode == '0') {
     list.value = res.data;
     total.value = res.total;
   }
 };
-const toSearch = (query) => {
-  searchForm.value = query;
+const toSearch = () => {
   search({ skip, limit });
 };
+const allMeal = ref([]);
+const computedMeal = ref([]);
+const toComputedSelectDay = async () => {
+  const date = searchForm.value.date;
+  if (!date) return;
+  const result = await store.computedMeal(date);
+  if ($checkRes(result)) {
+    allMeal.value = get(result.data, 'menuAllList');
+    computedMeal.value = get(result.data, 'data');
+  }
+  dialog.value.show = true;
+  dialog.value.type = '2';
+};
 // #endregion
 
 // #region 表格及操作
 // NeedChange
 let fields: Ref<any[]> = ref([
   { label: '日期', model: 'date', isSearch: true },
-  { label: '早餐', model: 'breakfast', format: (i) => getDict(i, 'schedule') },
-  { label: '午餐', model: 'lunch', format: (i) => getDict(i, 'schedule') },
-  { label: '晚餐', model: 'dinner', format: (i) => getDict(i, 'schedule') },
-  { label: '状态', model: 'is_use', format: (i) => getDict(i, 'is_use') }
+  { label: '早餐', model: 'breakfast', format: (i) => getDict(i, 'breakfast') },
+  { label: '午餐', model: 'lunch', format: (i) => getDict(i, 'lunch') },
+  { label: '晚餐', model: 'dinner', format: (i) => getDict(i, 'dinner') },
+  { label: '状态', model: 'is_use', custom: true }
 ]);
 // 操作
 let opera: Ref<any[]> = ref([{ label: '查看', method: 'view' }]);
 
 const getDict = (data, model) => {
-  let list;
+  let rawData = toRaw(data);
+  let result;
   switch (model) {
-    case 'is_use':
-      list = statusList.value;
-      break;
-    case 'schedule':
-      list = scheduleList.value;
+    case 'breakfast':
+    case 'lunch':
+    case 'dinner':
+      if (rawData) result = getTableMeal(rawData.list);
       break;
     default:
       break;
   }
-  if (!list) return;
-  const res = list.find((f) => f.value == data);
-  return get(res, 'label');
+  return result;
+};
+const checkUseStatus = (data) => {
+  let rawData = toRaw(data);
+  const b = get(rawData, 'breakfast');
+  const l = get(rawData, 'lunch');
+  const d = get(rawData, 'dinner');
+  let notUseBreakfastStr = '未使用早餐券';
+  let notUseLunchStr = '未使用午餐券';
+  let notUseDinnerStr = '未使用晚餐券';
+  let resultArr = [];
+  if (b) {
+    if (!get(b, 'is_use')) resultArr.push(notUseBreakfastStr);
+  }
+  if (l) {
+    if (!get(l, 'is_use')) resultArr.push(notUseLunchStr);
+  }
+  if (d) {
+    if (!get(d, 'is_use')) resultArr.push(notUseDinnerStr);
+  }
+  return resultArr.join(';');
+};
+const getTableMeal = (list = []) => {
+  const nameArr = list.map((i) => i.name);
+  const str = nameArr.join(';');
+  return str;
 };
 const toView = async (data) => {
   form.value = { ...data };
@@ -134,6 +185,7 @@ const form: Ref<any> = ref({ file: [] });
 const toClose = () => {
   form.value = {};
   dialog.value.show = false;
+  dialog.value.type = '1';
 };
 // #endregion
 </script>

+ 63 - 0
src/views/core/order/parts/computedTable.vue

@@ -0,0 +1,63 @@
+<template>
+  <div id="computedTable">
+    <el-table :data="data" border stripe :show-summary="true" :summary-method="getTotal">
+      <el-table-column label="" prop="meal" align="center"> </el-table-column>
+      <template v-for="f in fields" :key="f._id">
+        <el-table-column :label="f.name" :prop="f._id" align="center">
+          <template v-slot="{ row }">
+            {{ getNumber(row, f) }}
+          </template>
+        </el-table-column>
+      </template>
+    </el-table>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { get } from 'lodash';
+import { toRaw, toRefs } from 'vue';
+interface item {
+  key?: string;
+  num?: number;
+  name?: string;
+  _id: string;
+}
+const props = defineProps({
+  data: { type: Array<item>, default: () => {} },
+  fields: { type: Array<item>, default: () => [] }
+});
+const { data, fields } = toRefs(props);
+
+const getNumber = (data, field) => {
+  const key = `${data.key}_${field._id}`;
+  return get(data, key);
+};
+const getTotal = (param) => {
+  const { columns, data } = param;
+  const rawData = toRaw(data);
+  const result = [];
+  columns.forEach((col, index) => {
+    if (index === 0) {
+      result.push('合计');
+      return;
+    }
+    const rawCol = toRaw(col);
+    const menu_id = rawCol.property;
+    let total = 0;
+    // 循环三餐找菜品累加
+    for (const d of rawData) {
+      const keys = Object.keys(d);
+      const have_id_keys = keys.filter((f) => f.includes(menu_id));
+      if (have_id_keys.length > 0) {
+        for (const k of have_id_keys) {
+          total = total + (d[k] || 0);
+        }
+      }
+    }
+    result.push(total);
+  });
+  return result;
+};
+</script>
+
+<style scoped></style>

+ 8 - 1
src/views/user/admin/index.vue

@@ -18,6 +18,7 @@
           @del="toDel"
           @rp="toResetPwd"
           @changeUse="toChangeUse"
+          @bind="toBind"
         >
         </cTable>
       </el-col>
@@ -67,6 +68,7 @@ let fields: Ref<any[]> = ref([
 // 操作
 let opera: Ref<any[]> = ref([
   { label: '修改', method: 'edit' },
+  { label: '绑定用户', method: 'bind' },
   { label: '重置密码', method: 'rp', type: 'warning', confirm: true, confirmWord: '您确定要重置密码?' },
   { label: '禁用', method: 'changeUse', type: 'warning', confirm: true, confirmWord: '您确定要禁用该用户?', display: (i) => i.is_use === '0' },
   { label: '使用', method: 'changeUse', type: 'success', confirm: true, confirmWord: '您确定要启用该用户?', display: (i) => i.is_use === '1' },
@@ -97,6 +99,7 @@ const formFieldsForUpdate = [
   { label: '名称', model: 'nick_name' },
   { label: '是否启用', model: 'is_use', type: 'radio' }
 ];
+const formFieldsForBind = [{ label: 'openid', model: 'openid' }];
 const roleField = { label: '角色', model: 'role', type: 'select' };
 const defaultForm = { is_use: '0' };
 const formFields: Ref<any> = ref();
@@ -149,10 +152,14 @@ const toAdd = () => {
 const toEdit = (data) => {
   formFields.value = cloneDeep(formFieldsForUpdate);
   form.value = data;
-  console.log(data)
   if (data.is_super !== '0') formFields.value.push(roleField);
   dialog.value.show = true;
 };
+const toBind = (data) => {
+  formFields.value = cloneDeep(formFieldsForBind);
+  form.value = data;
+  dialog.value.show = true;
+};
 
 // 关闭弹框
 const toClose = () => {