Quellcode durchsuchen

系统配置页面绘制和短信配置基本完成

Huanyi vor 1 Monat
Ursprung
Commit
4bb7581d0b

+ 13 - 0
src/api/resource/smsConfig/index.ts

@@ -61,3 +61,16 @@ export const delSmsConfig = (id: string | number | Array<string | number>) => {
     method: 'delete'
   });
 };
+
+/**
+ * 修改短信配置状态
+ * @param id
+ * @param status
+ */
+export const changeSmsConfigStatus = (id: string | number, status: boolean) => {
+  return request({
+    url: '/resource/smsConfig/changeStatus',
+    method: 'put',
+    data: { id, status }
+  });
+};

+ 3 - 3
src/api/resource/smsConfig/types.ts

@@ -37,7 +37,7 @@ export interface SmsConfigVO {
   /**
    * 状态
    */
-  status: number;
+  status: boolean;
 
 }
 
@@ -80,7 +80,7 @@ export interface SmsConfigForm extends BaseEntity {
   /**
    * 状态
    */
-  status?: number;
+  status?: boolean;
 
 }
 
@@ -119,7 +119,7 @@ export interface SmsConfigQuery extends PageQuery {
   /**
    * 状态
    */
-  status?: number;
+  status?: boolean;
 
   /**
    * 日期范围参数

+ 2 - 2
src/api/system/store/index.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { StoreVO, StoreForm, StoreQuery, StoreStatusVO } from '@/api/system/store/types';
+import { StoreVO, StoreForm, StoreQuery, StoreStatusVO, SysStorePageBo } from '@/api/system/store/types';
 
 /**
  * 查询门店管理列表
@@ -8,7 +8,7 @@ import { StoreVO, StoreForm, StoreQuery, StoreStatusVO } from '@/api/system/stor
  * @returns {*}
  */
 
-export const listStore = (query?: StoreQuery): AxiosPromise<StoreVO[]> => {
+export const listStore = (query?: SysStorePageBo): AxiosPromise<StoreVO[]> => {
   return request({
     url: '/system/store/list',
     method: 'get',

+ 13 - 0
src/api/system/store/types.ts

@@ -82,6 +82,11 @@ export interface StoreVO {
    */
   tenantId: string;
 
+  /**
+   * 服务单
+   */
+  serviceOrder: number | string;
+
 }
 
 export interface StoreForm extends BaseEntity {
@@ -220,6 +225,14 @@ export interface StoreQuery extends PageQuery {
   params?: any;
 }
 
+export interface SysStorePageBo extends PageQuery {
+  storeOrContact?: string;
+  area?: number | string;
+  station?: number | string;
+  status?: number;
+  params?: any;
+}
+
 export interface StoreStatusVO {
   value: number;
   label: string;

+ 56 - 50
src/views/system/store/index.vue

@@ -2,50 +2,25 @@
   <div class="p-2">
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter"
       :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="门店名称" prop="name">
-              <el-input v-model="queryParams.name" placeholder="请输入门店名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="联系人" prop="contact">
-              <el-input v-model="queryParams.contact" placeholder="请输入联系人" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="有效期至" prop="validity">
-              <el-date-picker clearable v-model="queryParams.validity" type="date" value-format="YYYY-MM-DD"
-                placeholder="请选择有效期至" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
+      <div v-show="showSearch" class="mb-[10px] bg-white p-[20px] rounded-[4px] flex justify-between items-center shadow-sm" style="background-color: #fff; padding: 20px; border-radius: 4px; box-shadow: 0 1px 4px rgba(0,21,41,.08);">
+        <div class="text-[18px] font-bold text-[#303133]" style="font-size: 18px; font-weight: bold; color: #303133;">门店管理</div>
+        <div class="flex items-center gap-[10px]" style="display: flex; gap: 10px; align-items: center;">
+          <el-input v-model="queryParams.storeOrContact" placeholder="搜索门店名称/联系人" prefix-icon="Search"
+            style="width: 250px" clearable @keyup.enter="handleQuery" @clear="handleQuery" />
+          <el-cascader v-model="searchRegionValue" :options="areaOptions" placeholder="所属城市"
+            style="width: 150px" clearable @change="handleSearchAreaChange" />
+          <el-select v-model="queryParams.station" placeholder="所属站点" style="width: 150px" clearable @change="handleQuery">
+            <el-option v-for="site in searchSiteOptions" :key="site.value" :label="site.label" :value="site.value" />
+          </el-select>
+          <el-select v-model="queryParams.status" placeholder="状态" style="width: 120px" clearable @change="handleQuery">
+            <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+          <el-button type="primary" icon="Plus" @click="handleAdd" v-hasPermi="['system:store:add']">新增门店</el-button>
+        </div>
       </div>
     </transition>
 
     <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd"
-              v-hasPermi="['system:store:add']">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
-              v-hasPermi="['system:store:edit']">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
-              v-hasPermi="['system:store:remove']">删除</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="warning" plain icon="Download" @click="handleExport"
-              v-hasPermi="['system:store:export']">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
-      </template>
 
       <el-table v-loading="loading" border :data="storeList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
@@ -86,6 +61,11 @@
             <div>{{ scope.row.siteName }}</div>
           </template>
         </el-table-column>
+        <el-table-column label="服务单" align="center" width="150">
+          <template #default="scope">
+            <div>{{ scope.row.serviceOrder }}</div>
+          </template>
+        </el-table-column>
         <el-table-column label="营业时间" align="center" width="150">
           <template #default="scope">
             <div>{{ formatTime(scope.row.startBusinessTime) }}-{{ formatTime(scope.row.endBusinessTime) }}</div>
@@ -294,7 +274,7 @@
 
 <script setup name="Store" lang="ts">
 import { listStore, getStore, delStore, addStore, updateStore, listStoreStatus } from '@/api/system/store';
-import { StoreVO, StoreQuery, StoreForm, StoreStatusVO } from '@/api/system/store/types';
+import { StoreVO, StoreQuery, StoreForm, StoreStatusVO, SysStorePageBo } from '@/api/system/store/types';
 import { listOnStore } from '@/api/system/tenant';
 import { listOnStore as listTenantCategoriesOnStore } from '@/api/system/tenantCategories';
 import { listOnStore as listServiceOnStore } from '@/api/service/list';
@@ -318,6 +298,30 @@ const queryFormRef = ref<ElFormInstance>();
 const storeFormRef = ref<ElFormInstance>();
 const brandSelectRef = ref<any>(null);
 
+const searchRegionValue = ref<any[]>([]); // 搜索的区域值
+const searchSiteOptions = ref<any[]>([]); // 搜索的站点选项
+
+/** 处理搜索区域选择变化 */
+const handleSearchAreaChange = (value: any[]) => {
+  // 清空级联站点
+  queryParams.value.station = undefined;
+
+  if (value && value.length > 0) {
+    const areaId = value[value.length - 1];
+    queryParams.value.area = areaId;
+    searchSiteOptions.value = areaStationList.value
+      .filter((item: any) => item.type === 2 && String(item.parentId) === String(areaId))
+      .map((item: any) => ({
+        value: item.id,
+        label: item.name
+      }));
+  } else {
+    queryParams.value.area = undefined;
+    searchSiteOptions.value = [];
+  }
+  handleQuery();
+};
+
 // 新增的响应式变量
 const regionValue = ref<any[]>([]);
 const province = ref('');
@@ -386,17 +390,14 @@ const initFormData: StoreForm = {
   services: [],
   regionId: undefined,
 }
-const data = reactive<PageData<StoreForm, StoreQuery>>({
+const data = reactive<PageData<StoreForm, SysStorePageBo>>({
   form: { ...initFormData },
   queryParams: {
     pageNum: 1,
-    pageSize: 1,
-    businessLicense: undefined,
-    name: undefined,
-    tenantCatergories: undefined,
-    contact: undefined,
-    validity: undefined,
-    site: undefined,
+    pageSize: 10,
+    storeOrContact: undefined,
+    area: undefined,
+    station: undefined,
     status: undefined,
     params: {
     }
@@ -478,7 +479,12 @@ const handleQuery = () => {
 
 /** 重置按钮操作 */
 const resetQuery = () => {
-  queryFormRef.value?.resetFields();
+  searchRegionValue.value = [];
+  searchSiteOptions.value = [];
+  queryParams.value.storeOrContact = undefined;
+  queryParams.value.area = undefined;
+  queryParams.value.station = undefined;
+  queryParams.value.status = undefined;
   handleQuery();
 }
 

+ 120 - 0
src/views/systemConfig/index.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="system-config-container">
+    <div class="menu-tabs">
+      <div 
+        v-for="(item, index) in menuList" 
+        :key="index"
+        :class="['menu-item', { active: activeTab === item.key }]"
+        @click="activeTab = item.key"
+      >
+        {{ item.label }}
+      </div>
+    </div>
+    
+    <div class="page-title">{{ activeTitle }}</div>
+
+    <div class="content-container">
+      <!-- 网站设置组件预留 -->
+      <!-- <WebsiteConfig v-if="activeTab === 'website'" /> -->
+      <div v-if="activeTab === 'website'" class="placeholder">{{ activeTitle }}页面开发中...</div>
+
+      <!-- 平台配置组件预留 -->
+      <!-- <PlatformConfig v-if="activeTab === 'platform'" /> -->
+      <div v-if="activeTab === 'platform'" class="placeholder">{{ activeTitle }}页面开发中...</div>
+      
+      <!-- 文件存储配置组件引入 -->
+      <OssConfig v-if="activeTab === 'storage'" />
+
+      <!-- 短信配置组件引入 -->
+      <SmsConfig v-if="activeTab === 'sms'" />
+
+      <!-- 协议配置组件预留 -->
+      <!-- <ProtocolConfig v-if="activeTab === 'protocol'" /> -->
+      <div v-if="activeTab === 'protocol'" class="placeholder">{{ activeTitle }}页面开发中...</div>
+    </div>
+  </div>
+</template>
+
+<script setup name="SystemConfig" lang="ts">
+import { ref, computed } from 'vue';
+import SmsConfig from '@/views/systemConfig/sms/index.vue';
+import OssConfig from '@/views/system/oss/config.vue';
+
+const activeTab = ref('website');
+
+const menuList = [
+  { label: '网站设置', key: 'website' },
+  { label: '平台配置', key: 'platform' },
+  { label: '文件存储配置', key: 'storage' },
+  { label: '短信配置', key: 'sms' },
+  { label: '协议配置', key: 'protocol' }
+];
+
+const activeTitle = computed(() => {
+  const find = menuList.find(item => item.key === activeTab.value);
+  return find ? find.label : '';
+});
+</script>
+
+<style scoped>
+.system-config-container {
+  padding: 20px;
+  background-color: #fff;
+  min-height: calc(100vh - 84px);
+  border-radius: 4px;
+}
+
+.menu-tabs {
+  display: flex;
+  margin-bottom: 30px;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+.menu-item {
+  padding: 12px 24px;
+  font-size: 14px;
+  color: #606266;
+  cursor: pointer;
+  background-color: transparent;
+  border-top: 1px solid transparent;
+  border-left: 1px solid transparent;
+  border-right: 1px solid transparent;
+  border-bottom: 2px solid transparent;
+  border-radius: 4px 4px 0 0;
+  margin-bottom: -1px;
+  transition: all 0.3s;
+}
+
+.menu-item:hover {
+  color: #409eff;
+}
+
+.menu-item.active {
+  color: #409eff;
+  border-top-color: #e4e7ed;
+  border-left-color: #e4e7ed;
+  border-right-color: #e4e7ed;
+  border-bottom-color: #fff;
+  background-color: #fff;
+}
+
+.page-title {
+  font-size: 16px;
+  font-weight: bold;
+  color: #303133;
+  margin-bottom: 20px;
+}
+
+.placeholder {
+  padding: 40px;
+  text-align: center;
+  color: #909399;
+  background-color: #f8f9fa;
+  border-radius: 4px;
+}
+
+/* 如果SmsConfig组件自带了padding,这里可以通过深度选择器稍做调整以防多余内边距 */
+:deep(.content-container > .p-2) {
+  padding: 0;
+}
+</style>

+ 20 - 3
src/views/resource/smsConfig/index.vue → src/views/systemConfig/sms/index.vue

@@ -59,7 +59,11 @@
         <el-table-column label="短信签名" align="center" prop="signature" />
         <el-table-column label="sdk-app-id" align="center" prop="sdkAppId" />
         <el-table-column label="模板ID" align="center" prop="templateId" />
-        <el-table-column label="状态" align="center" prop="status" />
+        <el-table-column label="状态" align="center" prop="status">
+          <template #default="scope">
+            <el-switch v-model="scope.row.status" :active-value="true" :inactive-value="false" @change="handleStatusChange(scope.row)"></el-switch>
+          </template>
+        </el-table-column>
         <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-tooltip content="修改" placement="top">
@@ -107,7 +111,7 @@
 </template>
 
 <script setup name="SmsConfig" lang="ts">
-import { listSmsConfig, getSmsConfig, delSmsConfig, addSmsConfig, updateSmsConfig } from '@/api/resource/smsConfig';
+import { listSmsConfig, getSmsConfig, delSmsConfig, addSmsConfig, updateSmsConfig, changeSmsConfigStatus } from '@/api/resource/smsConfig';
 import { SmsConfigVO, SmsConfigQuery, SmsConfigForm } from '@/api/resource/smsConfig/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -175,7 +179,7 @@ const data = reactive<PageData<SmsConfigForm, SmsConfigQuery>>({
     ],
     templateId: [
       { required: true, message: "模板ID不能为空", trigger: "blur" }
-    ],
+    ]
   }
 });
 
@@ -255,6 +259,19 @@ const submitForm = () => {
   });
 }
 
+/** 状态修改  */
+const handleStatusChange = async (row: SmsConfigVO) => {
+  const text = row.status ? '启用' : '停用';
+  try {
+    await proxy?.$modal.confirm('确认要"' + text + '""' + row.supplier + '"配置吗?');
+    await changeSmsConfigStatus(row.id, row.status);
+    proxy?.$modal.msgSuccess(text + '成功');
+    await getList();
+  } catch {
+    row.status = !row.status;
+  }
+};
+
 /** 删除按钮操作 */
 const handleDelete = async (row?: SmsConfigVO) => {
   const _ids = row?.id || ids.value;