소스 검색

feat: 服务人员管理 - CRUD页面含新建编辑删除

- 列表页使用 basicLayout 对接 staffTable
- 新建/编辑使用 el-drawer 右侧滑出表单
- 密码提交时 MD5 加密,编辑支持原密码/新密码切换
- 状态列 el-switch 开关,确认后调用 changeStatus
- 行内编辑/删除按钮,提交带 loading 状态

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
xiaohaizhao 3 일 전
부모
커밋
97b353b5b9
4개의 변경된 파일468개의 추가작업 그리고 0개의 파일을 삭제
  1. 116 0
      src/bgj/personnelmanagement/index.vue
  2. 153 0
      src/bgj/personnelmanagement/modules/add.vue
  3. 189 0
      src/bgj/personnelmanagement/modules/edit.vue
  4. 10 0
      src/router/bgj.js

+ 116 - 0
src/bgj/personnelmanagement/index.vue

@@ -0,0 +1,116 @@
+<template>
+  <div>
+    <basicLayout
+      ref="list"
+      tableName="staffTable"
+      idName="sa_agents_service_hrid"
+      :apiId="{ query: 2026051913260102, del: 2026051913270102 }"
+    >
+      <template v-slot:titleLight>
+        <my-add class="inline-16" @onSuccess="onSuccess" />
+      </template>
+      <template v-slot:tbList="scope">
+        <div v-if="scope.data.column.columnname === 'status'">
+          <el-switch
+            :value="scope.data.column.data.status === 'ACTIVE'"
+            active-color="#13ce66"
+            inactive-color="#ff4949"
+            @change="handleStatusChange(scope.data.column.data, $event)"
+          />
+        </div>
+        <div v-else>
+          {{
+            scope.data.column.data[[scope.data.column.columnname]]
+              ? $t(scope.data.column.data[[scope.data.column.columnname]])
+              : "--"
+          }}
+        </div>
+      </template>
+      <template v-slot:tbOpreation="scope">
+        <my-edit
+          class="inline-16"
+          :data="scope.data.data"
+          @onSuccess="onSuccess"
+        />
+        <el-button
+          class="inline-16"
+          size="mini"
+          type="text"
+          style="color: #f56c6c"
+          :loading="deletingId === scope.data.data.sa_agents_service_hrid"
+          @click="handleDelete(scope.data.data)"
+        >{{ $t("删 除") }}</el-button>
+      </template>
+    </basicLayout>
+  </div>
+</template>
+
+<script>
+import MyAdd from "./modules/add.vue";
+import MyEdit from "./modules/edit.vue";
+
+export default {
+  components: {
+    MyAdd,
+    MyEdit,
+  },
+  data() {
+    return {
+      deletingId: null,
+    };
+  },
+  methods: {
+    onSuccess() {
+      this.$refs.list.listData();
+    },
+    async handleStatusChange(row, val) {
+      const action = val ? this.$t("启用") : this.$t("停用");
+      try {
+        await this.$confirm(
+          this.$t("确定") + action + row.name + "?",
+          this.$t("提示"),
+          { confirmButtonText: this.$t("确定"), cancelButtonText: this.$t("取消"), type: "warning" }
+        );
+      } catch {
+        this.$refs.list.listData();
+        return;
+      }
+      const res = await this.$api.requested({
+        classname: "webmanage.users.users",
+        method: "changeStatus",
+        content: {
+          userid: row.userid,
+          isactive: val ? 1 : 0,
+        },
+      });
+      this.tool.showMessage(res, () => {
+        this.$refs.list.listData();
+      });
+    },
+    async handleDelete(row) {
+      try {
+        await this.$confirm(
+          this.$t("确认删除") + row.name + "?",
+          this.$t("提示"),
+          { confirmButtonText: this.$t("确定"), cancelButtonText: this.$t("取消"), type: "warning" }
+        );
+      } catch {
+        return;
+      }
+      this.deletingId = row.sa_agents_service_hrid;
+      const res = await this.$api.requested({
+        id: 2026051913270102,
+        content: {
+          sa_agents_service_hrid: row.sa_agents_service_hrid,
+        },
+      });
+      this.tool.showMessage(res, () => {
+        setTimeout(() => {
+          this.deletingId = null;
+          this.$refs.list.listData();
+        }, 500);
+      });
+    },
+  },
+};
+</script>

+ 153 - 0
src/bgj/personnelmanagement/modules/add.vue

