Commit 222eb7e87492b2072963c3dcf62bcb5fe139e289

Authored by 杨泽宇
1 parent eab5869b

物业管理

src/api/property/index.ts
1 import request from '../request' 1 import request from '../request'
  2 +import {formDataWrapper} from '@/utils/tool'
2 3
3 /** 4 /**
4 * @description 物业列表 5 * @description 物业列表
5 * @function propertyList 6 * @function propertyList
6 */ 7 */
7 -export function propertyList (params) { 8 +export const propertyList = async ( params: any ) => {
8 for (const i in params) { 9 for (const i in params) {
9 if (!(params[i] + '').trim()) { 10 if (!(params[i] + '').trim()) {
10 delete params[i] 11 delete params[i]
11 } 12 }
12 } 13 }
13 - return request({  
14 - method: 'get',  
15 - url: '/property/list',  
16 - params: {  
17 - page: 1,  
18 - pageSize: 10  
19 - }  
20 - })  
21 -}  
22 -  
23 -export const property_list = async ( params: any ) => {  
24 let res: any = await request.get( '/property/list', { params } ) 14 let res: any = await request.get( '/property/list', { params } )
25 - // let res: any = await request( {url: '/neighborhood/getList', params:{propertyId: 1, type: 1}, method: 'post' })  
26 return res 15 return res
27 } 16 }
28 17
@@ -42,10 +31,7 @@ export function propertyAdd (data) { @@ -42,10 +31,7 @@ export function propertyAdd (data) {
42 * @description 修改物业状态 31 * @description 修改物业状态
43 * @function propertyStatus 32 * @function propertyStatus
44 */ 33 */
45 -export function propertyStatus (params) {  
46 - return request({  
47 - method: 'post',  
48 - url: '/property/updateStatus',  
49 - params: params  
50 - })  
51 -}  
52 \ No newline at end of file 34 \ No newline at end of file
  35 +export const propertyStatus = async ( data: any ) => {
  36 + let res: any = await request.post( '/property/updateStatus', formDataWrapper(data) )
  37 + return res
  38 +}
53 \ No newline at end of file 39 \ No newline at end of file
src/layout/menu.vue
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 */ 6 */
7 import { ref, computed } from "vue"; 7 import { ref, computed } from "vue";
8 import * as store from "@/pinia/index"; 8 import * as store from "@/pinia/index";
9 -import styles from '@/style/global.module.scss'; 9 +import styles from "@/style/global.module.scss";
10 // TIP 使用element plus ICON 10 // TIP 使用element plus ICON
11 import { 11 import {
12 Location, 12 Location,
@@ -15,8 +15,8 @@ import { @@ -15,8 +15,8 @@ import {
15 Setting, 15 Setting,
16 } from "@element-plus/icons-vue"; 16 } from "@element-plus/icons-vue";
17 // TIP 获取scss样式变量 17 // TIP 获取scss样式变量
18 -let styleData = computed(()=>{  
19 - return styles 18 +let styleData = computed(() => {
  19 + return styles;
20 }); 20 });
21 </script> 21 </script>
22 22
@@ -28,31 +28,28 @@ let styleData = computed(()=&gt;{ @@ -28,31 +28,28 @@ let styleData = computed(()=&gt;{
28 :text-color="styleData.menuText" 28 :text-color="styleData.menuText"
29 :active-text-color="styleData.menuActiveText" 29 :active-text-color="styleData.menuActiveText"
30 class="el-menu-vertical-demo" 30 class="el-menu-vertical-demo"
  31 + :router="true"
31 :collapse-transition="false" 32 :collapse-transition="false"
32 :collapse="store.family.appStore().isCollapse" 33 :collapse="store.family.appStore().isCollapse"
33 > 34 >
34 <el-sub-menu index="1"> 35 <el-sub-menu index="1">
35 <template #title> 36 <template #title>
36 <el-icon><location /></el-icon> 37 <el-icon><location /></el-icon>
37 - <span>Navigator One</span> 38 + <span>物业管理</span>
38 </template> 39 </template>
39 <el-menu-item-group> 40 <el-menu-item-group>
40 - <template #title><span>Group One</span></template>  
41 - <el-menu-item index="1-1">item one</el-menu-item>  
42 - <el-menu-item index="1-2">item two</el-menu-item> 41 + <el-menu-item index="/property">物业列表</el-menu-item>
43 </el-menu-item-group> 42 </el-menu-item-group>
44 - <el-menu-item-group title="Group Two">  
45 - <el-menu-item index="1-3">item three</el-menu-item> 43 + </el-sub-menu>
  44 + <el-sub-menu index="2">
  45 + <template #title>
  46 + <el-icon><location /></el-icon>
  47 + <span>小区管理</span>
  48 + </template>
  49 + <el-menu-item-group>
  50 + <el-menu-item index="/community">小区管理</el-menu-item>
46 </el-menu-item-group> 51 </el-menu-item-group>
47 - <el-sub-menu index="1-4">  
48 - <template #title><span>item four</span></template>  
49 - <el-menu-item index="1-4-1">item one</el-menu-item>  
50 - </el-sub-menu>  
51 </el-sub-menu> 52 </el-sub-menu>
52 - <el-menu-item index="2">  
53 - <el-icon><icon-menu /></el-icon>  
54 - <template #title>Navigator Two</template>  
55 - </el-menu-item>  
56 <el-menu-item index="3" disabled> 53 <el-menu-item index="3" disabled>
57 <el-icon><document /></el-icon> 54 <el-icon><document /></el-icon>
58 <template #title>Navigator Three</template> 55 <template #title>Navigator Three</template>
src/main.ts
@@ -5,6 +5,7 @@ import promise from &#39;es6-promise&#39; @@ -5,6 +5,7 @@ import promise from &#39;es6-promise&#39;
5 // import store from '@/store/index' 5 // import store from '@/store/index'
6 6
7 import ElementPlus from 'element-plus' 7 import ElementPlus from 'element-plus'
  8 +import { ElMessage } from 'element-plus'
8 import 'element-plus/dist/index.css' 9 import 'element-plus/dist/index.css'
9 import zhCn from 'element-plus/es/locale/lang/zh-cn' // TIP elementUI配置中文环境 10 import zhCn from 'element-plus/es/locale/lang/zh-cn' // TIP elementUI配置中文环境
10 11
@@ -26,7 +27,6 @@ promise.polyfill() @@ -26,7 +27,6 @@ promise.polyfill()
26 27
27 console.log('current env: ', process.env.NODE_ENV) 28 console.log('current env: ', process.env.NODE_ENV)
28 console.log('current api url: ', import.meta.env.VITE_BASE_URL) 29 console.log('current api url: ', import.meta.env.VITE_BASE_URL)
29 -  
30 const app = createApp(App) 30 const app = createApp(App)
31 31
32 // TIP 全局静态变量、方法挂载 32 // TIP 全局静态变量、方法挂载
@@ -37,6 +37,7 @@ for(const i in globalVariable) { @@ -37,6 +37,7 @@ for(const i in globalVariable) {
37 // TIP 关浏览器控制台错误和警告 37 // TIP 关浏览器控制台错误和警告
38 // app.config.warnHandler = () => null; 38 // app.config.warnHandler = () => null;
39 // app.config.errorHandler = () => null; 39 // app.config.errorHandler = () => null;
  40 +app.provide("$message", ElMessage);
40 41
41 app 42 app
42 // .use(store) 43 // .use(store)
src/router/modules/property.ts
@@ -9,6 +9,11 @@ const property= { @@ -9,6 +9,11 @@ const property= {
9 name: 'property', 9 name: 'property',
10 component: () => import('@/views/property/index.vue'), 10 component: () => import('@/views/property/index.vue'),
11 meta: { title: '物业管理' } 11 meta: { title: '物业管理' }
  12 + }, {
  13 + path: '/property/edit',
  14 + name: 'edit',
  15 + component: () => import('@/views/property/edit.vue'),
  16 + meta: { title: '物业编辑' }
12 }] 17 }]
13 } 18 }
14 19
src/style/element.scss
@@ -8,4 +8,7 @@ @@ -8,4 +8,7 @@
8 // TIP 解决左侧菜单scrollbar左侧有间隔 8 // TIP 解决左侧菜单scrollbar左侧有间隔
9 .el-scrollbar { 9 .el-scrollbar {
10 width: 100%; 10 width: 100%;
  11 +}
  12 +.el-form--inline .el-form-item {
  13 + margin-right: 0;
11 } 14 }
12 \ No newline at end of file 15 \ No newline at end of file
src/utils/tool.ts
@@ -153,4 +153,17 @@ export function globalFilters (value: number, groupData: EnumData[]) { @@ -153,4 +153,17 @@ export function globalFilters (value: number, groupData: EnumData[]) {
153 } else { 153 } else {
154 return value 154 return value
155 } 155 }
  156 +}
  157 +
  158 +/**
  159 + * 请求参数包formData
  160 + * @param {object}} data
  161 + * @returns {FormData} fd
  162 + */
  163 +export function formDataWrapper (data: any) {
  164 + const fd: any = new FormData()
  165 + for (let i in data) {
  166 + fd.append(i, data[i])
  167 + }
  168 + return fd
156 } 169 }
157 \ No newline at end of file 170 \ No newline at end of file
src/views/property/edit.vue 0 → 100644
  1 +<script setup lang="ts">
  2 +import { reactive, ref, getCurrentInstance } from "vue";
  3 +import { propertyAdd } from "@/api/property";
  4 +import { validMobile } from "@/utils/validate";
  5 +import type { ElForm } from "element-plus";
  6 +const ruleFormRef = ref<InstanceType<typeof ElForm>>();
  7 +const {
  8 + appContext: {
  9 + config: { globalProperties },
  10 + },
  11 +} = getCurrentInstance();
  12 +let form = reactive({
  13 + data: {
  14 + name: "",
  15 + userName: "",
  16 + userPhone: "",
  17 + location: "北京",
  18 + address: "",
  19 + businessLicense: "",
  20 + contractNumber: "",
  21 + logo: "",
  22 + id: null,
  23 + shortName: "",
  24 + remark: "",
  25 + status: 0,
  26 + },
  27 +});
  28 +// 校验手机号格式
  29 +const checkPhone = (rules, value, callback) => {
  30 + if (validMobile(value)) {
  31 + callback();
  32 + } else {
  33 + callback(new Error("请填写格式正确的手机号码"));
  34 + }
  35 +};
  36 +// 表单验证规则
  37 +const rules = reactive({
  38 + name: [
  39 + {
  40 + required: true,
  41 + message: "请填写物业名称",
  42 + trigger: "blur",
  43 + },
  44 + ],
  45 + userName: [
  46 + {
  47 + required: true,
  48 + message: "请填写联系人",
  49 + trigger: "blur",
  50 + },
  51 + ],
  52 + userPhone: [
  53 + {
  54 + required: true,
  55 + message: "请填写格式正确的手机号码",
  56 + trigger: "blur",
  57 + validator: checkPhone,
  58 + },
  59 + ],
  60 + location: [
  61 + {
  62 + required: true,
  63 + message: "请填写地区",
  64 + trigger: "blur",
  65 + },
  66 + ],
  67 + address: [
  68 + {
  69 + required: true,
  70 + message: "请填写详细地址",
  71 + trigger: "blur",
  72 + },
  73 + ],
  74 + businessLicense: [
  75 + {
  76 + required: true,
  77 + message: "请上传营业执照",
  78 + trigger: "blur",
  79 + },
  80 + ],
  81 + contractNumber: [
  82 + {
  83 + required: true,
  84 + message: "请填写合同编号",
  85 + trigger: "blur",
  86 + },
  87 + ],
  88 + type: [
  89 + {
  90 + required: true,
  91 + message: "请选择类型",
  92 + trigger: "blur",
  93 + },
  94 + ],
  95 +});
  96 +// 表单重置
  97 +const resetForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  98 + if (!formEl) return;
  99 + formEl.resetFields();
  100 +};
  101 +// 表单提交
  102 +const submitForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  103 + if (!formEl) return;
  104 + formEl.validate((valid) => {
  105 + if (valid) {
  106 + propertyAdd(form.data)
  107 + .then((res) => {
  108 + if (res) {
  109 + globalProperties.$message.success("操作成功");
  110 + history.go(-1);
  111 + }
  112 + })
  113 + .catch((error) => {
  114 + console.log(error);
  115 + });
  116 + } else {
  117 + globalProperties.$message.success("请检查表单格式");
  118 + return false;
  119 + }
  120 + });
  121 +};
  122 +</script>
  123 +
  124 +<template>
  125 + <div class="page-container">
  126 + <el-card class="form_card" style="max-width: 1303px">
  127 + <h1>新增物业</h1>
  128 + <el-form
  129 + :inline="true"
  130 + :model="form.data"
  131 + :rules="rules"
  132 + ref="ruleFormRef"
  133 + label-width="120px"
  134 + style="display: flex; flex-wrap: wrap; width: 100%"
  135 + >
  136 + <el-form-item label="物业名称" prop="name" style="width: 50%">
  137 + <el-input
  138 + v-model.trim="form.data.name"
  139 + placeholder="请填写物业名称"
  140 + maxlength="15"
  141 + />
  142 + </el-form-item>
  143 + <el-form-item label="物业简称" prop="shortName" style="width: 50%">
  144 + <el-input
  145 + v-model.trim="form.data.shortName"
  146 + placeholder="请填写物业简称"
  147 + maxlength="15"
  148 + />
  149 + </el-form-item>
  150 + <el-form-item label="联系人" prop="userName" style="width: 50%">
  151 + <el-input
  152 + v-model.trim="form.data.userName"
  153 + placeholder="请填写联系人"
  154 + maxlength="15"
  155 + />
  156 + </el-form-item>
  157 + <el-form-item label="联系电话" prop="userPhone" style="width: 50%">
  158 + <el-input
  159 + v-model.trim="form.data.userPhone"
  160 + placeholder="请填写联系电话"
  161 + maxlength="11"
  162 + />
  163 + </el-form-item>
  164 + <el-form-item label="地区" prop="location" style="width: 50%">
  165 + <el-input
  166 + v-model.trim="form.data.location"
  167 + placeholder="请填写地区"
  168 + maxlength="11"
  169 + disabled
  170 + />
  171 + </el-form-item>
  172 + <el-form-item label="详细地址" prop="address" style="width: 100%">
  173 + <el-input
  174 + v-model.trim="form.data.address"
  175 + placeholder="请填写详细地址"
  176 + maxlength="50"
  177 + />
  178 + </el-form-item>
  179 + <el-form-item
  180 + label="营业执照"
  181 + prop="businessLicense"
  182 + style="width: 50%"
  183 + >
  184 + <el-input
  185 + v-model.trim="form.data.businessLicense"
  186 + placeholder="请填写营业执照"
  187 + maxlength="50"
  188 + />
  189 + </el-form-item>
  190 + <el-form-item label="物业LOGO" prop="logo" style="width: 50%">
  191 + <el-input
  192 + v-model.trim="form.data.logo"
  193 + placeholder="请填写物业LOGO"
  194 + maxlength="50"
  195 + />
  196 + </el-form-item>
  197 + <el-form-item label="合同编号" prop="contractNumber" style="width: 50%">
  198 + <el-input
  199 + v-model.trim="form.data.contractNumber"
  200 + placeholder="请填写合同编号"
  201 + maxlength="50"
  202 + />
  203 + </el-form-item>
  204 + <el-form-item label="备注" prop="remark" style="width: 100%">
  205 + <el-input
  206 + v-model.trim="form.data.remark"
  207 + placeholder="请填写备注"
  208 + maxlength="50"
  209 + />
  210 + </el-form-item>
  211 + <el-form-item label="类型" prop="type" style="width: 50%">
  212 + <el-select v-model="form.data.type">
  213 + <el-option label="物业" value="1"></el-option>
  214 + <el-option label="公益" value="2"></el-option>
  215 + </el-select>
  216 + </el-form-item>
  217 + <el-form-item style="width: 100%">
  218 + <el-button type="primary" @click="submitForm(ruleFormRef)"
  219 + >提交</el-button
  220 + >
  221 + <el-button type="info" @click="resetForm(ruleFormRef)"
  222 + >取消</el-button
  223 + >
  224 + </el-form-item>
  225 + </el-form>
  226 + </el-card>
  227 + </div>
  228 +</template>
src/views/property/index.vue
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 -import { reactive, ref, onMounted } from "vue";  
3 -import { property_list } from "@/api/property"; 2 +import { reactive, ref, onMounted, getCurrentInstance } from "vue";
  3 +import { propertyList, propertyStatus } from "@/api/property";
  4 +import { parseTime } from "@/utils/tool";
4 import Pagination from "@/components/Pagination/index.vue"; 5 import Pagination from "@/components/Pagination/index.vue";
  6 +const {
  7 + appContext: {
  8 + config: { globalProperties },
  9 + },
  10 +} = getCurrentInstance();
  11 +interface Form {
  12 + page: number;
  13 + pageSize: number;
  14 + name?: string;
  15 +}
  16 +interface Params {
  17 + total: number;
  18 + query: Form;
  19 +}
  20 +interface Data {
  21 + loading: boolean;
  22 + list: any[] | null;
  23 + params: Params;
  24 +}
5 let data = reactive({ 25 let data = reactive({
6 - list: []  
7 -})  
8 -let loading = ref(false);  
9 -let params = reactive({  
10 - total: 0,  
11 - query: {  
12 - page: 1,  
13 - pageSize: 10, 26 + list: [],
  27 + loading: false,
  28 + params: {
  29 + total: 0,
  30 + query: {
  31 + page: 1,
  32 + pageSize: 10,
  33 + name: "",
  34 + },
14 }, 35 },
15 }); 36 });
  37 +// 列表
  38 +const getList = async () => {
  39 + data.loading = true;
  40 + try {
  41 + const res = await propertyList(data.params.query);
  42 + data.list = res.data.data.list;
  43 + data.params.total = res.data.data.total;
  44 + } catch (e) {
  45 + console.log(e);
  46 + } finally {
  47 + data.loading = false;
  48 + }
  49 +};
  50 +// 分页
16 const handlePageChange = (page, size) => { 51 const handlePageChange = (page, size) => {
17 - params.query.page = page;  
18 - params.query.pageSize = size; 52 + data.params.query.page = page;
  53 + data.params.query.pageSize = size;
  54 + getList();
  55 +};
  56 +// 查询
  57 +const handleSearch = () => {
  58 + getList();
19 }; 59 };
20 -const handleLogin = async () => { 60 +// 切换状态
  61 +const handleStatus = async (obj) => {
21 try { 62 try {
22 - const res = await property_list();  
23 - console.log(res.data.data.list);  
24 - data.list = res.data.data.list 63 + const res = await propertyStatus({
  64 + id: obj.id,
  65 + status: obj.status ? 0 : 1,
  66 + });
  67 + if (res?.data) {
  68 + globalProperties.$message.success("操作成功");
  69 + getList();
  70 + } else {
  71 + globalProperties.$message.error("操作失败");
  72 + }
25 } catch (e) { 73 } catch (e) {
26 - console.log(e) 74 + console.log(e);
27 } 75 }
28 }; 76 };
29 - 77 +// 状态值
  78 +enum statusEnum {
  79 + "禁用" = 0,
  80 + "启用",
  81 +}
30 onMounted(() => { 82 onMounted(() => {
31 - try{  
32 - handleLogin()  
33 - } catch(e) {  
34 - console.log(e)  
35 - } 83 + getList();
36 }); 84 });
37 </script> 85 </script>
38 86
39 <template> 87 <template>
40 <div class="page-container"> 88 <div class="page-container">
41 <h1>物业列表</h1> 89 <h1>物业列表</h1>
  90 + <el-row style="padding-bottom: 20px">
  91 + <el-form :inline="true" label-width="70px">
  92 + <el-form-item label="物业名称">
  93 + <el-input
  94 + v-model.trim="data.params.query.name"
  95 + placeholder="请填写物业名称"
  96 + maxlength="15"
  97 + @change="handleSearch"
  98 + />
  99 + </el-form-item>
  100 + <el-form-item>
  101 + <el-button type="primary" @click="handleSearch">查询</el-button>
  102 + <el-button type="primary">
  103 + <router-link to="/property/edit">创建物业</router-link>
  104 + </el-button>
  105 + </el-form-item>
  106 + </el-form>
  107 + </el-row>
42 <el-table 108 <el-table
43 :data="data.list" 109 :data="data.list"
44 style="width: 100%" 110 style="width: 100%"
45 border 111 border
46 - v-loading="loading" 112 + v-loading="data.loading"
47 align="center" 113 align="center"
48 element-loading-text="拼命加载中" 114 element-loading-text="拼命加载中"
49 > 115 >
50 - <el-table-column prop="location" label="地区" width="180"> 116 + <el-table-column prop="id" label="ID" align="center"> </el-table-column>
  117 + <el-table-column prop="location" label="地区" align="center">
51 </el-table-column> 118 </el-table-column>
52 - <el-table-column prop="address" label="详细地址" width="180"> 119 + <el-table-column prop="address" label="详细地址" align="center">
53 </el-table-column> 120 </el-table-column>
54 - <el-table-column prop="name" label="公司名称" width="180"> 121 + <el-table-column prop="name" label="公司名称" align="center">
55 </el-table-column> 122 </el-table-column>
56 - <el-table-column prop="userName" label="联系人" width="180"> 123 + <el-table-column prop="userName" label="联系人" align="center">
57 </el-table-column> 124 </el-table-column>
58 - <el-table-column prop="userPhone" label="联系电话" width="180"> 125 + <el-table-column prop="userPhone" label="联系电话" align="center">
59 </el-table-column> 126 </el-table-column>
60 - <el-table-column prop="businessLicense" label="营业执照" width="180"> 127 + <el-table-column prop="businessLicense" label="营业执照" align="center">
  128 + <template #default="scope">
  129 + <el-image
  130 + :src="
  131 + scope.row.businessLicense
  132 + ? scope.row.businessLicense
  133 + : globalProperties.$defaultImage
  134 + "
  135 + fit="contain"
  136 + lazy
  137 + style="height: 100px"
  138 + ></el-image>
  139 + </template>
61 </el-table-column> 140 </el-table-column>
62 - <el-table-column prop="createTime" label="入驻时间" width="180"> 141 + <el-table-column prop="createTime" label="入驻时间" align="center">
  142 + <template #default="scope">
  143 + {{ parseTime(new Date(scope.row.createTime).getTime()) }}
  144 + </template>
63 </el-table-column> 145 </el-table-column>
64 - <el-table-column prop="contractNumber" label="合同编号" width="180"> 146 + <el-table-column prop="contractNumber" label="合同编号" align="center">
65 </el-table-column> 147 </el-table-column>
66 - <el-table-column prop="status" label="状态"> 148 + <el-table-column prop="status" label="状态" align="center">
67 <template #default="scope"> 149 <template #default="scope">
68 - {{ scope.row.status }} 150 + {{ statusEnum[scope.row.status] }}
69 </template> 151 </template>
70 </el-table-column> 152 </el-table-column>
71 - <el-table-column label="操作"> 153 + <el-table-column label="操作" align="center">
72 <template #default="scope"> 154 <template #default="scope">
73 - <el-button type="primary">代理登录</el-button>  
74 - <el-button type="primary">删除</el-button> 155 + <el-button type="text" disabled>代理登录</el-button>
  156 + <el-button type="text" @click="handleStatus(scope.row)">{{
  157 + scope.row.status ? "禁用" : "启用"
  158 + }}</el-button>
  159 + <el-button type="text" disabled>删除</el-button>
75 </template> 160 </template>
76 </el-table-column> 161 </el-table-column>
77 </el-table> 162 </el-table>
78 <Pagination 163 <Pagination
79 - :total="params.total"  
80 - :currentPage="params.query.page"  
81 - :pageSize="params.query.pageSize" 164 + :total="data.params.total"
  165 + :currentPage="data.params.query.page"
  166 + :pageSize="data.params.query.pageSize"
82 @pageChange="handlePageChange" 167 @pageChange="handlePageChange"
83 ></Pagination> 168 ></Pagination>
84 </div> 169 </div>