Jelajahi Sumber

feat: add two modules org and users

gemercheung 1 tahun lalu
induk
melakukan
7010a72d69

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
     "konva": "9.3.6",
     "mitt": "^3.0.1",
     "ol": "^9.1.0",
+    "pinia": "^2.1.7",
     "proj4": "^2.11.0",
     "qrcode": "^1.5.3",
     "vue": "^3.4.21",

+ 21 - 0
pnpm-lock.yaml

@@ -32,6 +32,9 @@ dependencies:
   ol:
     specifier: ^9.1.0
     version: 9.2.4
+  pinia:
+    specifier: ^2.1.7
+    version: 2.1.7(typescript@5.4.5)(vue@3.4.27)
   proj4:
     specifier: ^2.11.0
     version: 2.11.0
@@ -1168,6 +1171,24 @@ packages:
     engines: {node: '>=8.6'}
     dev: true
 
+  /pinia@2.1.7(typescript@5.4.5)(vue@3.4.27):
+    resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==}
+    peerDependencies:
+      '@vue/composition-api': ^1.4.0
+      typescript: '>=4.4.4'
+      vue: ^2.6.14 || ^3.3.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+      typescript:
+        optional: true
+    dependencies:
+      '@vue/devtools-api': 6.6.1
+      typescript: 5.4.5
+      vue: 3.4.27(typescript@5.4.5)
+      vue-demi: 0.14.7(vue@3.4.27)
+    dev: false
+
   /pngjs@5.0.0:
     resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
     engines: {node: '>=10.13.0'}

+ 5 - 5
src/request/URL.ts

@@ -25,11 +25,11 @@ export const delDevice = `/relics/camera/del/:deviceId`;
 export const addDevice = `/relics/camera/add`;
 
 // organization
-export const organizationPage = `//relics/org/page`;
-export const addOrganization = `/relics/org/add`;
-export const delOrganization= `/relics/org/del`;
-export const getOrganizationDetail = `/relics/org/info//:orgId`;
-export const alterOrganization = `/relics/org/update`;
+export const organizationPage = `/relics/relics/org/page`;
+export const addOrganization = `/relics/relics/org/add`;
+export const delOrganization= `/relics/relics/org/del`;
+export const getOrganizationDetail = `/relicsrelics/org/info/:orgId`;
+export const alterOrganization = `/relics/relics/org/update`;
 
 
 // users

+ 2 - 1
src/request/index.ts

@@ -302,4 +302,5 @@ export const addDeviceFetch = (sn: string) =>
   });
 
 
-export * from './organization'
+export * from './organization'
+export * from './users'

+ 20 - 20
src/request/organization.ts

@@ -1,34 +1,34 @@
 import { sendFetch, PageProps } from './index'
+import { ResPage } from './type'
 import * as URL from "./URL";
 
