Commit 222eb7e87492b2072963c3dcf62bcb5fe139e289

Authored by 杨泽宇
1 parent eab5869b

物业管理

src/api/property/index.ts
1 1 import request from '../request'
  2 +import {formDataWrapper} from '@/utils/tool'
2 3  
3 4 /**
4 5 * @description 物业列表
5 6 * @function propertyList
6 7 */
7   -export function propertyList (params) {
  8 +export const propertyList = async ( params: any ) => {
8 9 for (const i in params) {
9 10 if (!(params[i] + '').trim()) {
10 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 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 15 return res
27 16 }
28 17  
... ... @@ -42,10 +31,7 @@ export function propertyAdd (data) {
42 31 * @description 修改物业状态
43 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 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 39 \ No newline at end of file
... ...
src/layout/menu.vue
... ... @@ -6,7 +6,7 @@
6 6 */
7 7 import { ref, computed } from "vue";
8 8 import * as store from "@/pinia/index";
9   -import styles from '@/style/global.module.scss';
  9 +import styles from "@/style/global.module.scss";
10 10 // TIP 使用element plus ICON
11 11 import {
12 12 Location,
... ... @@ -15,8 +15,8 @@ import {
15 15 Setting,
16 16 } from "@element-plus/icons-vue";
17 17 // TIP 获取scss样式变量
18   -let styleData = computed(()=>{
19   - return styles
  18 +let styleData = computed(() => {
  19 + return styles;
20 20 });
21 21 </script>
22 22  
... ... @@ -28,31 +28,28 @@ let styleData = computed(()=&gt;{
28 28 :text-color="styleData.menuText"
29 29 :active-text-color="styleData.menuActiveText"
30 30 class="el-menu-vertical-demo"
  31 + :router="true"
31 32 :collapse-transition="false"
32 33 :collapse="store.family.appStore().isCollapse"
33 34 >
34 35 <el-sub-menu index="1">
35 36 <template #title>
36 37 <el-icon><location /></el-icon>
37   - <span>Navigator One</span>
  38 + <span>物业管理</span>
38 39 </template>
39 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 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 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 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 53 <el-menu-item index="3" disabled>
57 54 <el-icon><document /></el-icon>
58 55 <template #title>Navigator Three</template>
... ...
src/main.ts
... ... @@ -5,6 +5,7 @@ import promise from &#39;es6-promise&#39;
5 5 // import store from '@/store/index'
6 6  
7 7 import ElementPlus from 'element-plus'
  8 +import { ElMessage } from 'element-plus'
8 9 import 'element-plus/dist/index.css'
9 10 import zhCn from 'element-plus/es/locale/lang/zh-cn' // TIP elementUI配置中文环境
10 11  
... ... @@ -26,7 +27,6 @@ promise.polyfill()
26 27  
27 28 console.log('current env: ', process.env.NODE_ENV)
28 29 console.log('current api url: ', import.meta.env.VITE_BASE_URL)
29   -
30 30 const app = createApp(App)
31 31  
32 32 // TIP 全局静态变量、方法挂载
... ... @@ -37,6 +37,7 @@ for(const i in globalVariable) {
37 37 // TIP 关浏览器控制台错误和警告
38 38 // app.config.warnHandler = () => null;
39 39 // app.config.errorHandler = () => null;
  40 +app.provide("$message", ElMessage);
40 41  
41 42 app
42 43 // .use(store)
... ...
src/router/modules/property.ts
... ... @@ -9,6 +9,11 @@ const property= {
9 9 name: 'property',
10 10 component: () => import('@/views/property/index.vue'),
11 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 8 // TIP 解决左侧菜单scrollbar左侧有间隔
9 9 .el-scrollbar {
10 10 width: 100%;
  11 +}
  12 +.el-form--inline .el-form-item {
  13 + margin-right: 0;
11 14 }
12 15 \ No newline at end of file
... ...
src/utils/tool.ts
... ... @@ -153,4 +153,17 @@ export function globalFilters (value: number, groupData: EnumData[]) {
153 153 } else {
154 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 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 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 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 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 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 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 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 82 onMounted(() => {
31   - try{
32   - handleLogin()
33   - } catch(e) {
34   - console.log(e)
35   - }
  83 + getList();
36 84 });
37 85 </script>
38 86  
39 87 <template>
40 88 <div class="page-container">
41 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 108 <el-table
43 109 :data="data.list"
44 110 style="width: 100%"
45 111 border
46   - v-loading="loading"
  112 + v-loading="data.loading"
47 113 align="center"
48 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 118 </el-table-column>
52   - <el-table-column prop="address" label="详细地址" width="180">
  119 + <el-table-column prop="address" label="详细地址" align="center">
53 120 </el-table-column>
54   - <el-table-column prop="name" label="公司名称" width="180">
  121 + <el-table-column prop="name" label="公司名称" align="center">
55 122 </el-table-column>
56   - <el-table-column prop="userName" label="联系人" width="180">
  123 + <el-table-column prop="userName" label="联系人" align="center">
57 124 </el-table-column>
58   - <el-table-column prop="userPhone" label="联系电话" width="180">
  125 + <el-table-column prop="userPhone" label="联系电话" align="center">
59 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 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 145 </el-table-column>
64   - <el-table-column prop="contractNumber" label="合同编号" width="180">
  146 + <el-table-column prop="contractNumber" label="合同编号" align="center">
65 147 </el-table-column>
66   - <el-table-column prop="status" label="状态">
  148 + <el-table-column prop="status" label="状态" align="center">
67 149 <template #default="scope">
68   - {{ scope.row.status }}
  150 + {{ statusEnum[scope.row.status] }}
69 151 </template>
70 152 </el-table-column>
71   - <el-table-column label="操作">
  153 + <el-table-column label="操作" align="center">
72 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 160 </template>
76 161 </el-table-column>
77 162 </el-table>
78 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 167 @pageChange="handlePageChange"
83 168 ></Pagination>
84 169 </div>
... ...