Quellcode durchsuchen

签约,经历

martin.ma vor 3 Jahren
Ursprung
Commit
d93107c3d0

+ 2 - 13
components/sign/step-education.vue

@@ -99,8 +99,8 @@
                 @change="val => handleImageUrl(idx, val)"
               ></uploader>
             </div>
-            <footer class="sign-new-education-footer">
-              <div class="sign-new-education-tips">
+            <footer class="sign-new-form-footer">
+              <div class="sign-new-form-tips">
                 <p>学信网在线验证报告, 例如:https://www.proginn.com</p>
                 <p>
                   注:学历证明可以是毕业证图片或学信网在线验证报告(二选一即可)
@@ -449,15 +449,4 @@ export default {
     line-height: 17px;
   }
 }
-
-.sign-new-education-footer {
-  display: flex;
-}
-.sign-new-education-tips {
-  flex: 1;
-}
-.sign-new-btn-area {
-  margin-top: 24px;
-  display: flex;
-}
 </style>

+ 312 - 0
components/sign/step-experience-form.vue

@@ -0,0 +1,312 @@
+<template>
+  <div class="sign-new-work-experience-form">
+    <el-form ref="form" :rules="rules" :model="item" label-width="147px">
+      <div class="header">
+        <!-- <el-date-picker
+          v-model="item.date"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+        ></el-date-picker>-->
+        <date-range class="range" v-model="item.date"></date-range>
+        <el-select
+          v-model="item.company"
+          allow-create
+          filterable
+          remote
+          reserve-keyword
+          placeholder="请输入公司名称"
+          :remote-method="fetchCompany"
+          :loading="loadingCompany"
+        >
+          <el-option
+            v-for="item in companys"
+            :key="item.label"
+            :label="item.label"
+            :value="item.label"
+          ></el-option>
+        </el-select>
+        <!-- TODO:公司规模未绑定 -->
+        <el-select
+          v-model="item.company"
+          allow-create
+          filterable
+          remote
+          reserve-keyword
+          placeholder="公司规模"
+          :remote-method="fetchCompany"
+          :loading="loadingCompany"
+        >
+          <el-option
+            v-for="item in companys"
+            :key="item.label"
+            :label="item.label"
+            :value="item.label"
+          ></el-option>
+        </el-select>
+
+        <el-select
+          v-model="item.title"
+          allow-create
+          filterable
+          remote
+          reserve-keyword
+          placeholder="请输入职位"
+          :remote-method="fetchTitle"
+          :loading="loadingTitle"
+        >
+          <el-option
+            v-for="item in titles"
+            :key="item.label"
+            :label="item.label"
+            :value="item.label"
+          ></el-option>
+        </el-select>
+      </div>
+      <div class="content">
+        <el-input
+          type="textarea"
+          :rows="7"
+          maxlength="5000"
+          minlength="60"
+          placeholder="请从主要工作内容、成就等方面,描述你的工作经历,字数要求:60-5000字符"
+          v-model="item.description"
+        ></el-input>
+        <uploader
+          :imageUrl="item.work_certify_img"
+          title="工作证明"
+          @change="val => handleImageUrl(idx, val)"
+        ></uploader>
+      </div>
+      <footer class="sign-new-form-footer">
+        <div class="sign-new-form-tips">
+          <p>
+            注:有效的工作证明包括:工牌/入职通知邮件/在职证明/公司邮箱截图/公司获奖证书/钉钉截图/离职证明/社保公积金证明等(其中之一即可,截图中需同时出现公司信息和个人信息,才能作为有效工作证明,并与目前公司相一致)
+          </p>
+        </div>
+        <div class="sign-new-btn-area">
+          <span class="opts">
+            <el-button type="danger" @click="handleDelete(item, idx)"
+              >删除</el-button
+            >
+            <el-button type="info" @click="handleCancel(item, idx)"
+              >取消</el-button
+            >
+            <el-button type="primary" @click="handleConfirm(item, idx)"
+              >保存</el-button
+            >
+          </span>
+        </div>
+      </footer>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import uploader from "@/components/uploader";
+import dateRange from "@/components/date-range";
+
+export default {
+  props: ["idx", "item", "handleDelete", "handleCancel", "handleConfirm"],
+  components: {
+    uploader,
+    dateRange
+  },
+  data() {
+    return {
+      rules: {
+        // date: [
+        //   {
+        //     required: true,
+        //     message: "请设置开始时间/结束时间",
+        //     trigger: "change"
+        //   }
+        // ],
+        // company: [
+        //   {
+        //     required: true,
+        //     message: "请设置公司名称/职位",
+        //     trigger: "change"
+        //   }
+        // ],
+        // title: [
+        //   {
+        //     required: true,
+        //     message: "请设置公司名称/职位",
+        //     trigger: "change"
+        //   }
+        // ],
+        // description: [
+        //   { min: 60, message: "经历描述不少于60字符", trigger: "blur" }
+        // ]
+        name: [
+          {
+            required: true,
+            message: "作品名称不得为空",
+            trigger: "blur"
+          },
+          { max: 50, message: "作品名称不得超过50字符", trigger: "blur" },
+          {
+            validator: (rule, value, callback) => {
+              if (/[&¥%\/\*]+/.test(value)) {
+                callback(new Error("作品名称不包含特殊字符"));
+              } else {
+                callback();
+              }
+            },
+            trigger: "blur"
+          }
+        ],
+        description: [
+          {
+            required: true,
+            message: "作品简介不得为空",
+            trigger: "blur"
+          },
+          { min: 60, message: "作品简介不得低于60字符", trigger: "blur" }
+        ],
+        industry_id: [
+          {
+            required: true,
+            message: "行业类型不得为空",
+            trigger: "change"
+          }
+        ],
+        function_ops: [
+          {
+            required: true,
+            message: "关键功能不得为空",
+            trigger: "change"
+          }
+        ],
+        duty: [
+          {
+            required: true,
+            message: "作品职责不得为空",
+            trigger: "blur"
+          },
+          { min: 15, message: "作品职责不得低于15字符", trigger: "blur" },
+          { max: 200, message: "作品职责不得高于200字符", trigger: "blur" }
+        ]
+      },
+      companys: [],
+      loadingCompany: false,
+      titles: [],
+      loadingTitle: false
+    };
+  },
+  computed: {},
+  async mounted() {},
+  methods: {
+    async handleSubmit(idx) {
+      this.$refs["form"].validate(async valid => {
+        if (valid) {
+          console.log("submit!", this.item);
+          const item = this.item;
+          this.onSubmit(this.item, idx);
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+    async fetchCompany(keyword) {
+      this.loadingCompany = true;
+      const res = await this.$axios.$post("/api/simple_data/select_company", {
+        keyword
+      });
+      this.loadingCompany = false;
+      const data = res.data || [];
+      this.companys = data.map(it => ({ value: it.id, label: it.name }));
+    },
+    async fetchTitle(keyword) {
+      this.loadingTitle = true;
+      const res = await this.$axios.$post("/api/simple_data/select_title", {
+        keyword
+      });
+      this.loadingTitle = false;
+      const data = res.data || [];
+      this.titles = data.map(it => ({ value: it.id, label: it.name }));
+    },
+    handleImageUrl(idx, url) {
+      this.item.work_certify_img = url;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.sign-new-work-experience-form {
+  padding: 20px 0;
+
+  > form {
+    .header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 10px;
+    }
+
+    .opts {
+      display: flex;
+      align-items: center;
+
+      .el-button {
+        margin-left: 5px;
+      }
+    }
+
+    .el-select,
+    .el-input {
+      width: 136px;
+      margin-right: 10px;
+
+      .el-input--suffix .el-input__inner {
+        padding-right: 0;
+      }
+    }
+
+    .to {
+      margin-right: 10px;
+    }
+
+    .times {
+      .el-checkbox {
+        width: 88px;
+      }
+
+      .el-input {
+        width: 136px;
+      }
+    }
+
+    .content {
+      display: flex;
+      justify-content: space-between;
+      align-items: flex-start;
+      margin-top: 10px;
+
+      .el-textarea {
+        display: flex;
+        width: 610px;
+        height: 162px;
+      }
+    }
+  }
+
+  footer {
+    margin-top: 10px;
+
+    p {
+      margin-top: 15px;
+      font-size: 12px;
+      font-family: PingFangSC-Regular;
+      font-weight: 400;
+      color: rgba(145, 154, 167, 1);
+      line-height: 17px;
+    }
+  }
+}
+</style>

+ 36 - 3
components/sign/step-experience.vue

@@ -4,20 +4,44 @@
       完善经历和技能信息,<b>技能</b>将直接用于<b>派单匹配</b>,确保准确,完善
     </div>
     <div class="sign-experience-main">
-      <stepEducation></stepEducation>
+      <!-- 教育经历 -->
+      <div class="sign-experience-item">
+        <stepEducation></stepEducation>
+      </div>
+
+      <!-- 工作经历 -->
+      <div class="sign-experience-item">
+        <stepWorkExperienceVue></stepWorkExperienceVue>
+      </div>
+
+      <!-- 技能 -->
+      <div class="sign-experience-item">
+        <stepSkills></stepSkills>
+      </div>
+
+      <!-- 个人介绍 -->
+      <div class="sign-experience-item">
+        <stepProfile></stepProfile>
+      </div>
     </div>
 
     <div class="sign-new-next">
-      <div class="sign-new-next-btn">下一步</div>
+      <div class="sign-new-next-btn">完成签约</div>
     </div>
   </div>
 </template>
 
 <script>
 import stepEducation from "./step-education.vue";
+import stepWorkExperienceVue from "./step-work-experience.vue";
+import stepSkills from "./step-skills.vue";
+import stepProfile from "./step-profile.vue";
 export default {
   components: {
-    stepEducation
+    stepEducation,
+    stepWorkExperienceVue,
+    stepSkills,
+    stepProfile
   }
 };
 </script>
@@ -26,4 +50,13 @@ export default {
 .sign-experience-main {
   margin-top: 60px;
 }
+.sign-experience-item {
+  margin-top: 60px;
+}
+.sign-new-experience {
+  padding-bottom: 30px;
+  .sign-new-next {
+    margin-top: 100px;
+  }
+}
 </style>

+ 152 - 0
components/sign/step-profile.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="sign-new-profile" id="profile">
+    <header class="sign-new-header">
+      <div class="sign-new-header-title">个人介绍</div>
+      <div v-if="editing" class="opts">
+        <el-button
+          class="sign-new-profile-btn"
+          type="info"
+          @click="editing = false"
+          >取消</el-button
+        >
+        <el-button class="sign-new-profile-btn" type="primary" @click="onSubmit"
+          >保存</el-button
+        >
+      </div>
+      <div v-else class="opts">
+        <el-button
+          class="sign-new-profile-btn"
+          type="primary"
+          @click="handleEdit"
+          >编辑</el-button
+        >
+      </div>
+    </header>
+    <div class="sign-new-profile-main">
+      <div v-if="!content && !editing" class="empty">
+        点击右上角“编辑”按钮添加个人介绍
+      </div>
+      <div v-else-if="editing" class="edit">
+        <editor
+          :hideImage="true"
+          :content="content"
+          @change="handleChange"
+          :placeholder="placeholder"
+        ></editor>
+      </div>
+      <!-- <div v-else class="show" v-html="content"></div> -->
+      <div v-else class="show ql-snow ql-editor" v-html="content"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import editor from "@/components/editor";
+
+export default {
+  data() {
+    return {
+      editing: false,
+      content: "",
+      placeholder:
+        "我是程序员客栈的【昵称】,一名【二级方向】;\n我毕业于【大学名称】,担任过【公司1】的【职位】,担任过【公司2】的【职位】;\n负责过【项目1名称】,【项目2名称】,【项目3名称】的开发;\n熟练使用【技术栈1】,【技术栈2】,【技术栈3】,【技术栈4】,【技术栈5】;\n如果我能帮上您的忙,请点击“立即预约”或“发布需求”!"
+    };
+  },
+  components: { editor },
+  watch: {
+    // content: function(val) {
+    //   console.log(val);
+    // }
+  },
+  computed: {
+    ...mapState(["userinfo"])
+  },
+  async mounted() {
+    let res = await this.$axios.$post("/api/user/get_resume");
+    this.content = res.data ? res.data.personaldetails : "";
+  },
+  methods: {
+    handleEdit() {
+      if (this.userinfo && this.userinfo.realname_verify_status === "0") {
+        this.$message.error("请先进行实名认证");
+        return;
+      }
+      this.editing = true;
+    },
+    handleChange(val) {
+      this.content = val;
+    },
+    async onSubmit() {
+      this.cnzz("签约", "签约页面+个人介绍保存", "");
+      if (!this.content) {
+        this.$message.error("请输入个人介绍");
+        return false;
+      }
+      if (this.content.length < 150) {
+        this.$message.error("个人介绍不得低于150字");
+        return false;
+      }
+      if (!this.content.length > 3000) {
+        this.$message.error("个人介绍不得 超过3000字");
+        return false;
+      }
+      const formData = {
+        personaldetails: this.content
+      };
+      let res = await this.$axios.$post("/api/user/update_resume", formData);
+      if (res.status === 1) {
+        this.$message.success("保存成功!");
+        this.editing = false;
+      } else {
+        this.$message.error(res.info);
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.sign-new-profile {
+  .sign-new-profile-main {
+    margin-top: 30px;
+  }
+  .edit {
+    padding: 10px;
+    min-height: 244px;
+    border-radius: 4px;
+    border: 1px solid #dcdfe6;
+
+    > div {
+      border: 0 !important;
+    }
+    & > .ql-toolbar.ql-snow {
+      border: 0 !important;
+    }
+  }
+
+  .show {
+    padding: 20px 0;
+    * {
+      word-break: break-all;
+    }
+  }
+  .empty {
+    margin: 112px auto 104px;
+    font-size: 27px;
+    font-family: PingFangSC-Regular;
+    font-weight: 400;
+    text-align: center;
+    color: rgba(205, 205, 205, 1);
+    line-height: 38px;
+  }
+  .sign-new-header {
+    border: none;
+  }
+}
+.sign-new-profile-btn {
+  height: 34px;
+  padding: 0 20px;
+  line-height: 34px;
+}
+</style>

+ 386 - 0
components/sign/step-skills.vue

@@ -0,0 +1,386 @@
+<template>
+  <div class="sign-new-skills" id="skill">
+    <header class="sign-new-header">
+      <div class="sign-new-header-title">技能</div>
+      <span>
+        <el-button @click="handleAdd" type="text" icon="el-icon-plus"
+          >添加</el-button
+        >
+      </span>
+    </header>
+    <div v-if="skills.length > 0">
+      <template v-for="(item, idx) in skills">
+        <div
+          v-if="editingItem.indexOf(idx) < 0"
+          :key="item.skill_name"
+          class="show"
+        >
+          <h4>
+            <span>{{
+              `技能名称: ${item.skill_name} 经验自评:${item.skill_level}分 `
+            }}</span>
+            <el-button @click="editItem(idx)" type="text">编辑</el-button>
+          </h4>
+        </div>
+        <div v-else :key="`skill_${item.skill_id}`" class="edit">
+          <el-form
+            ref="form"
+            :rules="rules"
+            :model="item"
+            label-width="80px"
+            label-position="left"
+          >
+            <div class="header">
+              <el-form-item label="技能名称:" prop="skill_name">
+                <el-cascader
+                  v-model="item.skill_name"
+                  :show-all-levels="false"
+                  :placeholder="item.skill_name || '请选择单个技能'"
+                  :options="skillList"
+                  :props="{ expandTrigger: 'hover', emitPath: 'false' }"
+                />
+              </el-form-item>
+              <el-form-item label="经验自评:" prop="skill_level">
+                <el-select
+                  :style="{ width: '130px' }"
+                  v-model="item.skill_level"
+                  placeholder="选择分数"
+                >
+                  <el-option
+                    v-for="level in 5"
+                    :label="`${level}分`"
+                    :key="level"
+                    :value="level"
+                  ></el-option>
+                </el-select>
+              </el-form-item>
+              <span class="tips">1分为新入门,5分为满分</span>
+            </div>
+          </el-form>
+          <div class="sign-new-skill-btn">
+            <span class="opts">
+              <el-button type="danger" @click="handleDelete(item, idx)"
+                >删除</el-button
+              >
+              <el-button type="info" @click="handleCancel(item, idx)"
+                >取消</el-button
+              >
+              <el-button type="primary" @click="onSubmit(item, idx)"
+                >保存</el-button
+              >
+            </span>
+          </div>
+        </div>
+      </template>
+    </div>
+    <div v-else class="empty">点击右上角“添加”按钮添加技能</div>
+  </div>
+</template>
+
+<script>
+import uploader from "@/components/uploader";
+import instance from "../../plugins/axios";
+
+export default {
+  data() {
+    return {
+      // editing: true,
+      editingItem: [],
+      rules: {
+        // skill_name: [{ required: true, message: "请输入技能全名", trigger: "blur" }]
+      },
+      init: {
+        skill_name: "123",
+        skill_level: "",
+        skill_id: ""
+      },
+      skills: [
+        // {
+        //   skill_name: "Javscript",
+        //   skill_level: "5"
+        // }
+      ],
+      originSkills: [],
+      current: null,
+      skillList: [],
+      loadingSkill: false
+    };
+  },
+  components: {
+    uploader
+  },
+  computed: {},
+  watch: {},
+  async mounted() {
+    this.getData();
+    this.fetchSkill();
+  },
+  methods: {
+    async getData() {
+      let res = await this.$axios.$post("/api/user_skills/list_by_user");
+      this.skills = res.data || [];
+    },
+    async onSubmit(item, idx) {
+      this.cnzz("签约", "签约页面+技能保存", "");
+      console.log("submit!", item);
+      if (!item.skill_name) {
+        this.$message.error("请填写技能名称!");
+        return;
+      }
+      if (!item.skill_level) {
+        this.$message.error("请选择技能自评!");
+        return;
+      }
+      if (item.skill_name.indexOf(",") > -1) {
+        const skills = item.skill_name.split(",");
+        console.log(skills);
+        item.skill_name = skills[skills.length - 1];
+        console.log("--------------", item.skill_name);
+      }
+
+      if (item.skill_name instanceof Array && item.skill_name.length > 0) {
+        item.skill_name = item.skill_name[item.skill_name.length - 1];
+      }
+      const data = {
+        skill_level: item.skill_level,
+        skill_name: item.skill_name
+      };
+      if (item.skill_id) {
+        data.skill_id = item.skill_id;
+      }
+      if (item.id) {
+        data.id = item.id;
+      }
+      const res = await this.$axios.$post("/api/user_skills/save", data);
+      if (res.status === 1) {
+        this.$message.success("保存成功!");
+        this.init = {
+          skill_name: "",
+          skill_level: "",
+          skill_id: ""
+        };
+        this.editingItem = [];
+        this.originSkills.splice(idx, 1, item);
+      } else {
+        // this.$message.error(res.info);
+      }
+    },
+    async fetchSkill(keyword) {
+      this.loadingSkill = true;
+      const res = await this.$axios.$post("api/userSkills/getSkillList", {
+        keyword
+      });
+      this.loadingSkill = false;
+      const data = res.data || [];
+      this.skillList = data.map(it => {
+        let children = [];
+        if (it.child && it.child.length > 0)
+          children = it.child.map(child => ({
+            label: child.skill_name,
+            value: child.skill_name
+          }));
+        return {
+          value: it.occupation_name,
+          label: it.occupation_name,
+          children: children
+        };
+      });
+    },
+    handleAdd() {
+      if (this.editingItem.length > 0 && !this.skills[this.editingItem[0]].id) {
+        this.$message.error("请先保存现有修改");
+        return;
+      }
+      this.skills.push(this.init);
+      this.editingItem = [this.skills.length - 1];
+    },
+    async handleDelete(item, idx) {
+      const deleteComplete = () => {
+        this.$message({
+          type: "success",
+          message: "删除成功!"
+        });
+        this.skills.splice(idx, 1);
+        this.editingItem = [];
+      };
+      this.$confirm("确认删除该技能?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(async () => {
+          if (item.id) {
+            const res = await this.$axios.$post("/api/user_skills/delete", {
+              id: item.id
+            });
+            if (res.status === 1) {
+              deleteComplete();
+              this.getData();
+            }
+          } else {
+            deleteComplete();
+          }
+        })
+        .catch(err => {
+          console.log(err);
+          this.$message({
+            type: "info",
+            message: "已取消删除"
+          });
+        });
+    },
+    handleCancel(item, idx) {
+      this.editingItem = [];
+      if (!item.skill_id) {
+        this.skills.splice(idx, 1);
+      }
+    },
+    editItem(idx) {
+      console.log("editItem:" + idx);
+      this.editingItem = [idx];
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.sign-new-skills {
+  header .el-icon-plus {
+    font-size: 18px;
+  }
+
+  .edit {
+    padding: 20px 0;
+
+    .header {
+      display: flex;
+      align-items: center;
+
+      .tips {
+        margin-right: 5px;
+      }
+    }
+
+    > form {
+      .el-form-item {
+        margin-bottom: 0;
+      }
+
+      .header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 10px;
+      }
+
+      .opts {
+        display: flex;
+        align-items: center;
+
+        .el-button {
+          margin-left: 5px;
+        }
+      }
+
+      .el-select,
+      .el-input {
+        width: 136px;
+        margin-right: 10px;
+
+        .el-input--suffix .el-input__inner {
+          padding-right: 0;
+        }
+      }
+
+      .to {
+        margin-right: 10px;
+      }
+
+      .times {
+        .el-checkbox {
+          width: 88px;
+        }
+
+        .el-input {
+          width: 136px;
+        }
+      }
+
+      .content {
+        display: flex;
+        justify-content: space-between;
+        align-items: flex-start;
+        margin-top: 10px;
+
+        .el-textarea {
+          display: flex;
+          width: 766px;
+          height: 162px;
+        }
+      }
+    }
+  }
+
+  .show {
+    padding: 23px 0 23px 0;
+    border-bottom: 1px solid #ebeef5;
+
+    &:last-of-type {
+      border: 0;
+    }
+
+    h4 {
+      display: flex;
+      justify-content: space-between;
+      height: 44px;
+      font-size: 14px;
+      font-family: PingFangSC-Medium;
+      font-weight: 500;
+      /* color: #308eff; */
+      line-height: 44px;
+    }
+
+    p {
+      margin-top: 8px;
+      font-size: 14px;
+      font-family: PingFangSC-Regular;
+      font-weight: 400;
+      color: rgba(102, 102, 102, 1);
+      line-height: 24px;
+    }
+  }
+
+  .empty {
+    margin: 112px auto 104px;
+    font-size: 27px;
+    font-family: PingFangSC-Regular;
+    font-weight: 400;
+    text-align: center;
+    color: rgba(205, 205, 205, 1);
+    line-height: 38px;
+  }
+
+  footer p {
+    margin-top: 15px;
+    width: 766px;
+    font-size: 12px;
+    font-family: PingFangSC-Regular;
+    font-weight: 400;
+    color: rgba(145, 154, 167, 1);
+    line-height: 17px;
+  }
+}
+
+.sign-new-skill-btn {
+  margin-top: 24px;
+  text-align: right;
+}
+</style>
+
+<style lang="scss">
+.sign-new-skills {
+  .el-form-item__label {
+    line-height: 40px;
+  }
+}
+</style>

+ 383 - 0
components/sign/step-work-experience.vue

@@ -0,0 +1,383 @@
+<template>
+  <div class="info" id="workexp">
+    <header class="sign-new-header">
+      <div class="sign-new-header-title">工作经历</div>
+      <span>
+        <el-button
+          style="margin-right:30px"
+          v-if="experience.length > 0"
+          @click="showRankDialog"
+          type="text"
+          >设置优先展示</el-button
+        >
+        <el-dialog
+          title="设置优先展示工作经历"
+          :visible.sync="rankDialog"
+          :before-close="handleRankClose"
+        >
+          <el-form ref="form" :model="rankForm" class="first-form">
+            <el-radio-group v-model="rankForm.first">
+              <template v-for="(item, idx) in experience">
+                <el-radio :label="item.id" :value="item.id" :key="item.id">
+                  <div class="first-radio">
+                    <span class="des">
+                      <span>{{ item.company }}</span>
+                      <span>{{ item.title }}</span>
+                    </span>
+                    <el-button @click="editItem(item, idx)" type="text"
+                      >编辑</el-button
+                    >
+                  </div>
+                </el-radio>
+              </template>
+            </el-radio-group>
+          </el-form>
+          <div class="first-tips">
+            <h6>温馨提示</h6>
+            <p>
+              1.
+              只有上传过工作证明且通过认证的工作经历,才可选择设置为"优先展示工作经历"
+              <br />2. 修改公司,
+              职位信息,"保存"成功后,客栈将在一个工作日内完成审核,审核通过后,即可生效
+            </p>
+          </div>
+          <span slot="footer" class="dialog-footer">
+            <el-button @click="rankDialog = false">取 消</el-button>
+            <el-button type="primary" @click="handleRank">确 定</el-button>
+          </span>
+        </el-dialog>
+        <el-button @click="handleAdd" type="text" icon="el-icon-plus"
+          >添加</el-button
+        >
+      </span>
+    </header>
+    <div v-if="experience.length > 0">
+      <template v-for="(item, idx) in experience">
+        <div v-if="editingItem.indexOf(idx) < 0" :key="item.id" class="show">
+          <h4>
+            <span>{{
+              `${item.start_time} - ${item.end_time || "至今"} ${
+                item.company
+              } ${item.title}`
+            }}</span>
+            <span v-if="item.is_main == '1'" class="first">优先展示</span>
+            <span v-if="item.isAuth == 1" class="verify">已认证</span>
+            <el-button @click="editItem(item, idx)" type="text">编辑</el-button>
+          </h4>
+          <p>{{ item.description }}</p>
+        </div>
+        <stepExperienceForm
+          v-else
+          :key="`experience${idx}`"
+          :idx="idx"
+          :item="item"
+          :handleCancel="handleCancel"
+          :handleConfirm="handleConfirm"
+          :handleDelete="handleDelete"
+        ></stepExperienceForm>
+      </template>
+    </div>
+    <div v-else class="empty">点击右上角“添加”按钮添加工作经历</div>
+  </div>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import experienceForm from "./experience-form";
+import stepExperienceForm from "./step-experience-form";
+
+export default {
+  data() {
+    return {
+      // editing: true,
+      editingItem: [],
+      rules: {},
+      init: {
+        work_certify_img: "",
+        start_time: "",
+        date: [],
+        end_time: "",
+        company: "",
+        title: "",
+        is_main: 0,
+        description: ""
+      },
+      experience: [],
+      originExperience: [],
+      current: null,
+      rankDialog: false,
+      rankForm: {
+        first: ""
+      }
+    };
+  },
+  components: {
+    experienceForm,
+    stepExperienceForm
+  },
+  computed: {
+    ...mapState(["userinfo"])
+  },
+  watch: {},
+  async mounted() {
+    this.getData();
+  },
+  methods: {
+    async onSubmit() {
+      console.log("submit!", this.originExperience);
+      if (this.originExperience.length > 10) {
+        this.$message.error("最多可添加10项工作经历!");
+      }
+      const res = await this.$axios.$post("/api/user_experience/save_all", {
+        data: JSON.stringify(this.originExperience)
+      });
+      if (res.status === 1) {
+        this.$message.success("保存成功!");
+        this.getData();
+      } else if (res.status === 2 && res.info.indexOf("管理员审核") > -1) {
+        // 保存工作经历,需要审核时,同样重新获取数据
+        this.getData();
+      }
+    },
+    async getData() {
+      const res = await this.$axios.$post("/api/user_experience/get_my_list");
+      const data = res.data || [];
+      const experience = data.map((it, index) => {
+        if (it.is_main == "1") {
+          this.rankForm.first = it.id;
+        }
+        return {
+          ...it,
+          date: [it.start_time, it.end_time]
+        };
+      });
+      this.experience = experience;
+      this.originExperience = data;
+    },
+    handleRankClose() {
+      this.rankDialog = false;
+      // this.rankForm = {
+      //   first: ""
+      // };
+    },
+    handleRank() {
+      let idx = 0;
+      this.experience.map((it, index) => {
+        if (it.id == this.rankForm.first) {
+          idx = index;
+        }
+        return it;
+      });
+      // this.experience.forEach((item, index) => {
+      //   if (idx === index) {
+      //     item.is_main = 1;
+      //   } else {
+      //     item.is_main = 0;
+      //   }
+      // })
+      this.originExperience.forEach((item, index) => {
+        if (idx === index) {
+          item.is_main = 1;
+        } else {
+          item.is_main = 0;
+        }
+      });
+
+      this.onSubmit();
+      this.rankDialog = false;
+    },
+    handleAdd() {
+      if (this.userinfo && this.userinfo.realname_verify_status === "0") {
+        this.$message.error("请先进行实名认证");
+        return;
+      }
+      if (
+        this.editingItem.length > 0 &&
+        !this.experience[this.editingItem[0]].id
+      ) {
+        this.$message.error("请先保存现有修改");
+        return;
+      }
+      const _init = JSON.parse(JSON.stringify(this.init));
+      this.experience.push(_init);
+      this.editingItem = [this.experience.length - 1];
+    },
+    handleDelete(item, idx) {
+      this.experience.splice(idx, 1);
+      this.originExperience.splice(idx, 1);
+      this.editingItem = [];
+      this.onSubmit();
+    },
+    handleCancel(item, idx) {
+      const origin = this.originExperience.slice(idx, idx + 1)[0];
+
+      if (!origin) {
+        this.editingItem = [];
+        this.experience.splice(idx, 1);
+      } else {
+        const originCopy = JSON.parse(JSON.stringify(origin));
+        originCopy.date = [origin.start_time, origin.end_time];
+        this.editingItem = [];
+        if (!item.id) {
+          this.experience.splice(idx, 1);
+        } else {
+          this.experience.splice(idx, 1, originCopy);
+        }
+      }
+    },
+    handleConfirm(item, idx) {
+      this.cnzz("签约", "签约页面+工作经历保存", "");
+      const origin = this.originExperience.slice(idx, idx + 1)[0];
+      // 编辑 item 时,item 对象中的 key 顺序均相同,可直接使用 JSON.stringify 做比较
+      let itemCopy = JSON.parse(JSON.stringify(item));
+      delete itemCopy["date"];
+      if (JSON.stringify(itemCopy) == JSON.stringify(origin)) {
+        this.$message.error("请修改后保存!");
+        return;
+      }
+      // if (item == origin) {
+      //   this.$message.error("请修改后保存!");
+      //   return;
+      // }
+      console.log(item.date);
+      if (!item.date) {
+        this.$message.error("请设置开始时间/结束时间!");
+        return;
+      } else if (
+        item.date &&
+        item.date[0] &&
+        item.date[1] &&
+        item.date[0] > item.date[1]
+      ) {
+        this.$message.error("请设置开始时间小于结束时间!");
+        return;
+      }
+      if (!item.company || !item.title) {
+        this.$message.error("请设置公司名称/职位!");
+        return;
+      }
+      if (!item.description || item.description.length < 60) {
+        this.$message.error("经历描述不少于60字符!");
+        return;
+      }
+      this.editingItem = [];
+      item.start_time = item.date[0];
+      item.end_time = item.date[1];
+      this.originExperience.splice(idx, 1, item);
+      this.onSubmit();
+    },
+    editItem(item, idx) {
+      this.rankDialog = false;
+      this.editingItem = [idx];
+    },
+    showRankDialog() {
+      if (this.experience.length < 1) {
+        this.$message.error("请先添加工作经历");
+        return false;
+      }
+      this.rankDialog = true;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.info {
+  header .el-icon-plus {
+    font-size: 18px;
+  }
+  .first,
+  .verify {
+    width: 70px;
+    height: 32px;
+    background: rgba(48, 142, 255, 1);
+    border-radius: 2px;
+    text-align: center;
+    font-size: 12px;
+    font-family: PingFangSC-Medium;
+    font-weight: 500;
+    color: rgba(255, 255, 255, 1);
+    line-height: 32px;
+  }
+  .verify {
+    background: #fff;
+    border-radius: 2px;
+    color: rgba(16, 185, 106, 1);
+    border: 1px solid rgba(16, 185, 106, 1);
+  }
+
+  .show {
+    padding: 23px 0 23px 0;
+    border-bottom: 1px solid #ebeef5;
+    word-break: break-all;
+    &:last-of-type {
+      border: 0;
+    }
+    h4 {
+      position: relative;
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      height: 44px;
+      font-size: 14px;
+      font-family: PingFangSC-Medium;
+      font-weight: 500;
+      color: #308eff;
+      line-height: 44px;
+      span {
+        margin-right: 20px;
+      }
+      button {
+        position: absolute;
+        right: 0;
+      }
+    }
+    p {
+      margin-top: 8px;
+      font-size: 14px;
+      font-family: PingFangSC-Regular;
+      font-weight: 400;
+      color: rgba(102, 102, 102, 1);
+      line-height: 24px;
+    }
+  }
+  .empty {
+    margin: 112px auto 104px;
+    font-size: 27px;
+    font-family: PingFangSC-Regular;
+    font-weight: 400;
+    text-align: center;
+    color: rgba(205, 205, 205, 1);
+    line-height: 38px;
+  }
+  .first-form {
+    margin-left: 40px;
+    .el-radio-group {
+      display: flex;
+      flex-direction: column;
+    }
+  }
+  .first-radio {
+    position: relative;
+    display: inline-flex;
+    justify-content: space-between;
+    align-items: center;
+    width: 350px;
+    margin: 0 20px 20px;
+    .des span {
+      margin-right: 40px;
+    }
+  }
+  .first-tips {
+    margin-top: 10px;
+    h6 {
+      font-size: 16px;
+      margin-bottom: 20px;
+    }
+    p {
+      font-size: 14px;
+      line-height: 1.4;
+    }
+  }
+}
+</style>

+ 12 - 0
pages/sign/new_v2.vue

@@ -203,6 +203,7 @@ export default {
 .sign-new-header {
   display: flex;
   justify-content: space-between;
+  align-items: center;
   border-bottom: 1px solid #f0f0f0;
   .sign-new-header-title {
     margin: 0;
@@ -229,4 +230,15 @@ export default {
     }
   }
 }
+
+.sign-new-form-footer {
+  display: flex;
+}
+.sign-new-form-tips {
+  flex: 1;
+}
+.sign-new-btn-area {
+  margin-top: 24px;
+  display: flex;
+}
 </style>