系统设置-签名-功能完成

main
ysn 6 days ago
parent 8f91b8a8c4
commit 8084ec42de
  1. 8
      src/api/login.js
  2. 199
      src/layout/components/ESignatureDialog.vue
  3. 8
      src/utils/auth.js

@ -88,4 +88,12 @@ export function postCommonCheckVersion(data) {
method: 'post',
data: data
})
}
// 更新签名
export function postUpdateOpsSignatureUpdate(data) {
return request({
url: '/users/ops/signature/update',
method: 'post',
data
})
}

@ -6,7 +6,7 @@
:show-close="true"
@close="handleClose"
@opened="initCanvas"
qappend-to-body
append-to-body
>
<el-form label-width="80px">
<el-form-item label="签名区域">
@ -40,13 +40,16 @@
ref="fileInput"
type="file"
accept="image/*"
class="file-input"
@change="handleFileChange"
style="display: none"
@change="handleFileSelect"
/>
</el-dialog>
</template>
<script>
import { postUpdateOpsSignatureUpdate } from "@/api/login";
import { uploadFile } from "@/utils/requestMinio";
import { setLoginInfo } from "@/utils/auth";
export default {
name: "ESignatureDialog",
data() {
@ -220,45 +223,100 @@ export default {
this.$refs.fileInput.click();
},
handleFileChange(e) {
const file = e.target.files[0];
if (file && this.ctx) {
//
async handleFileSelect(event) {
const file = event.target.files[0];
if (!file) return;
try {
await this.loadImageToCanvas(file);
} catch (error) {
console.error("图片加载失败:", error);
this.$modal.msgError("图片加载失败: " + error.message);
} finally {
//
event.target.value = "";
}
},
//
async loadImageToCanvas(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
const canvas = this.$refs.signatureCanvas;
const ctx = this.ctx;
//
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
//
const scale = Math.min(
canvas.width / img.width,
canvas.height / img.height,
1
);
ctx.clearRect(0, 0, canvas.width, canvas.height);
//
const scale = Math.min(canvas.width / img.width, canvas.height / img.height);
const x = (canvas.width - img.width * scale) / 2;
const y = (canvas.height - img.height * scale) / 2;
this.ctx.drawImage(
img,
x,
y,
img.width * scale,
img.height * scale
);
//
ctx.drawImage(img, x, y, img.width * scale, img.height * scale);
//
this.saveState();
resolve();
};
img.src = event.target.result;
img.onerror = () => reject(new Error("图片加载失败"));
img.src = e.target.result;
};
reader.onerror = () => reject(new Error("文件读取失败"));
reader.readAsDataURL(file);
}
// input
e.target.value = "";
});
},
// MinIO
async uploadAvatar(file) {
try {
// MinIO
await this.ensureMinioInitialized();
const config = this.$store.getters.config;
const bucket = config.MINIO_BUCKET_AVATAR || "remote-avatar-test";
const timestamp = Date.now();
const ext = file.name.split(".").pop() || "png";
const fileName = `${timestamp}.${ext}`;
const objectName = `head_portrait/${fileName}`;
console.log(
`Uploading avatar to bucket: ${bucket}, object: ${objectName}`
);
// 使 MinIO
const result = await uploadFile(
bucket,
objectName,
file,
{},
(percent) => {}
);
console.log("MinIO 上传成功:", result);
let avatar = config.MINIO_BUCKET_AVATAR + "/" + result.objectName;
//
await postUpdateOpsSignatureUpdate({
//
signature: avatar,
//
sign_hash: avatar,
});
//
submit() {
} catch (error) {
throw error;
}
},
// MinIO
async ensureMinioInitialized() {
const config = this.$store.getters.config;
if (!config || !config.MINIO_ENDPOINT) {
console.log("MinIO config not loaded, fetching...");
await this.$store.dispatch("GetNetConfig");
}
},
async submit() {
const canvas = this.$refs.signatureCanvas;
if (!canvas || !this.ctx) return;
@ -282,10 +340,85 @@ export default {
return;
}
this.signatureData = canvas.toDataURL("image/png");
this.$message.success("签名上传成功");
this.$emit("submit", this.signatureData);
this.handleClose();
try {
// blob
const blob = await new Promise((resolve) => {
canvas.toBlob(resolve, "image/png");
});
//
await this.uploadSignatureToServer(blob);
this.$message.success("签名上传成功");
this.$emit("submit", canvas.toDataURL("image/png"));
this.handleClose();
} catch (error) {
console.error("签名上传失败:", error);
this.$message.error("签名上传失败: " + error.message);
}
},
//
async uploadSignatureToServer(blob) {
// MinIO
await this.ensureMinioInitialized();
const config = this.$store.getters.config;
// MINIO_BUCKET_KERNEL/esign/_esign_.png
const bucket = config.MINIO_BUCKET_KERNEL || "remote-kernel-test";
const loginInfo = this.$store.state.user.loginInfo;
const username = loginInfo?.username || "unknown";
const timestamp = Date.now();
const objectName = `esign/${username}_esign_${timestamp}.png`;
console.log(`Uploading signature to bucket: ${bucket}, object: ${objectName}`);
// 使 MinIO
const result = await uploadFile(
bucket,
objectName,
blob,
{},
(percent) => {}
);
console.log("MinIO 上传成功:", result);
//
const signature = `${bucket}/${result.objectName}`;
//
const signHash = await this.calculateFileHash(blob);
//
await postUpdateOpsSignatureUpdate({
signature: signature,
sign_hash: signHash,
});
// loginInfo
this.updateLoginInfoSignature(signature);
},
// loginInfo
updateLoginInfoSignature(signature) {
const loginInfo = { ...this.$store.state.user.loginInfo };
loginInfo.signature = signature;
// Vuex store
this.$store.commit('SET_LOGIN_INFO', loginInfo);
//
try {
setLoginInfo(loginInfo);
} catch (e) {
console.error("更新本地存储失败:", e);
}
},
// SHA-256
async calculateFileHash(blob) {
const arrayBuffer = await blob.arrayBuffer();
const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
return hashHex;
},
handleClose() {

@ -5,14 +5,16 @@ const TokenKey = 'utalk-token'
export function getToken() {
return Cookies.get(TokenKey)
}
// auth.js 修改
export function getLoginInfo() {
return Cookies.get('loginInfo')
const info = Cookies.get('loginInfo')
return info ? JSON.parse(info) : null // 添加反序列化
}
export function setToken(token) {
return Cookies.set(TokenKey, token, { expires: 7 })
return Cookies.set(TokenKey, token)
}
export function setLoginInfo(loginInfo) {
return Cookies.set('loginInfo', loginInfo, { expires: 7 })
return Cookies.set('loginInfo', JSON.stringify(loginInfo)) // 添加序列化
}
export function removeToken() {

Loading…
Cancel
Save