-
-export const getOrgListFetch = (params: any) =>
-    sendFetch<PageProps<{
-        orgId: number
-        orgName: string
-        type: number
-    }>>(URL.organizationPage, {
-        method: "post",
-        body: JSON.stringify(params),
-    });
-
-
-type addOrgParamType = {
+export type AddOrgParamType= {
     ancestors: string
     contact: string
     orderNum: number
     orgId: number
     parentId: number
+    orgName:string
     password: string
-    type: number
+    type: number | null
     userName: string
+} 
+
+export type organizationType = {
+    orgId: number
+    orgName: string
+    type: number
 }
+
 export const addOrgFetch = (params: any) =>
-    sendFetch<PageProps<{
-        orgId: number
-        orgName: string
-        type: number
-    }>>(URL.organizationPage, {
+    sendFetch<PageProps<organizationType>>(URL.addOrganization, {
         method: "post",
         body: JSON.stringify(params),
-    });
+    });
+
+export const getOrgListFetch = (params: any) =>
+    sendFetch<ResPage<PageProps<organizationType>>>(URL.organizationPage, {
+        method: "post",
+        body: JSON.stringify(params),
+    });
+

+ 9 - 0
src/request/type.ts

@@ -11,10 +11,19 @@ import {
   WholeLinePolygonAttrib,
 } from "drawing-board";
 
+
+
+type UserInfoRoles = {
+  roleId: number
+  roleKey: string
+  roleName: string
+}
 export type UserInfo = {
   head: string;
   nickName: string;
   userName: string;
+  roles: UserInfoRoles[]
+  orgId: string
 };
 
 export type Relics = {

+ 17 - 0
src/request/users.ts

@@ -0,0 +1,17 @@
+import { sendFetch, PageProps } from './index'
+import { ResPage } from './type'
+import * as URL from "./URL";
+
+export type UserType = {
+    orgId: number
+    orgName: string
+    type: number
+}
+
+
+export const getUserpageFetch = (params: any) =>
+    sendFetch<ResPage<PageProps<UserType>>>(URL.userScenepage, {
+        method: "post",
+        body: JSON.stringify(params),
+    });
+

+ 6 - 0
src/store/organization.ts

@@ -0,0 +1,6 @@
+export const OrganizationTypeDesc = {
+  1: "省级",
+  2: "市级",
+  3: "县级",
+  4: "服务商",
+};

+ 135 - 0
src/view/organization-add.vue

@@ -0,0 +1,135 @@
+<template>
+  <!-- "ancestors": "",
+  "contact": "",
+  "orderNum": 0,
+  "orgId": 0,
+  "orgName": "",
+  "parentId": 0,
+  "password": "",
+  "type": 0,
+  "userName": "" -->
+  <el-form label-width="100px" :model="data" :rules="rules" ref="baseFormRef">
+    <el-form-item label="单位名称" prop="orgName" required>
+      <el-input v-model="data.orgName" style="width: 300px" :maxlength="500" placeholder="请输入" />
+    </el-form-item>
+    <el-form-item label="类型" prop="type" required>
+      <!-- <el-input v-model="data.type" style="width: 300px" :maxlength="500" placeholder="请输入" /> -->
+      <el-select style="width: 300px" v-model="data.type">
+        <el-option :value="Number(key)" :label="type" v-for="(type, key) in OrganizationTypeDesc" />
+      </el-select>
+    </el-form-item>
+    <el-form-item label="联系人" prop="contact" required>
+      <el-input v-model="data.contact" style="width: 300px" :maxlength="500" placeholder="请输入" />
+    </el-form-item>
+    <el-form-item label="账号" prop="userName" required>
+      <el-input v-model="data.userName" style="width: 300px" :maxlength="500" placeholder="请输入手机号" />
+    </el-form-item>
+    <el-form-item label="密码" prop="password" required>
+      <el-input autocomplete="off" readonly onfocus="this.removeAttribute('readonly');" v-model="data.password"
+        :type="addPassFlag ? 'text' : 'password'" style="width: 300px" :maxlength="500"
+        placeholder="请输入8-16位数字、字母大小写组合">
+        <template #suffix>
+          <span @click="addPassFlag = !addPassFlag" style="cursor: pointer;">
+            <el-icon v-if="addPassFlag">
+              <View />
+            </el-icon>
+            <el-icon v-else>
+              <Hide />
+            </el-icon>
+          </span>
+        </template>
+      </el-input>
+
+    </el-form-item>
+  </el-form>
+</template>
+
+<script setup lang="ts">
+import { QuiskExpose } from "@/helper/mount";
+import type { FormInstance, FormRules } from "element-plus";
+// import { ElMessage } from "element-plus";
+import { AddOrgParamType } from '@/request/organization'
+import { OrganizationTypeDesc } from '@/store/organization'
+import { ref, reactive, unref } from "vue";
+import { View, Hide } from '@element-plus/icons-vue';
+import { user } from '@/store/user'
+
+const addPassFlag = ref(false)//图标显示标识
+
+const baseFormRef = ref<FormInstance>();
+
+const rules = reactive<FormRules>({
+  orgName: [
+    { required: true, message: "请输入单位名称", trigger: "blur" },
+  ],
+  type: [
+    { required: true, message: "请选择类型", trigger: "change" },
+  ],
+  contact: [
+    { required: true, message: "请输入联系人", trigger: "blur" },
+  ],
+  userName: [
+    { required: true,pattern: /^1[3456789]\d{9}$/,message: "请输入正确手机号", trigger: "blur" },
+  ],
+  password: [
+    { required: true, pattern: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,16}$/, message: "请输入8-16位数字、字母大小写组合", trigger: "blur" },
+    { required: true, min: 8, message: '密码太短!', trigger: "blur" },
+  ],
+},)
+
+const props = defineProps<{
+  submit: (data: AddOrgParamType) => Promise<any>;
+}>();
+const data = ref<AddOrgParamType & {}>({
+  ancestors: "",
+  contact: "",
+  orderNum: 0,
+  orgId: 0,
+  orgName: "",
+  parentId: 0,
+  password: "",
+  type: null,
+  userName: ""
+});
+
+const setParentId = () => {
+  if (user.value) {
+    const isSuper = user.value.roles.filter(item => item.roleKey === "super_admin").length > 0;
+    data.value.parentId = isSuper ? 0 : Number(user.value.orgId)
+  }
+}
+
+defineExpose<QuiskExpose>({
+  async submit() {
+
+    if (unref(baseFormRef)) {
+      setParentId();
+      const res = await unref(baseFormRef)?.validate();
+      if (res) {
+        await props.submit(data.value as any as AddOrgParamType);
+      }
+    } else {
+      throw "";
+    }
+
+
+    // await baseForm.value.validate((valid: any, fields: any) => {
+    //   if (valid) {
+    //     throw "1111";
+    //   } else {
+    //     console.log('error submit!', fields)
+    //   }
+    // })
+
+    // try {
+    //   const res = await baseForm.value.validate();
+    //   console.log('res', res)
+
+
+    // } catch (error) {
+    //   throw error;
+    // }
+
+  },
+});
+</script>

+ 0 - 33
src/view/organization-edit.vue

@@ -1,33 +0,0 @@
-<template>
-  <el-form label-width="100px">
-    <el-form-item label="SN:" required>
-      <el-input
-        v-model="data.sn"
-        style="width: 250px"
-        :maxlength="500"
-        placeholder="请输入"
-      />
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { QuiskExpose } from "@/helper/mount";
-import { ElMessage } from "element-plus";
-import { ref } from "vue";
-
-const props = defineProps<{
-  submit: (sn: string) => Promise<any>;
-}>();
-const data = ref({ sn: "" });
-
-defineExpose<QuiskExpose>({
-  async submit() {
-    if (!data.value.sn) {
-      ElMessage.error("请输入SN!");
-      throw "请输入SN!";
-    }
-    await props.submit(data.value.sn);
-  },
-});
-</script>

+ 19 - 16
src/view/organization.vue

@@ -7,8 +7,8 @@
             <el-input v-model="pageProps.orgName" clearable style="width: 250px" placeholder="请输入" />
           </el-form-item>
           <el-form-item label="类型">
-            <el-select style="width: 250px" v-model="pageProps.orgId" clearable>
-              <el-option :value="Number(key)" :label="type" v-for="(type, key) in DeviceTypeDesc" />
+            <el-select style="width: 250px" v-model="pageProps.type" clearable>
+              <el-option :value="Number(key)" :label="type" v-for="(type, key) in OrganizationTypeDesc" />
             </el-select>
 
           </el-form-item>
@@ -26,12 +26,12 @@
 
     <div class="relics-content">
       <el-table :data="relicsArray" border>
-        <el-table-column label="单位名称" prop="cameraSn"></el-table-column>
-        <el-table-column label="类型" prop="cameraSn"></el-table-column>
-        <el-table-column label="单位账号" prop="cameraSn"></el-table-column>
-        <el-table-column label="单位联系人" prop="cameraSn"></el-table-column>
-        <el-table-column label="创建时间" prop="cameraSn"></el-table-column>
-        <el-table-column label="创建人" prop="cameraSn"></el-table-column>
+        <el-table-column label="单位名称" prop="orgName"></el-table-column>
+        <el-table-column label="类型" prop="type"></el-table-column>
+        <el-table-column label="单位账号" prop="userName"></el-table-column>
+        <el-table-column label="单位联系人" prop="contact"></el-table-column>
+        <el-table-column label="创建时间" prop="updateTime"></el-table-column>
+        <el-table-column label="创建人" prop="userId"></el-table-column>
         <el-table-column label="操作" width="100px" fixed="right">
           <template #default="{ row }">
             <el-button link type="danger" @click="() => { }" size="small">
@@ -59,10 +59,11 @@ import {
   addOrgFetch,
   PageProps
 } from "@/request";
-import { Device } from "@/request/type";
-import { DeviceTypeDesc } from "@/store/device";
+// import { Device } from "@/request/type";
+// import { DeviceTypeDesc } from "@/store/device";
 // import { ElMessageBox } from "element-plus";
-import { organizationEdit } from "./quisk";
+import { OrganizationTypeDesc } from '@/store/organization'
+import { organizationAdd } from "./quisk";
 import { debounce } from "@/util";
 
 const initProps: PageProps<{
@@ -78,13 +79,15 @@ const initProps: PageProps<{
 };
 const pageProps = ref({ ...initProps });
 const total = ref<number>(0);
-const relicsArray = ref<Device[]>([]);
+const relicsArray = ref<any[]>([]);
+
+// 1省级 2市级 3县级 4服务商
 
 const refresh = debounce(async () => {
   const data = await getOrgListFetch(pageProps.value);
-  debugger
-  // total.value = data.total;
-  // relicsArray.value = data.records;
+  console.log('data', data)
+  total.value = data.total;
+  relicsArray.value = data.records;
 });
 
 watch(pageProps, refresh, { deep: true, immediate: true });
@@ -92,7 +95,7 @@ onActivated(refresh);
 
 
 const addHandler = async () => {
-  await organizationEdit({ submit: addOrgFetch });
+  await organizationAdd({ submit: addOrgFetch });
   await refresh();
 };
 </script>

+ 2 - 2
src/view/quisk.ts

@@ -2,7 +2,7 @@ import { quiskMountFactory } from "@/helper/mount";
 import RelicsEdit from "./relics-edit.vue";
 import DeviceEdit from "./device-edit.vue";
 import SceneSelect from "./scene-select.vue";
-import OrganizationEdit from "./organization-edit.vue";
+import OrganizationAdd from "./organization-add.vue";
 
 export const relicsEdit = quiskMountFactory(RelicsEdit, {
   title: "创建文物",
@@ -18,7 +18,7 @@ export const selectScenes = quiskMountFactory(SceneSelect, {
   width: 1000,
 });
 
-export const organizationEdit = quiskMountFactory(OrganizationEdit, {
+export const organizationAdd = quiskMountFactory(OrganizationAdd, {
   title: "添加单位",
   width: 520,
 });

+ 3 - 3
src/view/users.vue

@@ -58,7 +58,7 @@
 <script lang="ts" setup>
 import { onActivated, ref, watch } from "vue";
 import {
-  getOrgListFetch,
+  getUserpageFetch,
   PageProps
 } from "@/request";
 import { Device } from "@/request/type";
@@ -76,8 +76,8 @@ const total = ref<number>(0);
 const relicsArray = ref<Device[]>([]);
 
 const refresh = debounce(async () => {
-  const data = await getOrgListFetch(pageProps.value);
-  debugger
+  const data = await getUserpageFetch(pageProps.value);
+
   // total.value = data.total;
   // relicsArray.value = data.records;
 });

+ 12 - 17
vite.config.ts

@@ -23,28 +23,23 @@ export default defineConfig({
     port: 5173,
     open: true,
     proxy: {
-      // "/api": {
-      //   target: "http://192.168.0.11:8324",
-      //   changeOrigin: true,
-      //   rewrite: (path) => path.replace(/^\/api/, ""),
-      // },
-      "/gear1": {
-        target: `http://devimages.apple.com/iphone/samples/bipbop`,
-        changeOrigin: true,
-        rewrite: (path) => path.replace(/^\/gear1/, "/gear1"),
-      },
       "/api": {
-        target: `http://sp.4dkankan.com`,
-        // target: `http://192.168.0.11:8324/relics/`,
+        target: "http://192.168.0.11:8324",
         changeOrigin: true,
-        rewrite: (path) => path.replace(/^\/api/, "/api"),
+        rewrite: (path) => path.replace(/^\/api/, ""),
       },
-      "/api/test": {
-        // target: `http://sp.4dkankan.com`,
-        target: `http://192.168.0.11:8324/`,
+      "/gear1": {
+        target: `http://devimages.apple.com/iphone/samples/bipbop`,
         changeOrigin: true,
-        rewrite: (path) => path.replace(/^\/api\/test/, "/api/test"),
+        rewrite: (path) => path.replace(/^\/gear1/, "/gear1"),
       },
+      // "/api": {
+      //   target: `http://sp.4dkankan.com`,
+      //   // target: `http://192.168.0.11:8324/relics/`,
+      //   changeOrigin: true,
+      //   rewrite: (path) => path.replace(/^\/api/, "/api"),
+      // },
+ 
     },
   },
 });