<template>
  <div class="app-container">
    <el-card shadow="never">
      <el-form ref="queryForm" :model="queryParams" size="small" :inline="true">
        <el-form-item prop="projectName">
          <template slot="label">{{ cpT("queryProjectName") }}</template>
          <el-input
            v-model="queryParams.projectName"
            :placeholder="cpT('queryProjectNamePh')"
            clearable
            style="width: 220px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item prop="projectType">
          <template slot="label">{{ cpT("queryProjectType") }}</template>
          <el-select v-model="queryParams.projectType" :placeholder="cpCommon('pleaseSelect')" clearable style="width: 200px">
            <el-option v-for="item in projectTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item prop="implYear">
          <template slot="label">{{ cpT("queryImplYear") }}</template>
          <el-select v-model="queryParams.implYear" :placeholder="cpCommon('pleaseSelect')" clearable style="width: 140px">
            <el-option v-for="y in yearOptions" :key="'q-' + y" :label="String(y)" :value="y" />
          </el-select>
        </el-form-item>
        <el-form-item prop="publishStatus">
          <template slot="label">{{ cpT("queryPublishStatus") }}</template>
          <el-select v-model="queryParams.publishStatus" :placeholder="cpCommon('pleaseSelect')" clearable style="width: 140px">
            <el-option :label="$t('commonProsperity.status.unpublished')" :value="0" />
            <el-option :label="$t('commonProsperity.status.published')" :value="1" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ cpCommon("search") }}</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ cpCommon("reset") }}</el-button>
          <el-button
            v-hasPermi="['commonProsperity:project:add']"
            type="primary"
            plain
            icon="el-icon-plus"
            size="mini"
            @click="handleAdd"
          >{{ cpCommon("add") }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <br />

    <el-card shadow="never">
      <el-table v-loading="loading" :data="tableList" border>
        <el-table-column :label="cpT('colProjectName')" prop="projectName" align="center" min-width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="cpT('colProjectType')" align="center" min-width="160">
          <template slot-scope="scope">
            <span>{{ typeLabel(scope.row.projectType) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="cpT('colIntro')" prop="introduction" align="center" min-width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="cpT('colImplYear')" prop="implYear" align="center" width="100" />
        <el-table-column :label="cpT('colOpImageCount')" align="center" width="88">
          <template slot-scope="scope">
            <span>{{ scope.row.opImageCount != null ? scope.row.opImageCount + cpT("opImageUnit") : $t("commonProsperity.status.dash") }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="cpT('colCover')" align="center" width="88">
          <template slot-scope="scope">
            <image-preview v-if="scope.row.coverFileUrl" :src="scope.row.coverFileUrl" :width="48" :height="48" />
            <span v-else>{{ $t("commonProsperity.status.dash") }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="cpCommon('colShelf')" align="center" width="92">
          <template slot-scope="scope">
            <span>{{ publishStatusText(scope.row.publishStatus) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="cpCommon('colPub')" align="center" width="110">
          <template slot-scope="scope">
            <span>{{ scope.row.publishTime ? parseTime(scope.row.publishTime, "{y}-{m}-{d}") : $t("commonProsperity.status.dash") }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="cpCommon('colCreate')" align="center" width="160">
          <template slot-scope="scope">
            <span>{{ scope.row.createTime ? parseTime(scope.row.createTime) : $t("commonProsperity.status.dash") }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="cpCommon('colOp')" align="center" class-name="small-padding fixed-width" width="280">
          <template slot-scope="scope">
            <el-button v-hasPermi="['commonProsperity:project:query']" type="text" size="mini" @click="handleView(scope.row)">{{ cpCommon("view") }}</el-button>
            <el-button
              v-hasPermi="['commonProsperity:project:edit']"
              v-if="canEdit(scope.row)"
              type="text"
              size="mini"
              @click="handleEdit(scope.row)"
            >{{ cpCommon("edit") }}</el-button>
            <el-button
              v-hasPermi="['commonProsperity:project:remove']"
              v-if="canDelete(scope.row)"
              type="text"
              size="mini"
              @click="handleDelete(scope.row)"
            >{{ cpCommon("delete") }}</el-button>
            <el-button
              v-hasPermi="['commonProsperity:project:publish']"
              v-if="canPublish(scope.row)"
              type="text"
              size="mini"
              @click="handlePublish(scope.row)"
            >{{ cpCommon("publish") }}</el-button>
            <el-button
              v-hasPermi="['commonProsperity:project:offline']"
              v-if="canOffline(scope.row)"
              type="text"
              size="mini"
              @click="handleOffline(scope.row)"
            >{{ cpCommon("offline") }}</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>

    <el-dialog :title="dialogTitle" :visible.sync="open" width="720px" append-to-body @close="cancel">
      <el-form :key="formKey" ref="form" :model="form" label-width="130px">
        <el-form-item prop="projectName" :rules="formRules.projectName">
          <template slot="label">{{ cpT("formProjectName") }}</template>
          <el-input
            v-model="form.projectName"
            type="textarea"
            :rows="2"
            :placeholder="cpT('phProjectName')"
            maxlength="64"
            show-word-limit
          />
        </el-form-item>
        <el-form-item prop="projectType" :rules="formRules.projectType">
          <template slot="label">{{ cpT("formProjectType") }}</template>
          <el-select v-model="form.projectType" :placeholder="cpCommon('pleaseSelect')" style="width: 100%">
            <el-option v-for="item in projectTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item prop="introduction" :rules="formRules.introduction">
          <template slot="label">{{ cpT("formIntro") }}</template>
          <el-input v-model="form.introduction" type="textarea" :rows="2" :placeholder="cpT('phIntro')" maxlength="50" show-word-limit />
        </el-form-item>
        <el-form-item prop="projectContent" :rules="formRules.projectContent">
          <template slot="label">{{ cpT("formContent") }}</template>
          <el-input v-model="form.projectContent" type="textarea" :rows="4" :placeholder="cpT('phContent')" maxlength="500" show-word-limit />
        </el-form-item>
        <el-form-item prop="investmentAmount" :rules="formRules.investmentAmount">
          <template slot="label">{{ cpT("formInvestmentAmount") }}</template>
          <el-input-number
            v-model="form.investmentAmount"
            :min="0"
            :precision="2"
            :controls="false"
            style="width: 220px"
          />
          <span class="form-unit">{{ cpCommon("unitWanYuan") }}</span>
        </el-form-item>
        <el-form-item prop="implYear" :rules="formRules.implYear">
          <template slot="label">{{ cpT("formImplYear") }}</template>
          <el-select v-model="form.implYear" :placeholder="cpCommon('pleaseSelect')" style="width: 220px">
            <el-option v-for="y in formYearOptions" :key="'f-' + y" :label="String(y)" :value="y" />
          </el-select>
        </el-form-item>
        <el-form-item prop="implStatus" :rules="formRules.implStatus">
          <template slot="label">{{ cpT("formImplStatus") }}</template>
          <el-input v-model="form.implStatus" type="textarea" :rows="3" :placeholder="cpT('phImplStatus')" maxlength="500" show-word-limit />
        </el-form-item>
        <el-form-item prop="operationImages">
          <template slot="label">{{ cpT("formOpImages") }}</template>
          <el-upload
            list-type="picture-card"
            :class="{ hide: hideOpImageUpload }"
            :action="uploadAction"
            :headers="uploadHeaders"
            :before-upload="beforeOpImageUpload"
            :on-success="handleOpImageUploadSuccess"
            :on-error="handleUploadHttpError"
            :on-remove="handleOpImageRemove"
            :limit="3"
            :file-list="opImageFileList"
            :disabled="dialogEdit && !canEditUploadRow"
          >
            <i class="el-icon-plus" />
          </el-upload>
          <div class="el-upload__tip">{{ cpCommon("tipOpImages") }}</div>
        </el-form-item>
        <el-form-item prop="videoFilePath">
          <template slot="label">{{ cpT("formVideo") }}</template>
          <el-upload
            class="upload-file-uploader"
            :action="uploadAction"
            :headers="uploadHeaders"
            :before-upload="beforeVideoUpload"
            :on-success="handleVideoUploadSuccess"
            :on-error="handleUploadHttpError"
            :show-file-list="false"
            :disabled="dialogEdit && !canEditUploadRow"
          >
            <el-button size="mini" type="primary" :disabled="dialogEdit && !canEditUploadRow">{{ cpCommon("pickFile") }}</el-button>
          </el-upload>
          <div class="el-upload__tip">{{ cpCommon("tipVideo") }}</div>
          <ul v-if="form.videoFilePath" class="upload-file-list el-upload-list el-upload-list--text">
            <li class="el-upload-list__item ele-upload-list__item-content">
              <el-link :href="form.videoFileUrl || '#'" :underline="false" target="_blank">
                <span class="el-icon-video-camera"> {{ videoDisplayName }} </span>
              </el-link>
              <div class="ele-upload-list__item-content-action">
                <el-link v-if="!(dialogEdit && !canEditUploadRow)" type="danger" :underline="false" @click="clearVideo">{{ cpCommon("del") }}</el-link>
              </div>
            </li>
          </ul>
        </el-form-item>
        <el-form-item prop="coverFilePath">
          <template slot="label">{{ cpT("formCover") }}</template>
          <el-upload
            list-type="picture-card"
            :class="{ hide: hideCoverUpload }"
            :action="uploadAction"
            :headers="uploadHeaders"
            :before-upload="beforeCoverUpload"
            :on-success="handleCoverUploadSuccess"
            :on-error="handleUploadHttpError"
            :on-remove="handleCoverRemove"
            :limit="1"
            :file-list="coverFileList"
            :disabled="dialogEdit && !canEditUploadRow"
          >
            <i class="el-icon-plus" />
          </el-upload>
          <div class="el-upload__tip">{{ cpCommon("tipCover") }}</div>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">{{ cpCommon("ok") }}</el-button>
        <el-button @click="cancel">{{ cpCommon("cancel") }}</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="cpCommon('viewTitle')" :visible.sync="viewOpen" width="680px" append-to-body>
      <el-form label-width="130px" size="small">
        <el-form-item :label="cpT('formProjectName')">
          <span>{{ viewRow.projectName }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formProjectType')">
          <span>{{ typeLabel(viewRow.projectType) }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formIntro')">
          <span>{{ viewRow.introduction || $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formContent')">
          <span class="view-content-text">{{ viewRow.projectContent || $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formInvestmentAmount')">
          <span>{{ investmentAmountText(viewRow.investmentAmount) }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formImplYear')">
          <span>{{ viewRow.implYear != null ? viewRow.implYear : $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formImplStatus')">
          <span class="view-content-text">{{ viewRow.implStatus || $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpT('viewOpImages')">
          <template v-if="viewOpImages.length">
            <image-preview
              v-for="(img, idx) in viewOpImages"
              :key="idx"
              :src="img.fileUrl"
              :width="80"
              :height="80"
              style="margin-right: 8px"
            />
          </template>
          <span v-else>{{ $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formVideo')">
          <el-link v-if="viewRow.videoFileUrl" type="primary" :href="viewRow.videoFileUrl" target="_blank">{{ cpCommon("view") }}</el-link>
          <span v-else>{{ $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpT('formCover')">
          <image-preview v-if="viewRow.coverFileUrl" :src="viewRow.coverFileUrl" :width="200" :height="120" />
          <span v-else>{{ $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpCommon('colShelf')">
          <span>{{ publishStatusText(viewRow.publishStatus) }}</span>
        </el-form-item>
        <el-form-item :label="cpCommon('viewPubTime')">
          <span>{{ viewRow.publishTime ? parseTime(viewRow.publishTime) : $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
        <el-form-item :label="cpCommon('viewOfflineTime')">
          <span>{{ viewRow.offlineTime ? parseTime(viewRow.offlineTime) : $t("commonProsperity.status.dash") }}</span>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="viewOpen = false">{{ cpCommon("close") }}</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from "@/utils/auth"
import commonProsperityLocaleMixin from "@/mixins/commonProsperityLocaleMixin"
import {
  listCommonProsperityProject,
  getCommonProsperityProject,
  addCommonProsperityProject,
  updateCommonProsperityProject,
  delCommonProsperityProject,
  publishCommonProsperityProject,
  offlineCommonProsperityProject
} from "@/api/commonProsperity/project"

const PUBLISH_STATUS = { UNPUBLISHED: 0, PUBLISHED: 1 }
const MAX_OP_IMAGES = 3

export default {
  name: "CommonProsperityProject",
  mixins: [commonProsperityLocaleMixin],
  data() {
    return {
      cpNs: "project",
      loading: false,
      open: false,
      viewOpen: false,
      viewRow: {},
      dialogEdit: false,
      canEditUploadRow: true,
      formKey: 0,
      total: 0,
      tableList: [],
      queryParams: {
        pageNum: 1,
        pageSize: 20,
        projectName: undefined,
        projectType: undefined,
        implYear: undefined,
        publishStatus: undefined
      },
      form: {},
      yearOptions: [],
      formYearOptions: [],
      /** 运营图片 el-upload 展示列表 */
      opImageFileList: [],
      imageFileExts: ["jpg", "jpeg", "png"],
      videoFileExts: ["mp4"],
      videoDisplayName: "video.mp4"
    }
  },
  computed: {
    dialogTitle() {
      return this.dialogEdit ? this.cpT("dialogEdit") : this.cpT("dialogAdd")
    },
    projectTypeOptions() {
      return [1, 2, 3].map((value) => ({ label: this.cpT("type" + value), value }))
    },
    formRules() {
      return {
        projectName: [
          { required: true, message: this.cpT("ruleProjectNameRequired"), trigger: "blur" },
          { min: 1, max: 64, message: this.cpCommon("ruleLen120"), trigger: "blur" }
        ],
        projectType: [{ required: true, message: this.cpT("ruleProjectTypeRequired"), trigger: "change" }],
        introduction: [{ max: 50, message: this.cpCommon("ruleLen50Optional"), trigger: "blur" }],
        projectContent: [{ max: 500, message: this.cpCommon("ruleLen500Optional"), trigger: "blur" }],
        investmentAmount: [{ validator: this.validateInvestmentAmount, trigger: "blur" }],
        implYear: [{ required: true, message: this.cpT("ruleImplYearRequired"), trigger: "change" }],
        implStatus: [{ max: 500, message: this.cpCommon("ruleLen500Optional"), trigger: "blur" }]
      }
    },
    uploadAction() {
      return process.env.VUE_APP_BASE_API + "/common/upload"
    },
    uploadHeaders() {
      return { Authorization: "Bearer " + getToken() }
    },
    coverFileList() {
      if (!this.form.coverFileUrl) {
        return []
      }
      return [{ name: "cover", url: this.form.coverFileUrl }]
    },
    hideCoverUpload() {
      return !!(this.form.coverFilePath || this.form.coverFileUrl)
    },
    hideOpImageUpload() {
      return this.opImageFileList.length >= MAX_OP_IMAGES
    },
    viewOpImages() {
      const list = this.viewRow.operationImages || []
      return [...list].sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
    }
  },
  created() {
    this.buildYearOptions()
    this.getList()
  },
  methods: {
    buildYearOptions() {
      const current = new Date().getFullYear()
      const years = []
      for (let y = current; y >= current - 4; y--) {
        years.push(y)
      }
      this.yearOptions = years
      this.resetFormYearOptions()
    },
    // 新增/编辑：实施年限仅近 5 年（含当年，共 5 个自然年）
    resetFormYearOptions(extraYear) {
      const current = new Date().getFullYear()
      const years = []
      for (let y = current; y >= current - 4; y--) {
        years.push(y)
      }
      if (extraYear != null && !years.includes(extraYear)) {
        years.push(extraYear)
        years.sort((a, b) => b - a)
      }
      this.formYearOptions = years
    },
    typeLabel(val) {
      const item = this.projectTypeOptions.find((o) => o.value === val)
      return item ? item.label : ""
    },
    investmentAmountText(val) {
      if (val === null || val === undefined || val === "") {
        return this.$t("commonProsperity.status.dash")
      }
      return val + " " + this.cpCommon("unitWanYuan")
    },
    validateInvestmentAmount(rule, value, callback) {
      if (value === null || value === undefined || value === "") {
        callback()
        return
      }
      if (Number(value) < 0) {
        callback(new Error(this.cpCommon("ruleNonNegativeNumber")))
        return
      }
      callback()
    },
    canEdit(row) {
      return row.publishStatus === PUBLISH_STATUS.UNPUBLISHED
    },
    canPublish(row) {
      return row.publishStatus === PUBLISH_STATUS.UNPUBLISHED
    },
    canOffline(row) {
      return row.publishStatus === PUBLISH_STATUS.PUBLISHED
    },
    canDelete(row) {
      return row.publishStatus === PUBLISH_STATUS.UNPUBLISHED
    },
    getList() {
      this.loading = true
      listCommonProsperityProject(this.queryParams)
        .then((res) => {
          this.tableList = res.rows || []
          this.total = res.total != null ? res.total : 0
        })
        .finally(() => {
          this.loading = false
        })
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      this.queryParams.projectName = undefined
      this.queryParams.projectType = undefined
      this.queryParams.implYear = undefined
      this.queryParams.publishStatus = undefined
      this.resetForm("queryForm")
      this.handleQuery()
    },
    resetFormModel() {
      this.form = {
        id: undefined,
        projectName: undefined,
        projectType: undefined,
        introduction: undefined,
        projectContent: undefined,
        investmentAmount: undefined,
        implYear: new Date().getFullYear(),
        implStatus: undefined,
        videoFileUrl: undefined,
        videoFilePath: undefined,
        coverFileUrl: undefined,
        coverFilePath: undefined
      }
      this.opImageFileList = []
      this.videoDisplayName = "video.mp4"
    },
    syncOpImagesFromFileList() {
      this.form.operationImages = this.opImageFileList.map((f, index) => ({
        fileUrl: f.url,
        filePath: f.filePath,
        sortOrder: index + 1
      }))
    },
    fillOpImagesFromApi(images) {
      const sorted = [...(images || [])].sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
      this.opImageFileList = sorted.map((img, index) => ({
        name: "op-" + (index + 1),
        url: img.fileUrl,
        filePath: img.filePath,
        uid: "op-" + index
      }))
      this.syncOpImagesFromFileList()
    },
    handleAdd() {
      this.formKey += 1
      this.resetFormModel()
      this.resetFormYearOptions()
      this.dialogEdit = false
      this.canEditUploadRow = true
      this.open = true
      this.$nextTick(() => this.resetForm("form"))
    },
    handleEdit(row) {
      if (!this.canEdit(row)) {
        return
      }
      getCommonProsperityProject(row.id).then((res) => {
        const data = res.data || {}
        this.formKey += 1
        this.dialogEdit = true
        this.canEditUploadRow = data.publishStatus === PUBLISH_STATUS.UNPUBLISHED
        this.resetFormYearOptions(data.implYear)
        this.form = {
          id: data.id,
          projectName: data.projectName,
          projectType: data.projectType,
          introduction: data.introduction,
          projectContent: data.projectContent,
          investmentAmount: data.investmentAmount,
          implYear: data.implYear,
          implStatus: data.implStatus,
          videoFileUrl: data.videoFileUrl,
          videoFilePath: data.videoFilePath,
          coverFileUrl: data.coverFileUrl,
          coverFilePath: data.coverFilePath
        }
        this.videoDisplayName = data.videoFilePath ? data.videoFilePath.split("/").pop() : "video.mp4"
        this.fillOpImagesFromApi(data.operationImages)
        this.open = true
        this.$nextTick(() => {
          if (this.$refs.form) {
            this.$refs.form.clearValidate()
          }
        })
      })
    },
    handleView(row) {
      getCommonProsperityProject(row.id).then((res) => {
        this.viewRow = res.data || {}
        this.viewOpen = true
      })
    },
    handleDelete(row) {
      this.$modal
        .confirm(this.$t("commonProsperity.project.confirmDelete", { id: row.id }))
        .then(() => delCommonProsperityProject(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.cpCommon("msgDelOk"))
          this.getList()
        })
        .catch(() => {})
    },
    handlePublish(row) {
      this.$modal
        .confirm(this.cpT("confirmPublish"))
        .then(() => publishCommonProsperityProject(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.cpCommon("msgPubOk"))
          this.getList()
        })
        .catch(() => {})
    },
    handleOffline(row) {
      this.$modal
        .confirm(this.cpT("confirmOffline"))
        .then(() => offlineCommonProsperityProject(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.cpCommon("msgOffOk"))
          this.getList()
        })
        .catch(() => {})
    },
    extOf(fileName) {
      if (!fileName || fileName.lastIndexOf(".") < 0) {
        return ""
      }
      return fileName.slice(fileName.lastIndexOf(".") + 1).toLowerCase()
    },
    beforeOpImageUpload(file) {
      if (this.opImageFileList.length >= MAX_OP_IMAGES) {
        this.$modal.msgError(this.cpCommon("errOpImageMax"))
        return false
      }
      const ext = this.extOf(file.name)
      if (!this.imageFileExts.includes(ext)) {
        this.$modal.msgError(this.cpCommon("errOpImageFmt"))
        return false
      }
      if (file.name.includes(",")) {
        this.$modal.msgError(this.cpCommon("errComma"))
        return false
      }
      if (file.size / 1024 / 1024 >= 10) {
        this.$modal.msgError(this.cpCommon("errOpImageMb"))
        return false
      }
      this.$modal.loading(this.cpCommon("uploadingImg"))
      return true
    },
    handleOpImageUploadSuccess(res, file) {
      this.$modal.closeLoading()
      if (res.code === 200) {
        this.opImageFileList.push({
          name: file.name,
          url: res.url,
          filePath: res.fileName,
          uid: file.uid
        })
        this.syncOpImagesFromFileList()
      } else {
        this.$modal.msgError(res.msg || this.cpCommon("errUploadFail"))
      }
    },
    handleOpImageRemove(file) {
      const uid = file.uid
      this.opImageFileList = this.opImageFileList.filter((f) => f.uid !== uid)
      this.syncOpImagesFromFileList()
    },
    beforeVideoUpload(file) {
      const ext = this.extOf(file.name)
      if (!this.videoFileExts.includes(ext)) {
        this.$modal.msgError(this.cpCommon("errVideoFmt"))
        return false
      }
      if (file.name.includes(",")) {
        this.$modal.msgError(this.cpCommon("errComma"))
        return false
      }
      if (file.size / 1024 / 1024 >= 100) {
        this.$modal.msgError(this.cpCommon("errVideoMb"))
        return false
      }
      this.$modal.loading(this.cpCommon("uploadingFile"))
      return true
    },
    handleVideoUploadSuccess(res, file) {
      this.$modal.closeLoading()
      if (res.code === 200) {
        this.form.videoFileUrl = res.url
        this.form.videoFilePath = res.fileName
        this.videoDisplayName = res.originalFilename || file.name
      } else {
        this.$modal.msgError(res.msg || this.cpCommon("errUploadFail"))
      }
    },
    clearVideo() {
      this.form.videoFileUrl = undefined
      this.form.videoFilePath = undefined
      this.videoDisplayName = "video.mp4"
    },
    beforeCoverUpload(file) {
      const ext = this.extOf(file.name)
      if (!this.imageFileExts.includes(ext)) {
        this.$modal.msgError(this.cpCommon("errCoverFmt"))
        return false
      }
      if (file.name.includes(",")) {
        this.$modal.msgError(this.cpCommon("errComma"))
        return false
      }
      if (file.size / 1024 / 1024 >= 10) {
        this.$modal.msgError(this.cpCommon("errCoverMb"))
        return false
      }
      this.$modal.loading(this.cpCommon("uploadingImg"))
      return true
    },
    handleCoverUploadSuccess(res) {
      this.$modal.closeLoading()
      if (res.code === 200) {
        this.form.coverFileUrl = res.url
        this.form.coverFilePath = res.fileName
      } else {
        this.$modal.msgError(res.msg || this.cpCommon("errUploadFail"))
      }
    },
    handleCoverRemove() {
      this.form.coverFileUrl = undefined
      this.form.coverFilePath = undefined
    },
    handleUploadHttpError() {
      this.$modal.closeLoading()
      this.$modal.msgError(this.cpCommon("errUploadRetry"))
    },
    buildSubmitPayload() {
      this.syncOpImagesFromFileList()
      const intro = this.form.introduction != null ? String(this.form.introduction).trim() : ""
      const implStatus = this.form.implStatus != null ? String(this.form.implStatus).trim() : ""
      return {
        projectName: this.form.projectName,
        projectType: this.form.projectType,
        introduction: intro || undefined,
        projectContent: this.form.projectContent,
        investmentAmount: this.form.investmentAmount,
        implYear: this.form.implYear,
        implStatus: implStatus || undefined,
        operationImages: this.form.operationImages || [],
        videoFileUrl: this.form.videoFileUrl,
        videoFilePath: this.form.videoFilePath,
        coverFileUrl: this.form.coverFileUrl,
        coverFilePath: this.form.coverFilePath
      }
    },
    validateOpImagesBeforeSubmit() {
      const count = (this.opImageFileList || []).length
      if (count < 1 || count > MAX_OP_IMAGES) {
        this.$modal.msgError(this.cpCommon("errOpImageCount"))
        return false
      }
      return true
    },
    submitForm() {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        if (!this.validateOpImagesBeforeSubmit()) {
          return
        }
        const payload = this.buildSubmitPayload()
        if (this.dialogEdit) {
          payload.id = this.form.id
          updateCommonProsperityProject(payload).then(() => {
            this.$modal.msgSuccess(this.cpCommon("msgModOk"))
            this.open = false
            this.getList()
          })
        } else {
          addCommonProsperityProject(payload).then(() => {
            this.$modal.msgSuccess(this.cpCommon("msgAddOk"))
            this.open = false
            this.getList()
          })
        }
      })
    },
    cancel() {
      this.open = false
      this.resetFormModel()
    }
  }
}
</script>

<style scoped>
.upload-file-uploader {
  margin-bottom: 8px;
}
.upload-file-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
}
.upload-file-list .el-upload-list__item {
  border: 1px solid #e4e7ed;
  line-height: 2;
  padding: 0 8px;
}
.ele-upload-list__item-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.hide ::v-deep .el-upload--picture-card {
  display: none;
}
.view-content-text {
  white-space: pre-wrap;
  word-break: break-word;
}
.form-unit {
  margin-left: 8px;
  color: #606266;
}
</style>