@@ -0,0 +1,153 @@
+<template>
+  <div>
+    <el-button size="small" type="primary" @click="show">{{ $t("新 建") }}</el-button>
+    <el-drawer
+      :title="$t('新建服务人员')"
+      :visible.sync="dialogFormVisible"
+      direction="rtl"
+      append-to-body
+      :show-close="false"
+      size="664px"
+      @close="onCancel"
+    >
+      <div class="drawer__panel">
+        <el-row :gutter="20">
+          <el-form
+            :model="form"
+            :rules="rules"
+            ref="form"
+            :label-width="tool.onlyZh('90px')"
+            label-position="right"
+            size="mini"
+          >
+            <el-col :span="24">
+              <el-form-item :label="$t('手机号')" prop="phonenumber">
+                <el-input v-model="form.phonenumber" :placeholder="$t('请输入手机号')" maxlength="11" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('登录密码')" prop="password">
+                <el-input v-model="form.password" :placeholder="$t('请输入登录密码')" show-password />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('姓名')" prop="name">
+                <el-input v-model="form.name" :placeholder="$t('请输入姓名')" maxlength="50" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('性别')" prop="sex">
+                <el-radio-group v-model="form.sex">
+                  <el-radio label="男">{{ $t("男") }}</el-radio>
+                  <el-radio label="女">{{ $t("女") }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('职位')" prop="position">
+                <el-input v-model="form.position" :placeholder="$t('请输入职位')" maxlength="50" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('备注')" prop="remarks">
+                <el-input
+                  type="textarea"
+                  v-model="form.remarks"
+                  :placeholder="$t('请输入备注')"
+                  maxlength="200"
+                />
+              </el-form-item>
+            </el-col>
+          </el-form>
+        </el-row>
+      </div>
+      <div class="fixed__btn__panel">
+        <el-button size="small" class="normal-btn-width" @click="onCancel">{{ $t("取 消") }}</el-button>
+        <el-button size="small" class="normal-btn-width" type="primary" :loading="loading" @click="onSubmit">{{ $t("确 定") }}</el-button>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import md5 from "js-md5";
+
+export default {
+  name: "add",
+  data() {
+    return {
+      dialogFormVisible: false,
+      loading: false,
+      form: {
+        phonenumber: "",
+        password: "",
+        name: "",
+        sex: "",
+        position: "",
+        remarks: "",
+      },
+      rules: {
+        phonenumber: [
+          { required: true, message: this.$t("请输入手机号"), trigger: "blur" },
+          {
+            pattern: /^1[3-9]\d{9}$/,
+            message: this.$t("请输入正确的手机号"),
+            trigger: "blur",
+          },
+        ],
+        password: [
+          { required: true, message: this.$t("请输入登录密码"), trigger: "blur" },
+          { min: 6, max: 20, message: this.$t("密码长度在6到20位之间"), trigger: "blur" },
+        ],
+        name: [
+          { required: true, message: this.$t("请输入姓名"), trigger: "blur" },
+        ],
+      },
+    };
+  },
+  methods: {
+    show() {
+      this.dialogFormVisible = true;
+    },
+    onCancel() {
+      this.dialogFormVisible = false;
+      this.$refs.form.resetFields();
+      this.form = {
+        phonenumber: "",
+        password: "",
+        name: "",
+        sex: "",
+        position: "",
+        remarks: "",
+      };
+    },
+    onSubmit() {
+      this.$refs.form.validate(async (valid) => {
+        if (!valid) return;
+
+        this.loading = true;
+        const res = await this.$api.requested({
+          id: 2026051913192002,
+          content: {
+            sa_agents_service_hrid: 0,
+            name: this.form.name,
+            phonenumber: this.form.phonenumber,
+            password: md5(this.form.password),
+            position: this.form.position,
+            sex: this.form.sex,
+            remarks: this.form.remarks,
+          },
+        });
+
+        this.tool.showMessage(res, () => {
+          setTimeout(() => {
+            this.loading = false;
+            this.dialogFormVisible = false;
+            this.$emit("onSuccess");
+          }, 500);
+        });
+      });
+    },
+  },
+};
+</script>

+ 189 - 0
src/bgj/personnelmanagement/modules/edit.vue

@@ -0,0 +1,189 @@
+<template>
+  <div>
+    <el-button size="mini" :type="btnType || 'text'" @click="show">{{ $t("编 辑") }}</el-button>
+    <el-drawer
+      :title="$t('编辑服务人员')"
+      :visible.sync="dialogFormVisible"
+      direction="rtl"
+      append-to-body
+      :show-close="false"
+      size="664px"
+      @close="onCancel"
+    >
+      <div class="drawer__panel">
+        <el-row :gutter="20">
+          <el-form
+            :model="form"
+            :rules="rules"
+            ref="form"
+            :label-width="tool.onlyZh('90px')"
+            label-position="right"
+            size="mini"
+          >
+            <el-col :span="24">
+              <el-form-item :label="$t('手机号')" prop="phonenumber">
+                <el-input v-model="form.phonenumber" :placeholder="$t('请输入手机号')" maxlength="11" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('登录密码')" prop="password" :rules="passwordType === 'new' ? rules.password : []">
+                <el-radio-group v-model="passwordType" style="margin-bottom: 8px">
+                  <el-radio label="keep">{{ $t("原密码") }}</el-radio>
+                  <el-radio label="new">{{ $t("新密码") }}</el-radio>
+                </el-radio-group>
+                <el-input
+                  v-if="passwordType === 'new'"
+                  v-model="form.password"
+                  :placeholder="$t('请输入新密码')"
+                  show-password
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('姓名')" prop="name">
+                <el-input v-model="form.name" :placeholder="$t('请输入姓名')" maxlength="50" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('性别')" prop="sex">
+                <el-radio-group v-model="form.sex">
+                  <el-radio label="男">{{ $t("男") }}</el-radio>
+                  <el-radio label="女">{{ $t("女") }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('职位')" prop="position">
+                <el-input v-model="form.position" :placeholder="$t('请输入职位')" maxlength="50" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="$t('备注')" prop="remarks">
+                <el-input
+                  type="textarea"
+                  v-model="form.remarks"
+                  :placeholder="$t('请输入备注')"
+                  maxlength="200"
+                />
+              </el-form-item>
+            </el-col>
+          </el-form>
+        </el-row>
+      </div>
+      <div class="fixed__btn__panel">
+        <el-button size="small" class="normal-btn-width" @click="onCancel">{{ $t("取 消") }}</el-button>
+        <el-button size="small" class="normal-btn-width" type="warning" :loading="loading" @click="onSubmit">{{ $t("保 存") }}</el-button>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import md5 from "js-md5";
+
+export default {
+  name: "edit",
+  props: {
+    data: {
+      type: Object,
+      default: () => ({}),
+    },
+    btnType: {
+      type: String,
+      default: "text",
+    },
+  },
+  data() {
+    return {
+      dialogFormVisible: false,
+      loading: false,
+      passwordType: "keep",
+      form: {
+        phonenumber: "",
+        password: "",
+        name: "",
+        sex: "",
+        position: "",
+        remarks: "",
+      },
+      rules: {
+        phonenumber: [
+          { required: true, message: this.$t("请输入手机号"), trigger: "blur" },
+          {
+            pattern: /^1[3-9]\d{9}$/,
+            message: this.$t("请输入正确的手机号"),
+            trigger: "blur",
+          },
+        ],
+        name: [
+          { required: true, message: this.$t("请输入姓名"), trigger: "blur" },
+        ],
+        password: [
+          { required: true, message: this.$t("请输入新密码"), trigger: "blur" },
+          { min: 6, max: 20, message: this.$t("密码长度在6到20位之间"), trigger: "blur" },
+        ],
+      },
+    };
+  },
+  watch: {
+    passwordType(val) {
+      if (val === "keep") {
+        this.form.password = "";
+        this.$refs.form.clearValidate("password");
+      }
+    },
+  },
+  methods: {
+    show() {
+      this.passwordType = "keep";
+      this.form = {
+        phonenumber: this.data.phonenumber || "",
+        password: "",
+        name: this.data.name || "",
+        sex: this.data.sex || "",
+        position: this.data.position || "",
+        remarks: this.data.remarks || "",
+      };
+      this.dialogFormVisible = true;
+    },
+    onCancel() {
+      this.dialogFormVisible = false;
+      this.$refs.form.resetFields();
+    },
+    onSubmit() {
+      this.$refs.form.validate(async (valid) => {
+        if (!valid) return;
+
+        this.loading = true;
+        const content = {
+          sa_agents_service_hrid: this.data.sa_agents_service_hrid,
+          name: this.form.name,
+          phonenumber: this.form.phonenumber,
+          position: this.form.position,
+          sex: this.form.sex,
+          remarks: this.form.remarks,
+        };
+
+        if (this.passwordType === "keep") {
+          content.password = this.data.password;
+        } else if (this.form.password) {
+          content.password = md5(this.form.password);
+        }
+
+        const res = await this.$api.requested({
+          id: 2026051913192002,
+          content,
+        });
+
+        this.tool.showMessage(res, () => {
+          setTimeout(() => {
+            this.loading = false;
+            this.dialogFormVisible = false;
+            this.$emit("onSuccess");
+          }, 500);
+        });
+      });
+    },
+  },
+};
+</script>

+ 10 - 0
src/router/bgj.js

@@ -196,6 +196,16 @@ const bgj = [
           import(/* webpackChunkName: "about" */ '@/bgj/workOrderManage/modules/detail'),
       },
     ],
+  },
+  {
+    path: '/personnelmanagement',
+    name: 'personnelmanagement',
+    meta: {
+      title: '服务人员管理',
+      ast_nav: true,
+      keeproute: true,
+    },
+    component: () => import(/* webpackChunkName: "about" */ '@/bgj/personnelmanagement/index'),
   }
 ];
 export default bgj;